Spring的后置处理器BeanPostProcessor接口的执行流程

发布时间 2023-12-07 11:43:11作者: 残城碎梦

BeanPostProcessor的设计目标主要是提供一种扩展机制,让开发者可以在Spring Bean的初始化阶段进行自定义操作。这种设计理念主要体现了Spring的一种重要原则,即“开放封闭原则”。开放封闭原则强调软件实体(类、模块、函数等等)应该对于扩展是开放的,对于修改是封闭的。在这里,Spring容器对于Bean的创建、初始化、销毁等生命周期进行了管理,但同时开放了BeanPostProcessor这种扩展点,让开发者可以在不修改Spring源码的情况下,实现对Spring Bean生命周期的自定义操作,这种设计理念大大提升了Spring的灵活性和可扩展性。

BeanPostProcessor不是Spring Bean生命周期的一部分,但它是在Spring Bean生命周期中起重要作用的组件

BeanPostProcessor 接口定义了两个方法,postProcessBeforeInitialization和postProcessAfterInitialization:

  • postProcessBeforeInitialization方法会在任何bean初始化回调(如InitializingBean的afterPropertiesSet方法或者自定义的init-method)之前被调用。也就是说,这个方法会在bean的属性已经设置完毕,但还未进行初始化时被调用。
  • postProcessAfterInitialization方法在任何bean初始化回调(比如InitializingBean的afterPropertiesSet或者自定义的初始化方法)之后被调用。这个时候,bean的属性值已经被填充完毕。返回的bean实例可能是原始bean的一个包装。

整体的调用流程如下:

  • AbstractApplicationContext#refresh 核心方法入口
  • AbstractApplicationContext#finishBeanFactoryInitialization 初始化所有(非懒加载)单例bean
  • DefaultListableBeanFactory#preInstantiateSingletons 初始化所有(非懒加载)单例bean

  • AbstractBeanFactory#getBean 根据单例bean名称获取实例
  • AbstractBeanFactory#doGetBean 根据单例bean名称获取实例

(1)DefaultSingletonBeanRegistry#getSingleton 通过bean名称从单例缓存中获取单例对象(可能获取到的实现FactoryBean接口的对象)

(2)若从单例缓存中获取不到对象,则创建bean实例,创建完后也存在单例缓存中

  • AbstractAutowireCapableBeanFactory#createBean 创建bean实例
  • AbstractAutowireCapableBeanFactory#doCreateBean 创建bean实例

  • AbstractAutowireCapableBeanFactory#initializeBean 初始化bean

其中applyBeanPostProcessorsBeforeInitialization方法会调用所有实现了BeanPostProcessor接口的postProcessBeforeInitialization方法

invokeInitMethods方法调用所有实现InitializingBean接口的afterPropertiesSet方法以及自定义的初始化方法

applyBeanPostProcessorsAfterInitialization在初始化之后调用所有实现BeanPostProcessor接口的postProcessAfterInitialization方法

我们总结下BeanPostProcessor的源码上下文方法:

populateBean(beanName, mbd, instanceWrapper); // 给bean进行属性赋值
initializeBean(beanName, exposedObject, mbd)
{
    applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//bean的初始化前
    invokeInitMethods(beanName, wrappedBean, mbd); // 先执行InitializingBean接口的afterPropertiesSet方法和用户自定义的初始化
    applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//bean的初始化后
}