生命周期BeanPostProcessor(3)---Spring源码从入门到精通(九)

上篇文章主要介绍了Bean生命周期,bean生命周期:创建bean--->初始化init--->销毁destory,而初始化和销毁是可以用@Bean指定的,或者用@PostCoustruct@preDestory注解,或者用InitializingBean和DisposableBean接口都能指定调用的初始化和销毁方法:

Bean生命周期(2)---Spring源码从入门到精通(八)

这篇主要介绍BeanPostProcessor,在spring框架非常重要,里面有两个接口,一个是postProcessBeforeInitialization 和 postProcessAfterInitialization两个方法,顾名思义,前者在类初始化前调用,后者在类初始化之后调用。

下面主要分为三个部分:

1、BeanPostProcessor实用。

2、BeanPostProcessor源码解析。

3、Spring底层使用BeanPostProcessor。

1、BeanPostProcessor实用

先自定义类MyBeanPostProcessor实现接口,会重写里面的两个方法,可以打印出当前初始化的类。


/**
 * 自定义类实现beanPostProcessor接口,两个重写的方法在bean初始化前后调用。
 *
 * 初始化之前用populateBean()方法,给bean属性赋值
 * 初始化开始:
 * 「
 * applyBeanPostProcessorsBeforeInitialization()初始化之前调用的方法 , 接口BeanPostProcessor
 * invokeInitMethods()方法初始化 ,执行bean初始化
 * applyBeanPostProcessorsAfterInitialization()初始化之后调用的方法 , 接口BeanPostProcessor
 * 」
 *
 * @author keying
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(
            "postProcessBeforeInitialization.....Before..." + bean.getClass() + ",【beanName】=" + beanName);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(
            "postProcessAfterInitialization.....After..." + bean.getClass() + ",【beanName】=" + beanName);
        return bean;
    }
}

junitTest还和上篇文章一样不变,直接运行,为了方便理解,再贴一遍:

 @Test
    public void test() {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
            ConfigLifeCycle.class);
        System.out.println("容器创建完毕");
        //多实例情况下,需要获取组件,才会初始化,并且不会销毁
        //Object carObject = annotationConfigApplicationContext.getBean("car");

        //getDefinitionNames(annotationConfigApplicationContext);
        annotationConfigApplicationContext.close();
    }

控制台打印如下,我们创建的三个bean在初始化的前后都会打印:

2、BeanPostProcessor源码解析。

1、刚开始AnnotationConfigApplicationContext主要调用refresh()方法

2、点进去之后,refresh主要调用finishBeanFactoryInitialization方法,初始化所有单实例对象        3、点进去之后,调用下图的beanFactory.preInstantiateSingletons方法

4、初始化单实例 bean之后,点进去此方法,可以看到getBean方法5、点进getBean之后,可以看到下图方法,获取单实例,若获取不到,就会createBean创建对象并且返回。6、createBean里有个doCreateBean,点进此方法,里面有个populateBean方法作用是在初始化对象之前,给bean注入信息,bean名,工厂名,之后下面的initializeBean方法,后面的方法就是处理器的调用。

7、点进initializaBean方法可以看到,里面有三个方法,中间invokeInitMethods方法就是初始化bean,applyBeanPostProcessorsBeforeInitialization方法为初始化之前调用的,applyBeanPostProcessorsAfterInitialization方法为初始化之后调用的。8、点击applyBeanPostProcessorsBeforeInitialization方法,进入可以看到,遍历获取容器所有的beanPostProcessors,挨个执行beforeInitialization若返回为 null,则跳出for循环,不会执行后面的postBeforeBeforeInitialization方法。        

3、Spring底层使用BeanPostProcessor

可以传递ApplicationContext对象,用bean实现ApplicationContextAware方法,代码如下:

@Component
public class Cat implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    public Cat(){
        System.out.println("Cat...construct");
    }

    /**
     * construct 构造函数创建对象之后执行
     */
    @PostConstruct
    public void init(){
        System.out.println("cat ...PostConstruct.");
    }

    /**
     * 销毁之前调用
     */
    @PreDestroy
    public void destory(){
        System.out.println("cat ...PreDestroy");
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

源码如下,ApplicationContextAwareProcessor类就是集成了此接口,里面可以设置代码里的ApplicationContext。

BeanValidationPostProcessor类,作用在bean初始化前后进行效验,源码如下。

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;
    }

之前用的@PostConstruct,和@PreDestroy注解也是因为BeanPostProcessor才运行的,在InitDestroyAnnotationBeanPostProcessor类里,调用invokeInitMethods方法点进invokeInitmethods方法可以看到,会用反射调用element.invoke方法,找到对应的bean。

还有AutowiredAnnotationBeanPostProcessor类,就是在对象创建完之后,处理@Autowired注解获取到bean对象。

所有@Bean注入对象,其他方法注入组件,@Autowired,生命周期注解,@Async异步注解等等,都是基本BeanPostProcessor接口实现的。

简单总结:spring生命周期,主要为bean创建--->init初始化--->销毁,

单实例在容器加载完毕前,创建和初始化,多实例在获取bean的时候才会创建bean和初始化。@Bean注释可以指定init-method和destory-method来初始化和销毁,@PostConstruct注解和接口也可以实现,这些都基于BeanPostRrocessor接口,控制生命周期,并且实现此接口,可以在bean初始化前后处理事务。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后端从入门到精通

你的鼓励是我最大的动力~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值