IOC流程解析-BeanFactoyPostProcessor和BeanPostProcessor

本次内容要讲的是BeanFactory 创建完成并设置了BeanDefinition 之后,BeanFactoyPostProcessor 的初始化和执行,还有BeanPostProcessor 的初始化,注意今天的内容BeanPostProcessor 是不会执行的,在 Spring的基本概念和IOC流程的简述 的文章就说过了IOC 的流程图,BeanPostProcessor 的执行是在Bean 实例化之后。

源码分析

接着上篇文章(上篇文章是: IOC流程解析-BeanFactory的创建)继续讲IOC 的核心方法refresh 方法的内容,之前讲完了obtainFreshBeanFactory 方法的调用,那么下一步就是prepareBeanFactory 方法了。

Bean工厂的前置操作-prepareBeanFactory方法

这个方法不是重点方法,所以代码就不细说了,按照代码流程简单说一下这个方法的主要了些什么,作用如下:

  1. 首先就是给beanFactory 设置一些属性,如类加载器、注册解析器之类;
  2. 然后就是添加第一个beanPostProcessor 后置处理器(注意:这里是bean,不是beanFactory),这个后置处理器会添加到beanFactory 的私有常量集合beanPostProcessors 集合属性中,而这个后置处理器ApplicationContextAwareProcessor 处理器,其主要作用就是为了在bean 初始化的时候,判断bean 是否都实现了ApplicationContextAware、EnvironmentAware之类接口,然后为其注入对应的applicationContext 对象;
  3. 然后就是设置一些忽略接口,比如刚刚说的ApplicationContextAware,因为这些spring 自己会做处理,接着就是对特殊的几个bean依赖做处理,这里不用深究;
  4. 然后就是添加第二个beanPostProcessor 后置处理器,这个是ApplicationListenerDetector 处理器,其主要做用就是为实现ApplicationListener 接口的对象初始化的时候,将其注册到一个监听列表中。这里涉及到spring 的事件传播机制,这个后续再说,会结合上篇所说到的dubbo 标签解析内容一起再细说一次;
  5. 最后一个重点,这里会创建三个完整对象,并添加到单例池中,单例池就是beanFactory 的私有常量集合singletonObjects 集合,这也是我们常说的IOC 容器、一级缓存。后面bean 初始化完成后得到的完整对象就是存入这个集合中。说回三个完整对象,其实就是对系统和beanFactory 的一些配置信息,后面需要使用的话可以直接通过对象获取。

Bean工厂后置操作-postProcessBeanFactory方法

prepareBeanFactory方法结束后,接下来就是postProcessBeanFactory 方法,但是这个方法就是提供一个模板,可以自己实现接口,重写这个方法来实现自己的业务逻辑,它本身没有任何的代码逻辑。

调用bean工厂后置处理器-invokeBeanFactoryPostProcessors 方法

这一步就已经到了BeanFactoryPostProcessors 的构建和调用过程了,也算是今天的重点之一。

跟进具体方法,其重点是继续invokeBeanFactoryPostProcessors 方法的调用,继续跟进的话,这里的内容就多了去了,不过逻辑并不复杂,我们一步一步跟重点看。不过这里需要注意一点该方法的第二个入参getBeanFactoryPostProcessors 方法返回值,这里是当前应用上下文中已经注册的BeanFactoryPostProcessor,也就是只有多容器启动的时候这个返回才有值。

1
2
3
// 1.getBeanFactoryPostProcessors(): 获取当前应用上下文中已经注册的 BeanFactoryPostProcessor
// 2.invokeBeanFactoryPostProcessors : 实例化并调用所有已注册的BeanFactoryPostProcessors变量中的值
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());

进入invokeBeanFactoryPostProcessors 方法。

第一步:判断beanFactory

判断beanFactory 是否为BeanDefinitionRegistry,之前Spring的基本概念和IOC流程的简述 文章中介绍bean 组件的时候有说过beanFactory 的最底层子类是DefaultListableBeanFactory,而该类又实现了BeanDefinitionRegistry,我们目前传入的对象就是DefaultListableBeanFactory,所以这里一定是满足的。

然后看到这里会声明两个集合,一是:用于保存普通的BeanFactoryPostProcessor类型的后置处理器、还有一个是:保存BeanDefinitionRegistryPostProcessor类型的后置处理器,由此可以知道BeanFactory 后置处理器为两个实现类型。

1
2
3
4
5
6
7
8
9
// 1. 判断beanFactory是否为BeanDefinitionRegistry
// beanFactory类型为DefaultListableBeanFactory,DefaultListableBeanFactory实现了BeanDefinitionRegistry,所有为true
if (beanFactory instanceof BeanDefinitionRegistry) {
// 类型强转
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 声明集合:保存普通的BeanFactoryPostProcessor类型的后置处理器
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 声明集合:保存BeanDefinitionRegistryPostProcessor类型的后置处理器
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

BeanFactory后置处理器-BeanDefinitionRegistryPostProcessor

BeanFactoryPostProcessor 这个后置处理器没有什么好说的,只要实现了这个接口,那么就是BeanFactory 的后置处理器。

我们目前要知道的是BeanDefinitionRegistryPostProcessor,这个接口是BeanFactoryPostProcessor 接口的子类接口。它这里可以看做是对于原本普通的BeanFactoryPostProcessor 进行了一次加强,也就说如果实现该接口,不光要实现BeanFactoryPostProcessor 接口的方法,还要实现该接口本身的方法。

1
2
3
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}

第二步:处理入参的BeanFactoryPostProcessor集合

这里继续刚刚的invokeBeanFactoryPostProcessors 方法。

接下来是处理刚刚传入参数的BeanFactoryPostProcessor 集合,也就是上面说的getBeanFactoryPostProcessors 方法的返回值。这里的处理也就是简单的调用而已,因为这个集合是注册在其余容器中了的,所以优先级之类的已经处理过了,这里我们不重点看。

但是需要注意的是:这里执行的只有BeanDefinitionRegistryPostProcessor 的实现,BeanFactoryPostProcessor 的实现类是没有执行对应的方法的,但是这个两种接口实现都会存入上面声明的集合。

第三步:处理当前BeanDefinitionRegistryPostProcessor的PriorityOrdered实现

下一步是再次声明一个集合用于保存本次要执行的BeanDefinitionRegistryPostProcessor。

然后就是通过beanFactory 获取到所有的实现了BeanDefinitionRegistryPostProcessor 接口的对象,这里我们其实还可以看出:如果存在多个执行器的话,目前的执行顺序就是配置信息的解析顺序。

接下来就是循环上面获取的集合,然后就是筛选出接口实现,并添加相应集合。

然后在此将要执行的集合再次排序,依据就是否是实现了Ordered 接口,还有其接口实现的order 值。然后添加上面声明的registryProcessors 集合,最后执行处理好的currentRegistryProcessors 集合,并在执行完成之后清空关闭该集合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 定义集合:用于保存本次要执行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 3.调用所有实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessors
// 3.1 找出所有实现了PriorityOrdered接口的Bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 3.2 遍历postProcessorNames
for (String ppName : postProcessorNames) {
// 3.3 校验是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 3.4 获取ppName对应regular的bean实例,添加到currentRegistryProcessors
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 3.5 将要被执行的加入processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
registryProcessors.addAll(currentRegistryProcessors);
// 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 3.9 执行完毕后, 清空currentRegistryProcessors
currentRegistryProcessors.clear();

第四步:处理当前BeanDefinitionRegistryPostProcessor的Ordered实现

逻辑跟上面一样,先获取、再筛选、再排序、最后执行实现对象的对应方法,并清空关闭集合。没有什么可以聊的,不过需要注意的是这里和上面执行的都是BeanDefinitionRegistryPostProcessor 接口的postProcessBeanDefinitionRegistry 方法,BeanFactoryPostProcessor 接口对应的方法是还没有执行的。

对了这里还要注意一个校验执行过的,是不能重复执行的,也就是processedBeans 集合的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)
// 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,
// 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 校验是否实现了Ordered接口,并且还未执行过
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

执行优先级-PriorityOrdered接口和Ordered接口

这两个接口的优先级,从上面的代码也可以看出来PriorityOrdered 接口实现要优先于Ordered 接口实现。PriorityOrdered 接口更像是一个标识,它本身没有方法,它的父类就是Ordered 接口,这个接口有一个getOrder 方法,用于编写优先级。具体实现如下。其返回数字越大,优先级越大。

1
2
3
4
@Override
public int getOrder() {
return 1;
}

第五步:执行剩下的BeanDefinitionRegistryPostProcessors

首先是通过循环筛选出剩下的所有BeanDefinitionRegistryPostProcessors 的实现类,然后排序、添加集合、执行调用该接口的postProcessBeanDefinitionRegistry 方法,清空关闭currentRegistryProcessors 集合,老套路了,没有什么好说的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 5.最后, 调用所有剩下的BeanDefinitionRegistryPostProcessors
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 5.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 5.2 跳过已经执行过的
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
// 5.3 如果有BeanDefinitionRegistryPostProcessor被执行, 则有可能会产生新的BeanDefinitionRegistryPostProcessor,
// 因此这边将reiterate赋值为true, 代表需要再循环查找一次
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 5.4 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}

第六步:执行所有的BeanDefinitionRegistryPostProcessors实现的postProcessBeanFactory方法

到这里是执行所有的,注意是所有的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory方法,也就是其父类接口对应的方法,之前执行的方法都是它自己定义的,然后是执行入参集合中的postProcessBeanFactory方法。

这里所有的BeanDefinitionRegistryPostProcessors 实现算是执行完成了。

1
2
3
4
5
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// 6.调用所有BeanDefinitionRegistryPostProcessor的postProcessBeanFactory方法(BeanDefinitionRegistryPostProcessor继承自BeanFactoryPostProcessor)
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 7.最后, 调用入参beanFactoryPostProcessors中的普通BeanFactoryPostProcessor的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

第七步到最后一步:执行BeanFactoryPostProcessor的实现

这里就不展示代码了,因为套路是一模一样的,唯一的区别就是获取的接口实现不一样而已。

这个方法就算是结束了。

小结:方法作用及优先级顺序

这个方法其主要作用就是执行所有的BeanFactoryPostProcessor 接口和子类接口的相关实现,如果是多容器启动的话,其余容器的BeanFactory 执行器也要再次执行。

不同方法执行优先级总结:其余容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanDefinitionRegistry 方法 > 当前容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanDefinitionRegistry 方法 > 其余容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory 方法 > 当前容器的BeanDefinitionRegistryPostProcessors 实现的postProcessBeanFactory 方法 > 其余容器的BeanDefinitionPostProcessors 实现的postProcessBeanFactory 方法 > 当前容器的BeanDefinitionPostProcessors 实现的postProcessBeanFactory。

同一方法执行优先级总结:实现PriorityOrdered 接口 > 实现Ordered接口 > 配置文件配置顺序;实现同一接口是:按照getOrder 方法返回的数字排序,数字越大优先级越高。

注册Bean后置处理器-registerBeanPostProcessors方法

看完了bean工厂后置处理器的执行,在回到核心refresh 方法继续看。

接下来是Bean 的后置处理器,注意不是beanFactory 的了,同时这里是register 注册没有调用的内容。清楚这点后,我们再看代码。

跟进方法,没有什么内容就是调用PostProcessorRegistrationDelegate 对象的注册方法,继续跟进后内容跟上面的一样多,不过都是老套路,我们就看下区别点就行了。

1
2
3
4
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 1.注册BeanPostProcessor
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

跟进该方法。

首先获取所有的BeanPostProcessor 接口的实现。

1
2
// 1.找出所有实现BeanPostProcessor接口的类
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

然后记一下数据量,并存入beanFactory 中。

1
2
3
4
5
// BeanPostProcessor的目标计数
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;

// 2.添加BeanPostProcessorChecker(主要用于记录信息)到beanFactory中
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

然后就是老三样、筛选、排序、保存集合、然后注意这里不是执行对应接口方法,而是注册。

1
2
// 5.2 注册priorityOrderedPostProcessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

也就是存入beanFactory 中。不过这里其实已经添加过几个BeanPostProcessor 了,就是上面的前置作用内容添加的。

1
2
3
4
5
6
7
8
9
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {

// 1.遍历postProcessors
for (BeanPostProcessor postProcessor : postProcessors) {
// 2.将PostProcessor添加到BeanFactory中的beanPostProcessors缓存
beanFactory.addBeanPostProcessor(postProcessor);
}
}

说到上面添加的处理器,这个方法的最后一部分就是想将它们再次注册,也就是移动到处理链末尾。

然后这个方法就结束了。

1
2
3
4
5
6
7
8
9
10
// 8.最后, 重新注册所有内部BeanPostProcessors(相当于内部的BeanPostProcessor会被移到处理器链的末尾)
// 8.1 对internalPostProcessors进行排序
sortPostProcessors(internalPostProcessors, beanFactory);
// 8.2注册internalPostProcessors
registerBeanPostProcessors(beanFactory, internalPostProcessors);

// Re-register post-processor for detecting inner beans as ApplicationListeners,
// moving it to the end of the processor chain (for picking up proxies etc).
// 9.重新注册ApplicationListenerDetector(跟8类似,主要是为了移动到处理器链的末尾)
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));

Bean后置执行器的实现-BeanPostProcessor接口

这里还要说一点就是Bean 后置执行器就是BeanPostProcessor 接口的实现,这一点从上面的代码中也可以看出来,我们这里要说的是BeanPostProcessor 接口中的postProcessBeforeInitialization 方法和postProcessAfterInitialization 方法,这两个方法名称的差别非常的小,要注意看前者是Before,后者是After。从名字看也能知道前者是前置方法,后者是后置方法,这样读起来也很有意思,Bean后置执行器的前置方法和后置方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
public interface BeanPostProcessor {

@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}

}

结合之前文章[Spring的基本概念和IOC流程的简述](https://liwqtm.github.io/2022/04/09/Spring IOC(一)/#more) 的IOC 流程图可以看出,这两个方法的执行时机是在bean 的初始化部分,同时After 后置方法还存在aop 的实现内容,这个我们后面再说,目前要明白Bean 后置执行器是如何去实现的,并且重写了哪两个方法即可。

image-20220423204948988

总结

本次就是继上篇IOC流程解析-BeanFactory的创建 后说了refresh 核心方法中的后面四个方法,其主要作用就是BeanFactory 的前置操作、BeanFactory 的后置处理器执行、Bean 后置处理的注册。简单来说还是一些BeanFactory 的处理,是实例化和初始化之前的大部分内容了,后面就是初始化和实例化了。

附录Spring 源码分析系列文章

IOC

时间 文章
2022-03-09 Spring的基本概念和IOC流程的简述
2022-03-11 IOC流程解析-BeanFactory的创建
2022-03-14 IOC流程解析-BeanFactoyPostProcessor和BeanPostProcessor
2022-03-15 IOC流程解析-实例化和初始化
2022-03-17 IOC流程解析-循环依赖

AOP

时间 文章
2022-03-19 AOP流程源码分析-配置信息解析和代理对象创建
2022-03-20 AOP流程源码分析-请求调用全流程