最近项目中使用到了一些bean生命周期的扩展接口,对各个接口实现类去实例化时的加载顺序产生了疑惑,项目中也有顺序的问题。所以梳理一下。
直接能百度到的bean声明周期的方法调用为:
1、Bean自身的方法:
这个包括了Bean本身调用的方法和通过配置文件中的init-method和destroy-method指定的方法
2、Bean级生命周期接口方法:
这个包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean这些接口的方法
3、容器级生命周期接口方法:
这个包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现,一般称它们的实现类为“后处理器”。
4、工厂后处理器接口方法:
这个包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等非常有用的工厂后处理器 接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。
网上也各个接口的有加载顺序,但我发现,自己的项目加载顺序和网上所说的顺序不太一样,但网上的大家都赞同,肯定是自己哪里有区别:
于是先读一遍源码:
---------------bean加载源码分析-------------------
接口 :BeanDefinitionRegistryPostProcessor(extends BeanFactoryPostProcessor)
解释:此接口是标准BeanFactoryPostProcesser的扩展,它是在BeanFactoryPostProcesser前一步
进行执行的。
方法:postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
解释:在bean标准的初始化后修改程序上下文中的bean定义注册。所有常规的bean定义都被加
载,但仍然没有实例化bean,此时允许进一步在下一个后置处理器来之前进行bean定义。
接口 :BeanFactoryPostProcessor
解释:允许在程序上下文bean定义时进行自定义修改。一般在定义bean之后修改bean的属性配置,
此接口可以和bean定义进行交互,但此时bean还未进行实例化,违反了容器,可能会有意想不
到的副作用,如果需要和bean实例交互,考虑: BeanPostProcessor.
方法:postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
解释:在上下文内的bean工厂里标准初始化之后修改bean。此时bean被加载,但没有实例化。
接口:ApplicationContextAware extends Aware
解释:所有实现此接口的对象都希望在它运行时能得到通知 ApplicationContext。这个接口也可以被
对象去实现去获取资源文件,去发布应用程序,去获取MessageSource.然而它们有更具体的接口:
ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware.
方法:setApplicationContext(ApplicationContext applicationContext)
解释:在该对象运行的时候设置上下文,通常这个调用将被用来初始化对象。
接口:BeanPostProcessor
解释:允许自定义修改新bean实例,如:检查标记接口或包装代理。
方法:postProcessBeforeInitialization(Object bean, String beanName)
解释:运用这个方法给新定义的bean实例回调接口之前执行,例如:InitializingBean's
{@code afterPropertiesSet}或者自定义 init-method。这个bean此时已经填充了属性值,返回
的bean实例可能时原始的包装器。
方法:postProcessAfterInitialization(Object bean, String beanName)
解释:运用这个方法给新定义的bean实例回调接口之后执行,例如:InitializingBean's
{@code afterPropertiesSet}或者自定义 init-method。这个bean此时已经填充了属性值,返回
的bean实例可能时原始的包装器。
在factoryBean中,调用这个回调将获取到factoryBean创建的实例和对象,这个后置处理
器能够决定是否运用FactoryBean或者创建对象或通过相应的bean检查。
接口:InitializingBean
解释:继承了此接口的bean需要立即反应他们在BeanFactory中的属性,例如:执行自定义初始化,
或者仅仅是检查强制性属性设置。
方法:afterPropertiesSet()
解释:此方法被bean工厂调用来设置所有bean的属性,此方法只允许所有的bean属性设置并且配
置异常事件的错误配置之后bean实例化才能执行。
其他bean级声明周期接口:BeanNameAware、BeanFactoryAware、DiposableBean
接口:InstantiationAwareBeanPostProcessor extends BeanPostProcessor
解释:它是BeanPostProcessor的子接口,添加实例化之前的回调以及实例化之后的回调但是在明确
属性设置或自动装配之前。通常用于阻止特定目标bean的默认初始化,例如创建特殊目标的代理
(池目标,懒加载目标,等),这个接口是一个特殊的接口,一般在框架内部进行实例化使用,
方法:postProcessBeforeInstantiation(Class> beanClass, String beanName);
解释:此方法执行实在目标bean实例化之前,返回的对象可能是一个代理bean而不是目标bean,有
效地禁止了默认目标bean的实例化。如果这个方法返回的是一个非空对象,bean的创建过程将
会短路,唯一进一步处理的应用是通过{ @link # postProcessAfterInitialization } 从配置回调
{ @link BeanPostProcessor BeanPostProcessors },这个回调仅适用于对一个bean类的定义,特别
地,它不适应用于多个bean的工厂方法。后处理器可以实现扩展
SmartInstantiationAwareBeanPostProcessor 接口,能够预测bean对象的类型,并返回到这里。
方法:postProcessAfterInstantiation(Object bean, String beanName)
解释:bean实例化之后执行的方法,但是在spring属性群(显示属性或者自动装配)之前发生。这是
一个理想的给bean实例进行执行注入字段的回调属性。如果属性群应该跳过,通常实现应该返回
true,返回false的话也将会阻止任何后续InstantiationAwareBeanPostProcessor实例调用这个bean实
例。
方法:postProcessPropertyValues(
PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName)
解释:在工厂给bean运用属性之前的后置处理器,允许检查是否所有的依赖像是满足的,例如基
于“Required”注解在bean属性上的setters.还允许替换属性值运用,通常通过创建一个新的
基于最初的MutablePropertyValues 实例,添加或删除特定的值。
返回值: 真正给bean的属性值(能够传入PropertyValues实例),或者为null来跳过属性设置。
接口敲了敲继承这些接口的小demo,这里只贴上它们的加载顺序吧:
注意:上面的红色部分只有特殊类会执行,蓝色部分只有普通类实例化时才会执行。看下面:
发现:只要继承了BeanFactoryPostProcessor,BeanPostProcessor 这两个接口,它们的bean的加载都会在容器级接口
以前就会完成,而且不会被其他bean生命周期接口实现类去回调。
spring的东西不熟,如有错误或缺漏的地方,希望能指正。