PS : 个人感觉,实现IOC的两个核心后处理器 :
ConfigurationClassPostProcessor 解析配置类(这里的配置类不仅仅局限于@Configuration 注解,还包括 @Import、 @ImportResource 等注解),将解析到的需要注入到Spring容器中的bean的BeanDefinition保存起来
AutowiredAnnotationBeanPostProcessor 解析bean中的 需要自动注入的bean @Autowired 和 @Inject @Value注解。
二、BeanFactoryPostProcessor & BeanDefinitionRegistryPostProcessor
由于 invokeBeanFactoryPostProcessors 方法中主要就是对BeanFactoryPostProcessor 的处理,所以这里简单的介绍一下 BeanFactoryPostProcessor 及其子接口 BeanDefinitionRegistryPostProcessor。其结构如下图:
BeanFactoryPostProcessor 相比较于 BeanPostProcessor 方法是很简单的,只有一个方法,其子接口也就一个方法。但是他们俩的功能又是类似的,区别就是作用域并不相同。BeanFactoryPostProcessor的作用域范围是容器级别的。它只和你使用的容器有关。如果你在容器中定义一个BeanFactoryPostProcessor ,它仅仅对此容器中的bean进行后置处理。BeanFactoryPostProcessor 不会对定义在另一个容器中的bean进行后置处理,即使这两个容器都在同一容器中。
BeanFactoryPostProcessor 可以对 bean的定义(配置元数据)进行处理。Spring IOC 容器允许 BeanFactoryPostProcessor 在容器实际实例化任何其他bean之前读取配置元数据,并有可能修改它,也即是说 BeanFactoryPostProcessor 是直接修改了bean的定义,BeanPostProcessor 则是对bean创建过程中进行干涉。
BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor 的区别在于:
BeanDefinitionRegistryPostProcessor .postProcessBeanDefinitionRegistry 方法针对是BeanDefinitionRegistry类型的ConfigurableListableBeanFactory,可以实现对BeanDefinition的增删改查等操作,但是对于非 ConfigurableListableBeanFactory 类型的BeanFactory,并不起作用。
BeanFactoryPostProcessor .postProcessBeanFactory 针对的是所有的BeanFactory。
postProcessBeanDefinitionRegistry 的调用时机在postProcessBeanFactory 之前。
注: 关于 BeanPostProcessor ,请看前篇 :Spring源码分析衍生篇四:后处理器 BeanPostProcessor
三、代码分析
1. BeanFactory
需要注意的是,我们这里的 BeanFactory 实际类型是 DefaultListableBeanFactory。这一点在 Spring源码分析一:容器的刷新 - refresh() 中已经得到证实。
下面我们看看 DefaultListableBeanFactory 的结构图如下,可以看到DefaultListableBeanFactory 实现了 BeanDefinitionRegistry 接口。这点在下面的分析中会用到。
2. 代码分析
invokeBeanFactoryPostProcessors 方法的作用是激活BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor 。
为了更好的了解下面的代码,我们先了解几个代码中的规则:
BeanFactoryPostProcessor 在本次分析中分为两种类型: BeanFactoryPostProcessor 和其子接口 BeanDefinitionRegistryPostProcessor 。BeanDefinitionRegistryPostProcessor 相较于 BeanFactoryPostProcessor ,增加了一个方法如下。
需要注意的是,BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry 这个方法仅仅针对于 BeanDefinitionRegistry 类型的 BeanFactory 生效,这一点根据其入参就可以看到。
总结一下即 : BeanFactoryPostProcessor 针对所有的 BeanFactory ,即对于所有类型的BeanFactory 都会调用其方法;BeanDefinitionRegistryPostProcessor 仅对 BeanDefinitionRegistry 子类的BeanFactory 起作用,非BeanDefinitionRegistry类型则直接处理即可。
BeanFactoryPostProcessor 的注入分为两种方式:
配置注入方式:即通过注解或者xml的方式动态的注入到容器中的BeanFactoryPostProcessor
硬编码注入方式: 这种方式是直接调用 AbstractApplicationContext#addBeanFactoryPostProcessor 方法将 BeanFactoryPostProcessor 添加到 AbstractApplicationContext#beanFactoryPostProcessors 属性中。其中
硬编码注入的BeanFactoryPostProcessor 并不需要也不支持接口排序,而配置注入的方式因为Spring无法保证加载的顺序,所以通过支持PriorityOrdered、Ordered排序接口的排序。
在下面代码分析中会由四个集合
regularPostProcessors : 记录通过硬编码方式注册的BeanFactoryPostProcessor 类型的处理器
registryProcessors:记录通过硬编码方式注册的BeanDefinitionRegistryPostProcessor 类型的处理器
currentRegistryProcessors : 记录通过配置方式注册的 BeanDefinitionRegistryPostProcessor 类型的处理器
processedBeans : 记录当前已经处理过的BeanFactoryPostProcessor 和 BeanDefinitionRegistryPostProcessor
其实调用顺序可以归纳为: 硬编码先于配置,postProcessBeanDefinitionRegistry 先于postProcessBeanFactory
下面我们来看具体代码:
AbstractApplicationContext#invokeBeanFactoryPostProcessors 方法内容如下
可以看到主要功能还是在PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()); 这一句上。我们先来看看 getBeanFactoryPostProcessors() 得到的是什么
2.1 getBeanFactoryPostProcessors()
可以看到 getBeanFactoryPostProcessors() 方法仅仅是将 beanFactoryPostProcessors 集合返回了出去而已。那么 beanFactoryPostProcessors 集合是通过 set方法添加的。这就是我们上面提到过的,beanFactoryPostProcessors 实际上是 硬编码形式注册的BeanDefinitionRegistryPostProcessor 类型的处理器集合。
2.2 invokeBeanFactoryPostProcessors
通过上一步,我们可以知道 入参中的 beanFactoryPostProcessors 集合是硬编码注册的 集合。对于下面的分析我们就好理解了。
下面代码主要是对于 BeanDefinitionRegistry 类型 BeanFactory的处理以及 BeanFactoryPostProcessor 调用顺序问题的处理。实际上并不复杂。
下面有一个简单的流程图: