Spring 源码阅读 14:注册 BeanPostProcessor
前情提要
在之前的 ApplicationContext 初始化 Spring 容器 一文中,提到 AbstractApplicationContext#refresh
方法是一个非常重要的方法,它包含了 Spring 容器初始化的整个流程。最近的一系列文章都在深入分析这个方法中的每一个步骤的具体原理,本文接着分析 BeanPostProcessor 的注册,也就是refresh
方法中的这行代码:
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
BeanPostProcessor 介绍
进入方法之前,有必要先深入了解一下 BeanPostProcessor 接口。
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;
}
}
它是 Bean 实例的后处理器,在 Bean 被实例化之后、执行初始化的前后,分别提供了扩展点,这两个扩展点就是 BeanPostProcessor 中的两个方法。具体见下图:
通过实现 BeanPostProcessor 接口,并注入 Spring 容器中,可以在 Bean 初始化的前后对 Bean 做一些处理。关于 Bean 的实例化和初始化,不在本文讨论的范畴,之后会有文章专门讨论。
了解了 BeanPostProcessor 的作用之后,下面来从代码中分析它是如何被注册到容器中的。
注册 BeanPostProcessor
首先进入registerBeanPostProcessors
方法内部。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
方法的执行过程被委派给了 PostProcessorRegistrationDelegate 的同名方法。
public static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, register the BeanPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
// Finally, re-register all internal BeanPostProcessors.
sortPostProcessors(internalPostProcessors, beanFactory);
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).
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
整个方法体中的逻辑流程比较长,其中包括一些比较相似的逻辑。为了方便查看分析,我会在分析到某一部分的时候,将那部分的代码片段再贴出来。
注册 BeanPostProcessorChecker
先看方法代码开头的一部分。
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
// Register BeanPostProcessorChecker that logs an info message when
// a bean is created during BeanPostProcessor instantiation, i.e. when
// a bean is not eligible for getting processed by all BeanPostProcessors.
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
首先,通过getBeanNamesForType
方法,从beanFactory
中找出了所有实现了 BeanPostProcessor 的beanName
。
然后,计算了全部注册完成之后,容器中 BeanPostProcessor 的数量,计算方法是:
容器中已注册的后处理器数量+1+即将要注册的后处理器的数量
这里之所以要加 1 是因为下一句代码中,向beanFactory
中注册了一个新的 BeanPostProcessor,类型是 BeanPostProcessorChecker。它的作用是检查出一些没有资格被所有 BeanPostProcessor 处理的 Bean,并记录日志。
给 BeanPostProcessor 分组
接着往下看:
// Separate between BeanPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
如果你看过我的上一篇源码分析,会非常熟悉这里的操作。这里将所有即将注册的 BeanPostProcessor 根据是否实现了 PriorityOrdered 或 Ordered 接口,将它们分组,主要是为了调整 BeanPostProcessor 注册的顺序。如果你不了解这个流程,强烈建议阅读我上一篇代码分析中相关的内容。
上一篇代码分析的传送门:Spring 源码阅读 13:执行 BeanFactoryPostProcessor 中的处理方法
这里有一个特殊的地方是,多了一个 internalPostProcessors 列表,用来存放 Spring 容器内部的 BeanPostProcessor。只要实现了 MergedBeanDefinitionPostProcessor 接口的 BeanPostProcessor 都会放入这个列表中(针对其余三个列表中所有的 BeanPostProcessor 都会执行这样的操作)。
按组进行注册操作
接着看后面的代码。
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
首先对orderedPostProcessors中的元素进行了排序,然后通过registerBeanPostProcessors
方法执行了 BeanPostProcessor 的注册。
以下是registerBeanPostProcessors
方法的代码:
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
后续的代码中,对于orderedPostProcessorNames
和nonOrderedPostProcessorNames
两个列表,也执行了同样的操作:
// Next, register the BeanPostProcessors that implement Ordered.
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String ppName : orderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
两段相同的逻辑如下:
- 创建一个对应的 BeanPostProcessor 列表
- 遍历列表中的每一个元素,也就是一个
beanName
- 根据
beanName
从beanFactory
获取到 Bean 的实例 - 将其添加到第一步创建的列表中
- 如果实现了 MergedBeanDefinitionPostProcessor 接口,则添加到 internalPostProcessors 中(
nonOrderedPostProcessors
除外) - 遍历完之后,对列表中的元素进行排序,然后通过
registerBeanPostProcessors
方法进行注册
注册 Spring 内部的 BeanPostProcessor
之后,在对internalPostProcessors
列表中的 BeanPostProcessor 进行排序和注册,代码如下。
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
重新注册 ApplicationListenerDetector
在方法的最后:
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
这行代码的作用是重新注册一次 ApplicationListenerDetector。ApplicationListenerDetector 实现了 MergedBeanDefinitionPostProcessor 接口,也就是它被作为 Spring 内部的 BeanPostProcessor 来处理的。进行重新注册是为了把它放到后处理器链的末尾。
重复注册和顺序
以上的流程介绍完了,但是有两个可能会产生疑点需要再介绍一下,这两个疑点是:
- 将实现了 MergedBeanDefinitionPostProcessor 的 BeanPostProcessor 放到一个内部后处理器的列表中时,并没有在原来的列表中移除,这不是重复注册了吗?
- 为什么重新注册一个 BeanPostProcessor 会将其移动到后处理器链的末尾呢?
其实答案都在注册 BeanPostProcessor 的方法当中,在 AbstractBeanFactory 中找到addBeanPostProcessor
方法,查看其代码:
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
可以看到,在将一个 BeanPostProcessor 进行注册之前,会先将其移除。因此不会出现重复注册的问题,通过重复注册将一个 BeanPostProcessor 移动位置也说得通了。
后续
本文介绍了在 Spring 容器初始化过程中, BeanPostProcessor 注册的流程。有一点要提醒的是,这部分逻辑知识进行了 BeanPostProcessor 的注册,而并没有执行其中的处理方法,这些方法会在 Bean 的初始化过程中执行。
后续会接着分析 Spring 容器初始化之后的流程。