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

ConfigurationClassPostProcessorAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorEventListenerMethodProcessorPersistenceAnnotationBeanPostProcessor

虽然其他的不熟悉,但是熟悉的有AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor,这两个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代理过程

posted @ 2023-01-02 22:53  写的代码很烂  阅读(52)  评论(0编辑  收藏  举报