Spring之BeanFactoryPostProcessor的执行流程
BeanFactoryPostProcessor的执行流程
一、Spring中的BeanDefinition是什么时候开始创建的?
从这个问题开始入手分析BeanFactoryPostProcessor。
由我们前面的分析可以知道,BeanDefinition是ClassPathBeanDefinitionScanner在调用scan方法进行扫描的时候生成的BeanDefinition。
从下面代码中开始着手分析:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.refresh();
那么随着上面的思路分析,在ClassPathBeanDefinitionScanner调用scan方法时的截图如下:
通过上面的截图可以发现,这个时候已经有了对应的beanDefinitionMap已经存在值了,通过左面的线程栈中可以知道,应该是在某个方法中对这里的beanDefinitionMap添加了一些BeanDefinition。那么Spring在哪里做到的以及这么做的目的是什么呢?
1.1、Spring在哪里实现生成BeanDefinition并添加到beanDefinitionMap中
通过调用栈可以追踪到第一行代码中
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
然后跟随着调用栈追踪到org.Springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.Springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
发现是在这里将Spring内置的一些BeanDefinition并添加到beanDefinitionMap。
既然这些BeanDefinition是由Spring添加到beanDefinitionMap,那么Spring提前做了的意义在哪里呢?
1.2、Spring默认添加的BeanDefinition
ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、EventListenerMethodProcessor、PersistenceAnnotationBeanPostProcessor
虽然其他的不熟悉,但是熟悉的有AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor,这两个Bean工厂的后置处理器对使用@Autowired和@Resource进行依赖注入的时候发挥作用的。
那么其他的呢?所以从这里引入了ConfigurationClassPostProcessor后置处理器
后续过程中因为需要使用到这些BeanDefinition,所以Spring提前将这些BeanDefinition进行创建。
二、ConfigurationClassPostProcessor后置处理器
对于后置处理器而言,在Spring中分为两种:BeanFactory后置处理器和BeanPostProcessor后置处理器。
这个接口在最开始的阶段中发挥了举足轻重的作用,换句话说这个类可以说在Spring容器初始化阶段中最重要的一个类。
2.1、继承体系
从继承体系图中可以看到,ConfigurationClassPostProcessor是实现了BeanFactoryPostProcessor接口的,而ConfigurationClassPostProcessor也实现了BeanDefinitionRegistryPostProcessor接口,而BeanDefinitionRegistryPostProcessor接口也实现了BeanFactoryPostProcessor接口。
所以对于ConfigurationClassPostProcessor类来说,既有BeanFactoryPostProcessor接口的功能,也有BeanDefinitionRegistryPostProcessor接口的功能,而这两个接口在初始化阶段分别发挥着不同的作用。
2.2、作用时机
在org.Springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.Springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.Springframework.beans.factory.config.BeanFactoryPostProcessor中会有对应的体现
那么直接看下源码
一、找到实现BeanDefinitionRegistryPostProcessor接口的BD的后置处理器并调用postProcessBeanDefinitionRegistry方法以及记录BeanDefinitionRegistryPostProcessor对应的BD
1、首先对bean工厂的类型来做判断,判断是否是BeanDefinitionRegistry类型的bean工厂,而bean工厂是DefaultListableBeanFactory,是属于BeanDefinitionRegistry子类的,所以符合条件;
2、如果Spring开天辟地的BeanDefinition中存在BeanDefinitionRegistryPostProcessor类型的bean工厂后置处理器,那么会先调用后置处理器的postProcessBeanDefinitionRegistry方法。而Spring默认的BeanDefinition中只有ConfigurationClassPostProcessor是符合条件的。所以会先执行ConfigurationClassPostProcessor中的postProcessBeanDefinitionRegistry方法;
3、然后将找到了的实现了BeanDefinitionRegistryPostProcessor对应的BD保存起来;
Spring既然在这里写了,那么Spring又是如何在这里实现呢?
通过源码来进行观察
可以知道这里的beanFactoryPostProcessors是从方法参数中传递过来的,那么看下这个参数是如何传递过来的。
看下这里传递过来的参数信息
通过结果发现这里是Spring容器中的一个属性参数,所以只需要找到Spring何时在这里添加的即可。
通过Find Usage发现
那么在容器进行调用refresh方法前,调用这个方法会调用上面的方法。对应的代码如下所示:
首先创建一个MyBeanFactoryPostProcessor,对应代码如下所示:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(AppConfig.class);
applicationContext.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
applicationContext.refresh();
然后断点打上,如下所示:
从这里可以看到我们手动注册进去的BeanFactoryPostProcessor
方便在下面按照条件来进行筛选
①找到实现BeanDefinitionRegistryPostProcessor和PriorityOrdered接口的Bean
需要注意的是这里是先找到,然后再执行。而不是找到之后就执行。
注意一下这里的两个集合:
currentRegistryProcessors:当前执行的后置处理器集合;
processedBeans:处理过的bean的集合
根据上下文的分析,currentRegistryProcessors只适用于当前循环中,当前循环结束,那么就会清空;而processedBeans则会一直伴随着整个方法的结束。
从上面的截图中可以看到,先找到实现BeanDefinitionRegistryPostProcessor和PriorityOrdered接口的bean(Spring中只有ConfigurationClassPostProcessor符合条件),然后进行排序,排完顺序之后执行对应的postProcessBeanDefinitionRegistry方法。
②找到实现BeanDefinitionRegistryPostProcessor和PriorityOrdered接口的Bean
需要注意的是上面的一个集合processedBeans,对已经处理过了的,不再会再次处理!!
然后调用BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry来进行调用
③找到实现BeanDefinitionRegistryPostProcessor类型的Bean
这里需要注意的是,如果已经处理过了的bean会被添加到processedBeans中来,也就是说执行执行过了的下面不会重复执行的!!!
while循环说明
那么肯定是在①②③中产生了BeanDefinitionRegistryPostProcessor类型的Bean,然后这里从Spring容器中再次来进行遍历的时候找到了!!
那么如何产生了BeanDefinitionRegistryPostProcessor类型的Bean呢?说明了扫描包下的class文件的时候是在上面发生的,那么才会产生BeanDefinitionRegistryPostProcessor类型的Bean。
用代码演示即如下所示:
public class MyBeanDefinitionRegistryPostProcessor2 implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
但是再次来利用一个BeanDefinitionRegistryPostProcessor来进行处理:
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(MyBeanDefinitionRegistryPostProcessor2.class);
beanDefinitionBuilder.setAbstract(false);
AbstractBeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
registry.registerBeanDefinition("postProcessor2",beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
④找到并执行BeanDefinitionRegistryPostProcessor中的postProcessBeanFactory方法
二、找到实现BeanFactoryPostProcessor接口的Bean
①找到实现BeanFactoryPostProcessor和PriorityOrdered接口的bean并执行postProcessBeanFactory方法
②找到实现BeanFactoryPostProcessor和Ordered接口的Bean并执行postProcessBeanFactory方法
③找到实现BeanFactoryPostProcessor且没有实现PriorityOrdered和Ordered接口的Bean并执行postProcessBeanFactory方法
三、总结
3.1、接口方法区别
接口 | BeanFactoryPostProcessor | BeanDefinitionRegistryPostProcessor |
---|---|---|
二者关系 | 后者是前者的子类 | |
方法名称 | postProcessBeanFactory | postProcessBeanDefinitionRegistry |
参数 | ConfigurableListableBeanFactory | BeanDefinitionRegistry |
作用 | 可以修改容器中的BD,但是不能够添加 | 向容器中的BDMap中注册添加BD |
注释说明 | 在应用程序上下文的标准初始化之后修改其内部bean工厂。 所有bean定义都将被加载,但还没有bean被实例化。 这允许重写或添加属性,甚至是对急切初始化的bean。 |
在应用程序上下文的标准初始化之后,修改其内部bean定义注册表。 所有常规bean定义都将被加载,但还没有bean被实例化。 这允许在下一个后处理阶段开始之前添加更多的bean定义。 |
实现类说明 | ConfigurationClassPostProcessor主要为了完成配置类的扫描 |
3.2、流程总结
在Spring中,ConfigurationClassPostProcessor先执行postProcessBeanDefinitionRegistry方法----完成扫描,生成对应的BD;
然后执行postProcessBeanFactory-----完成对应的CGLIB代理过程;