Spring注解学习_生命周期2_BeanPostProcessor

  1. 实现BeanPostProcessor
  2. BeanPostProcessor原理
  3. Spring底层对BeanPostProcessor的使用:
    1. ApplicationContextAwareProcessor
    2. InitDestroyAnnotationBeanPostProcessor

**BeanPostProcessor接口:**在bean初始化前后进行一些处理工作

这个接口需要实现两个方法:

  • postProcessBeforeInitialization( ):在创建好的Bean实例任何初始化之前调用
  • postProcessAfterInitialization( ):在创建好的Bean实例任何初始化之后调用

实现BeanPostProcessor

我们自行实现一个后置处理器:

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

还是用上一篇文章的配置类和测试类:

@Configuration
@Import(MyBeanPostProcessor.class)
public class MainConfig3 {
    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Car car(){
        return new Car();
    }
    @Bean
    public Cat cat(){
        return new Cat();
    }
    @Bean
    public Dog dog(){
        return new Dog();
    }
}

测试,发现对于所有注册的bean都生效了:

BeanPostProcessor原理

手动debug发现,Bean的自动装配,在AbstractAutowireCapableBeanFactory类中,经过了如下方法调用:

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) throws BeanCreationException {
    ...
    try {
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    ...
}
...
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args) throws BeanCreationException {
    ...
    try {
        //给bean进行属性复制
        populateBean(beanName, mbd, instanceWrapper);
        //进行初始化
        exposedObject = initializeBean(beanName, exposedObject, mbd);
    }
    ...
}
...

(有个值得注意的点:创建bean时,先调用populateBean给bean属性赋值,再initializeBean调用初始化方法。)

我们看看代码注释中对populateBean(beanName, mbd, instanceWrapper)的定义:

Populate the bean instance in the given BeanWrapper with the property values from the bean definition.(用bean定义中的属性值填充给定BeanWrapper中的bean实例。)

再看看对InitializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd)的定义:

Initialize the given bean instance, applying factory callbacks as well as init methods and bean post processors.

Called from {@link #createBean} for traditionally defined beans, and from {@link #initializeBean} for existing bean instances.(初始化给定的bean实例,应用工厂回调以及init方法和bean后处理器。

从{@link #createBean}为传统定义的bean调用,从{@link #initializeBean}为现有的bean实例调用。)

然后直接看InitializeBean源码:

调用initializeBean方法:

进入applyBeanPostProcessorsBeforeInitialization方法:

而后置处理器则为我们之前自行实现并注册的MyBeanPostProcessor,里面重写的方法将被用到。

//在bean初始化之前调用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("postProcessBeforeInitialization..."+beanName);
    return bean;
}

故不难得知initializeBean处理流程大致为:

initializeBean{

​ 1️⃣ applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)

​ 2️⃣ invokeInitMethods(beanName, wrappedBean, mbd);

​ 3️⃣ applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);

}

  • applyBeanPostProcessorsBeforeInitialization会遍历容器中所有的BeanPostProcessor,逐个执行后置处理器中实现的 postProcessBeforeInitialization() 方法,一旦返回null,跳出循环,不会再执行后面的postProcessBeforeInitialization() 方法。

  • 然后再执行初始化方法:invokeInitMethods(beanName, wrappedBean, mbd);

  • 最后执行applyBeanPostProcessorsAfterInitialization 方法,其过程与1️⃣大体相同。

Spring底层对BeanPostProcessor的使用:

bean赋值,注入其他组件,@Autowired,bean声明周期的注解功能,@Async等等,都用到了BeanPostProcessor。可在IDEA中用快捷键Ctrl+Alt+B查看其具体实现类。

ApplicationContextAwareProcessor

ApplicationContextAwareProcessor也实现了BeanPostProcessor接口,它的作用是帮我们**向组件(Compenent)中注入IOC容器(ApplicationContext)**依赖。另外,要想通过这种方式在组件中注入IOC容器,我们需先让组件实现ApplicationContextAware接口。这里分析一下原理:

直接看ApplicationContextAwareProcessor的源码:

image-20200330163923886

首先它自己就通过构造注入得到了IOC容器依赖:

/**
 * Create a new ApplicationContextAwareProcessor for the given context.
 */
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
    this.applicationContext = applicationContext;
    this.embeddedValueResolver = new 
        EmbeddedValueResolver(applicationContext.getBeanFactory());
}

然后由于实现了BeanPostProcessor接口,在初始化前会调用postProcessBeforeInitialization方法:

image-20200330164847960

查看 InvokeAwareInterfaces() 方法的源码:

image-20200330165300341

InitDestroyAnnotationBeanPostProcessor

类似的,InitDestroyAnnotationBeanPostProcessor类也通过实现BeanPostProcessor接口来完成对bean的所有标注的初始化和销毁方法调用。对于标注了@PostConstruct,@PreDestroy等注解的bean:

public class Dog{
    //对象创建并赋值之后调用
    @PostConstruct
    public void init(){
        System.out.println("dog @PostConstruct...");
    }

    //容器销毁对象之前调用
    @PreDestroy
    public void destroy(){
        System.out.println("dog @PreDestroy...");
    }
}

先看这个类如何实现postProcessBeforeInitialization(初始化前处理):

image-20200330172243446

调用findLifecycleMetadata(bean.getClass()) 找到生命周期元数据(其中包括我们标注@PostConstruct和@PreDestroy的初始化、销毁方法)找到之后调用invokeInitMethod执行初始化方法↓

image-20200330172537270

对于@PreDestroy标注的销毁方法调用,也是类似的处理思路

image-20200330172854236

image-20200330172935442


我们经常用到的**@Autowired**,它的处理类AutowiredAnnotationBeanPostProcessor也是实现了BeanPostProcessor,以后写@Autowired时再深入分析。


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,邮件至 708801794@qq.com

文章标题:Spring注解学习_生命周期2_BeanPostProcessor

文章字数:1.1k

本文作者:梅罢葛

发布时间:2020-03-30, 01:51:10

最后更新:2020-03-30, 17:37:53

原始链接:https://qiurungeng.github.io/2020/03/30/Spring%E6%B3%A8%E8%A7%A3%E5%AD%A6%E4%B9%A0-%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F2-BeanPostProcessor/
目录
×

喜欢就点赞,疼爱就打赏