欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【Spring源码】 BeanPostProcessor底层原理分析

程序员文章站 2024-01-29 13:15:04
...

1.Spring中bean的生命周期

  • 今天不聊那么复杂,其实bean的生命周期就这四步:实例化、初始化、使用、销毁
    【Spring源码】 BeanPostProcessor底层原理分析

2.Spring注解开发指定初始化和销毁的方式

  • 大概以下四种方式:

2.1 @Bean指定init-method和destroy-method

  • 举例Demo:
  • bean实体类
/**
 * bean的生命周期
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
public class Food {

    public Food(){
        System.out.println("food constructor");
    }

    public void init(){
        System.out.println("food init");
    }

    public void detory(){
        System.out.println("food detory");
    }
}

  • 配置类
@Configuration
public class ConfigOfLifeCycle {

    @Bean(initMethod = "init",destroyMethod = "detory")
    public Food food(){
        return new Food();
    }
}
  • 测试用例:
/**
 * IOC生命周期测试
 * 注意:单实例bean测试,多实例bean容器创建完之后就不再管了
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
public class IOCTest_LifeCycle {

    @Test
    public void test01(){
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class);
        System.out.println("容器加载完成");
        applicationContext.close();
    }
}
  • 运行结果:
food constructor
food init
容器加载完成
food detory

2.2 通过让Bean实现InitializingBean(定义初始化逻辑)DisposableBean(定义销毁逻辑)

  • 举例Demo:
  • bean实体类
/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
@Component
public class Dog implements InitializingBean, DisposableBean {

    public Dog(){
        System.out.println("dog constructor");
    }
    @Override
    public void destroy() throws Exception {
        System.out.println("dog destroy");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("dog afterPropertiesSet");
    }
}

  • 配置类不变,只加上包扫描注解@ComponentScan(“com.code.bean”)
@ComponentScan("com.code.bean")
public class ConfigOfLifeCycle {...}
  • 测试用例不变,运行结果
dog constructor
dog afterPropertiesSet
food constructor
food init
容器加载完成
food detory
dog destroy

2.3 可以使用JSR250:@PostConstruct,@PreDestroy注解

  • @PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法

  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

  • 举例Demo:

  • bean实体类:

/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
@Component
public class Pig {

    public Pig(){
        System.out.println("Pig constructor");
    }

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

    @PreDestroy
    public void detory(){
        System.out.println("Pig PreDestroy");
    }
}

  • 配置类与测试用例不变,运行结果:
dog constructor
dog afterPropertiesSet
Pig constructor
Pig PostConstruct
food constructor
food init
容器加载完成
food detory
Pig PreDestroy
dog destroy

Process finished with exit code 0

2.4 主角出场,创建BeanPostProcessor接口实现类

  • BeanPostProcessor接口:bean的后置处理器,其有两个方法
  • postProcessBeforeInitialization:在初始化之前工作
  • postProcessAfterInitialization:在初始化之后工作
  • 举例Demo:

/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {



    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {


        System.out.println("postProcessBeforeInitialization  "+s);
        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {

        System.out.println("postProcessAfterInitialization  "+s);
        return o;
    }
}
  • 配置类与测试用例不变,运行结果:
dog constructor
postProcessBeforeInitialization  dog
dog afterPropertiesSet
postProcessAfterInitialization  dog
Pig constructor
postProcessBeforeInitialization  pig
Pig PostConstruct
postProcessAfterInitialization  pig
food constructor
postProcessBeforeInitialization  food
food init
postProcessAfterInitialization  food
容器加载完成
food detory
Pig PreDestroy
dog destroy

Process finished with exit code 0

3.BeanPostProcessor底层原理分析

  • 这里我们从测试用例当做入口,一点一点Debug进去:
    【Spring源码】 BeanPostProcessor底层原理分析
  • new AnnotationConfigApplicationContext(ConfigOfLifeCycle.class)创建一个IOC容器,点进去:
    【Spring源码】 BeanPostProcessor底层原理分析
  • 熟悉Spring源码的对refresh()这个方法应该不会陌生,spring的核心,在这个方法里,Spring完成了容器的初始化
  • 这个方法很重要,我就不截图了,直接把 源码搞下来一行一行添加注释,这样比较清楚:
public void refresh() throws BeansException, IllegalStateException {
        Object var1 = this.startupShutdownMonitor;
        synchronized(this.startupShutdownMonitor) {
            //容器刷新前的准备,设置上下文状态,获取属性,验证必要的属性等
            this.prepareRefresh();
            //获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等
            ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
            this.prepareBeanFactory(beanFactory);

            try {
               //配置标准的beanFactory,设置ClassLoader,设置SpEL表达式解析器,添加忽略注入的接口,添加bean,添加bean后置处理器等
                this.postProcessBeanFactory(beanFactory);
                //模板方法,此时,所有的beanDefinition已经加载,但是还没有实例化。
                //允许在子类中对beanFactory进行扩展处理。比如添加ware相关接口自动装配设置,添加后置处理器等,是子类扩展 
                //prepareBeanFactory(beanFactory)的方法。
                // 实例化并调用所有注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor的bean,在beanFactory标准初始化之后执行)。
                this.invokeBeanFactoryPostProcessors(beanFactory);
                //实例化和注册beanFactory中扩展了BeanPostProcessor的bean。
                this.registerBeanPostProcessors(beanFactory);
                //初始化国际化工具类MessageSource
                this.initMessageSource();
                //初始化事件广播器
                this.initApplicationEventMulticaster();
                //模板方法,在容器刷新的时候可以自定义逻辑,不同的Spring容器做不同的事情。
                this.onRefresh();
                //注册监听器,广播early application events
                this.registerListeners();
                //实例化所有剩余的(非懒加载)单例
                //实例化的过程各种BeanPostProcessor开始起作用。
                this.finishBeanFactoryInitialization(beanFactory);
                //refresh做完之后需要做的其他事情。
                //清除上下文资源缓存(如扫描中的ASM元数据)
                //初始化上下文的生命周期处理器,并刷新(找出Spring容器中实现了Lifecycle接口的bean并执行start()方法)。
                //发布ContextRefreshedEvent事件告知对应的ApplicationListener进行响应的操作
                this.finishRefresh();
            } catch (BeansException var9) {
                if (this.logger.isWarnEnabled()) {
                    this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
                }

                this.destroyBeans();
                this.cancelRefresh(var9);
                throw var9;
            } finally {
                this.resetCommonCaches();
            }

        }
    }
  • 我们今天聊的是注解开发和BeanPostProcessor底层原理,所以我们看的是 this.finishBeanFactoryInitialization(beanFactory);这行代码。
  • 打开这个方法:
    【Spring源码】 BeanPostProcessor底层原理分析
  • 一堆判断,直接看最后一行代码,跟进去:
    【Spring源码】 BeanPostProcessor底层原理分析
  • 然后走到这个方法的getBean()里:
    【Spring源码】 BeanPostProcessor底层原理分析
    【Spring源码】 BeanPostProcessor底层原理分析
  • 获取单实例的bean,获取不到就创建
    【Spring源码】 BeanPostProcessor底层原理分析
    【Spring源码】 BeanPostProcessor底层原理分析
    【Spring源码】 BeanPostProcessor底层原理分析
  • 开始初始化bean
    【Spring源码】 BeanPostProcessor底层原理分析
  • 关键点到了:
  • applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  • invokeInitMethods(beanName, wrappedBean, mbd);执行自定义初始化
  • applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  • 还记得BeanPostProcessor里的两个方法吗?
  •  postProcessBeforeInitialization:在初始化之前工作
    
  •  postProcessAfterInitialization:在初始化之后工作
    
  • 仔细对比上面两个方法看看,是不是悟出些什么
  • 我们来看看applyBeanPostProcessorsBeforeInitialization这个方法:
    【Spring源码】 BeanPostProcessor底层原理分析
  • 遍历执行容器内所有BeanPostProcessor接口实现类的postProcessBeforeInitialization方法。
  • 我们再来看invokeInitMethods方法
    【Spring源码】 BeanPostProcessor底层原理分析
  • 开始对bean初始化,看到我圈出的那个红框框吗?还记得InitializingBean接口吗?忘记的请看上面2.2
  • 最后看一下applyBeanPostProcessorsAfterInitialization:
    【Spring源码】 BeanPostProcessor底层原理分析
  • 一脉相承,不再赘述。

4.Spring中BeanPostProcessor的应用

  • 我们直接来看Spring中BeanPostProcessor的实现类
    【Spring源码】 BeanPostProcessor底层原理分析
  • 简单列举几个:

4.1 AsyncAnnotationBeanPostProcessor

  • 处理@Async注解,检测每个bean是否符合在类级别或者方法级别使用异步注解,如果使用了,则会使用一个AsyncAnnotationAdvisor包裹该bean,从而该bean上通过异步注解所定义的方法在调用时会被真正地异步调用起来。

4.2 AbstractBeanFactoryAwareAdvisingPostProcessor

  • 可以帮助我们往组件里面注入IOC容器,具体可以看下面Demo:
/**
 * todo
 *
 * @author wangjie
 * @version V1.0
 * @date 2020/1/6
 */
public class Car implements ApplicationContextAware {

    ApplicationContext applicationContext;

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

4.3 BeanValidationPostProcessor

  • 初始化前后的数据校验

4.4 InitDestroyAnnotationBeanPostProcessor

  • 处理@PostConstruct,@PreDestroy注解,这两个注解忘记做什么的可以往上翻看2.3

4.5 AutowiredAnnotationBeanPostProcessor

  • 处理@Autowired自动依赖注入,@Autowired做什么的不用我说了吧。。。

【完】
注:文章内所有测试用例源码:https://gitee.com/wjie2018/source-code.git