Spring再次学习(4)

时隔一年多,在掌握了Spring、SpringBoot、SpringCloud之后

我再次回头,重新学习Spring框架

Bean的生命周期学习:

在传统的XML配置中,可以这样自定义初始化和销毁方法:

init-method="" destroy-method=""

注解方式的简单使用:

@Configuration
public class LifeCircleConfig {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
}
public class Car {
    public Car(){
        System.out.println("Construct Car!");
    }
    public void init(){
        System.out.println("Car init!");
    }
    public void destroy(){
        System.out.println("Car destroy!");
    }
}
public class LifeCircleTest {

    private static AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(LifeCircleConfig.class);

    @Test
    public void test(){
        applicationContext.close();
    }
}

注意:要有close方法,否则不会打印Car销毁方法

打印如下:

Construct Car!
Car init!
Car destroy!

这里默认的是单实例Bean

如果是多实例的话,按照以上的测试代码是不会打印的,因为多实例情况下,在获取Bean的情况下才会创建对象

而且在多例情况下,只会调用初始化和构造方法,不会调用销毁方法

以上测试代码只完成了初始化IOC容器,所以什么都不打印

实现Spring中接口方式:这时候不需要在@Bean中进行配置

public class Car implements InitializingBean, DisposableBean {

    public Car() {
        System.out.println("Construct Car!");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("Car init!");
    }

    public void destroy() {
        System.out.println("Car destroy!");
    }

}

使用Java原生注解:

public class Car {

    public Car() {
        System.out.println("Construct Car!");
    }

    @PostConstruct
    public void init() {
        System.out.println("Car init!");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("Car destroy!");
    }

}

使用Spring中Bean的后置处理器:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 初始化前调用
     */
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization " + bean + " " + beanName);
        return bean;
    }

    /**
     * 初始化后调用
     */
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization " + bean + " " + beanName);
        return bean;
    }
}
@Configuration
@ComponentScan("org.dreamtech.bean")
public class LifeCircleConfig {
    @Bean
    public Car car(){
        return new Car();
    }
}

测试后部分打印如下:

Construct Car!
postProcessBeforeInitialization [email protected] car
postProcessAfterInitialization [email protected] car

BeanPostProcessor原理:

查看这一段源码:

initializeBean(beanName, exposedObject, mbd)方法中:

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
            invokeInitMethods(beanName, wrappedBean, mbd);
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    (mbd != null ? mbd.getResourceDescription() : null),
                    beanName, "Invocation of init method failed", ex);
        }

        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

在invokeInitMethods初始化方法之前

调用了applyBeanPostProcessorsBeforeInitialization,也就是调用了所有PostProcessor的Before方法

在invokeInitMethods初始化方法之后

调用了applyBeanPostProcessorsAfterInitialization,也就是调用了所有PostProcessor的After方法

进入applyBeanPostProcessorsBeforeInitialization方法查看源码:

遍历所有的Processor,一旦返回null,就会跳出循环

    @Override
    public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException {

        Object result = existingBean;
        for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
            result = beanProcessor.postProcessBeforeInitialization(result, beanName);
            if (result == null) {
                return result;
            }
        }
        return result;
    }

在initializeBean方法之前,调用的是populateBean方法

作用:给属性赋值

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            if (exposedObject != null) {
                exposedObject = initializeBean(beanName, exposedObject, mbd);
            }
        }

所以:BeanPostProcessor是在Bean赋值之后,初始化的过程前后执行的

BeanPostProcessor在Spring底层的使用:

获取IOC容器的接口:

public interface ApplicationContextAware extends Aware {
    void setApplicationContext(ApplicationContext var1) throws BeansException;
}

而它就是基于BeanPostProcessor的,代码过长就不截取了

class ApplicationContextAwareProcessor implements BeanPostProcessor

或者是参数校验:也使用到了BeanPostProcessor

public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean

部分代码如下:

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!this.afterInitialization) {
            this.doValidate(bean);
        }

        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (this.afterInitialization) {
            this.doValidate(bean);
        }

        return bean;
    }

原文地址:https://www.cnblogs.com/xuyiqing/p/11307820.html

时间: 2024-08-30 14:38:09

Spring再次学习(4)的相关文章

Spring Batch学习笔记二

此系列博客皆为学习Spring Batch时的一些笔记: Spring Batch的架构 一个Batch Job是指一系列有序的Step的集合,它们作为预定义流程的一部分而被执行: Step代表一个自定义的工作单元,它是Job的主要构件块:每一个Step由三部分组成:ItemReader.ItemProcessor.ItemWriter:这三个部分将执行在每一条被处理的记录上,ItemReader读取每一条记录,然后传递给ItemProcessor处理,最后交给ItemWriter做持久化:It

Spring boot 学习笔记 - Hello world

Spring boot 学习笔记 - Hello world spring boot介绍: spring-boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的配置.通过这种方式,Boot致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者. Hello world 通过官网https://start.spring.io/

Spring Cloud学习--配置中心(Config)

Spring Cloud学习--配置中心(Config) 一 Spring Cloud Config简介 二 编写 Config Server 三 编写Config Client 四 使用refresh端点手动刷新配置 五 Spring Config Server与Eurelka配合使用 六 Config Server的高可用 一. Spring Cloud Config简介 微服务要实现集中管理微服务配置.不同环境不同配置.运行期间也可动态调整.配置修改后可以自动更新的需求,Spring Cl

Spring MVC 学习笔记(二):@RequestMapping用法详解

一.@RequestMapping 简介 在Spring MVC 中使用 @RequestMapping 来映射请求,也就是通过它来指定控制器可以处理哪些URL请求,相当于Servlet中在web.xml中配置 <servlet>     <servlet-name>servletName</servlet-name>     <servlet-class>ServletClass</servlet-class> </servlet>

spring cloud 学习(4) - hystrix 服务熔断处理

hystrix 是一个专用于服务熔断处理的开源项目,当依赖的服务方出现故障不可用时,hystrix有一个所谓的断路器,一但打开,就会直接拦截掉对故障服务的调用,从而防止故障进一步扩大(类似中电路中的跳闸,保护家用电器). 使用步骤:(仍然在之前的示例代码上加以改造) 一.添加hystrix依赖 compile 'org.springframework.cloud:spring-cloud-starter-hystrix' 二.在需要熔断的方法上添加注解 package com.cnblogs.y

Spring框架学习之IOC(一)

Spring框架学习之IOC 先前粗浅地学过Spring框架,但当时忙于考试及后期实习未将其记录,于是趁着最近还有几天的空闲时间,将其稍微整理一下,以备后期查看. Spring相关知识 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器.可单独使用,通常也与其他框架整合使用,例如SSH.SSM. IOC:控制反转 控制权由对象本身转向容器:由容器根据配置文件去创建实例并创建各个实例之间的依赖关系.等同于DI依赖注入 A

[Spring MVC]学习笔记--DispatcherServlet

在上一篇我们介绍了Servlet,这一篇主要来看一下MVC中用到的DispatcherServlet(继承自HttpServlet). 1. DispatcherServlet在web.xml中被声明. <web-app> <servlet> <servlet-name>example</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet&l

spring框架学习(二)依赖注入

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740835 ———————————————————————————————————————————— spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.接口注入不作要求,下面介绍前两种方式. 1,set注入 采用属性的set方法进行初始化,就成为set注入. 1)给普通字符类型赋值. [java] view plaincopyprint? pub

spring框架学习(一)

转自:http://blog.csdn.net/lishuangzhe7047/article/details/20740209 —————————————————————————————————————————————————— 1,什么是spring框架 spring是J2EE应用程序框架,是轻量级的IoC和AOP的容器框架,主要是针对javaBean的生命周期进行管理的轻量级容器,可以单独使用,也可以和Struts框架,ibatis框架等组合使用. 2,架构概述 1)IoC(Inversi