Spring 源码阅读 14:注册 BeanPostProcessor

简介: 本文主要分析了 Spring 上下文初始化过程中,注册 BeanPostProcessor 的逻辑。

image.png

基于 Spring Framework v5.2.6.RELEASE

接上篇:Spring 源码阅读 13:执行 BeanFactoryPostProcessor 中的处理方法

前情提要

在之前的 ApplicationContext 初始化 Spring 容器 一文中,提到 AbstractApplicationContext#refresh 方法是一个非常重要的方法,它包含了 Spring 容器初始化的整个流程。最近的一系列文章都在深入分析这个方法中的每一个步骤的具体原理,本文接着分析 BeanPostProcessor 的注册,也就是refresh方法中的这行代码:

// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);

BeanPostProcessor 介绍

进入方法之前,有必要先深入了解一下 BeanPostProcessor 接口。

publicinterfaceBeanPostProcessor {
@NullabledefaultObjectpostProcessBeforeInitialization(Objectbean, StringbeanName) throwsBeansException {
returnbean;
   }
@NullabledefaultObjectpostProcessAfterInitialization(Objectbean, StringbeanName) throwsBeansException {
returnbean;
   }
}

它是 Bean 实例的后处理器,在 Bean 被实例化之后、执行初始化的前后,分别提供了扩展点,这两个扩展点就是 BeanPostProcessor 中的两个方法。具体见下图:

image.png

通过实现 BeanPostProcessor 接口,并注入 Spring 容器中,可以在 Bean 初始化的前后对 Bean 做一些处理。关于 Bean 的实例化和初始化,不在本文讨论的范畴,之后会有文章专门讨论。

了解了 BeanPostProcessor 的作用之后,下面来从代码中分析它是如何被注册到容器中的。

注册 BeanPostProcessor

首先进入registerBeanPostProcessors方法内部。

protectedvoidregisterBeanPostProcessors(ConfigurableListableBeanFactorybeanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

方法的执行过程被委派给了 PostProcessorRegistrationDelegate 的同名方法。

publicstaticvoidregisterBeanPostProcessors(
ConfigurableListableBeanFactorybeanFactory, AbstractApplicationContextapplicationContext) {
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.intbeanProcessorTargetCount=beanFactory.getBeanPostProcessorCount() +1+postProcessorNames.length;
beanFactory.addBeanPostProcessor(newBeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
// Separate between BeanPostProcessors that implement PriorityOrdered,// Ordered, and the rest.List<BeanPostProcessor>priorityOrderedPostProcessors=newArrayList<>();
List<BeanPostProcessor>internalPostProcessors=newArrayList<>();
List<String>orderedPostProcessorNames=newArrayList<>();
List<String>nonOrderedPostProcessorNames=newArrayList<>();
for (StringppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
         }
      }
elseif (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=newArrayList<>(orderedPostProcessorNames.size());
for (StringppName : orderedPostProcessorNames) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
      }
   }
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.List<BeanPostProcessor>nonOrderedPostProcessors=newArrayList<>(nonOrderedPostProcessorNames.size());
for (StringppName : nonOrderedPostProcessorNames) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
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(newApplicationListenerDetector(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.intbeanProcessorTargetCount=beanFactory.getBeanPostProcessorCount() +1+postProcessorNames.length;
beanFactory.addBeanPostProcessor(newBeanPostProcessorChecker(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=newArrayList<>();
List<BeanPostProcessor>internalPostProcessors=newArrayList<>();
List<String>orderedPostProcessorNames=newArrayList<>();
List<String>nonOrderedPostProcessorNames=newArrayList<>();
for (StringppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
      }
   }
elseif (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方法的代码:

privatestaticvoidregisterBeanPostProcessors(
ConfigurableListableBeanFactorybeanFactory, List<BeanPostProcessor>postProcessors) {
for (BeanPostProcessorpostProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
   }
}

后续的代码中,对于orderedPostProcessorNamesnonOrderedPostProcessorNames两个列表,也执行了同样的操作:

// Next, register the BeanPostProcessors that implement Ordered.List<BeanPostProcessor>orderedPostProcessors=newArrayList<>(orderedPostProcessorNames.size());
for (StringppName : orderedPostProcessorNames) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
   }
}
sortPostProcessors(orderedPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
// Now, register all regular BeanPostProcessors.List<BeanPostProcessor>nonOrderedPostProcessors=newArrayList<>(nonOrderedPostProcessorNames.size());
for (StringppName : nonOrderedPostProcessorNames) {
BeanPostProcessorpp=beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (ppinstanceofMergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
   }
}
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

两段相同的逻辑如下:

  1. 创建一个对应的 BeanPostProcessor 列表
  2. 遍历列表中的每一个元素,也就是一个beanName
  3. 根据beanNamebeanFactory获取到 Bean 的实例
  4. 将其添加到第一步创建的列表中
  5. 如果实现了 MergedBeanDefinitionPostProcessor 接口,则添加到 internalPostProcessors 中(nonOrderedPostProcessors除外)
  6. 遍历完之后,对列表中的元素进行排序,然后通过registerBeanPostProcessors方法进行注册

注册 Spring 内部的 BeanPostProcessor

之后,在对internalPostProcessors列表中的 BeanPostProcessor 进行排序和注册,代码如下。

sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);

重新注册 ApplicationListenerDetector

在方法的最后:

beanFactory.addBeanPostProcessor(newApplicationListenerDetector(applicationContext));

这行代码的作用是重新注册一次 ApplicationListenerDetector。ApplicationListenerDetector 实现了 MergedBeanDefinitionPostProcessor 接口,也就是它被作为 Spring 内部的 BeanPostProcessor 来处理的。进行重新注册是为了把它放到后处理器链的末尾。

重复注册和顺序

以上的流程介绍完了,但是有两个可能会产生疑点需要再介绍一下,这两个疑点是:

  1. 将实现了 MergedBeanDefinitionPostProcessor 的 BeanPostProcessor 放到一个内部后处理器的列表中时,并没有在原来的列表中移除,这不是重复注册了吗?
  2. 为什么重新注册一个 BeanPostProcessor 会将其移动到后处理器链的末尾呢?

其实答案都在注册 BeanPostProcessor 的方法当中,在 AbstractBeanFactory 中找到addBeanPostProcessor方法,查看其代码:

@OverridepublicvoidaddBeanPostProcessor(BeanPostProcessorbeanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if anythis.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction awareif (beanPostProcessorinstanceofInstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors=true;
   }
if (beanPostProcessorinstanceofDestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors=true;
   }
// Add to end of listthis.beanPostProcessors.add(beanPostProcessor);
}

可以看到,在将一个 BeanPostProcessor 进行注册之前,会先将其移除。因此不会出现重复注册的问题,通过重复注册将一个 BeanPostProcessor 移动位置也说得通了。

后续

本文介绍了在 Spring 容器初始化过程中, BeanPostProcessor 注册的流程。有一点要提醒的是,这部分逻辑知识进行了 BeanPostProcessor 的注册,而并没有执行其中的处理方法,这些方法会在 Bean 的初始化过程中执行。

后续会接着分析 Spring 容器初始化之后的流程。

目录
相关文章
|
3天前
|
Java Spring
Spring的BeanPostProcessor后置处理器与bean的生命周期
Spring的BeanPostProcessor后置处理器与bean的生命周期
|
10天前
|
存储 Java 程序员
Spring 注册BeanPostProcessor 源码阅读
Spring 注册BeanPostProcessor 源码阅读
|
3天前
|
Java 数据库连接 Spring
Spring 整合 MyBatis 底层源码解析
Spring 整合 MyBatis 底层源码解析
|
4天前
|
Java Spring 容器
解读spring5源码中实例化单例bean的调用链
解读spring5源码中实例化单例bean的调用链
|
3天前
|
Java 程序员 Spring
Spring 源码阅读 一
Spring 源码阅读 一
|
3天前
|
Java 容器 Spring
Spring5源码解析5-ConfigurationClassPostProcessor (上)
Spring5源码解析5-ConfigurationClassPostProcessor (上)
|
4天前
|
Java Nacos 微服务
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
Spring Cloud微服务在Windows本地开发时禁用Nacos注册中心注册
|
4天前
|
缓存 Java 数据库连接
spring中注解驱动事务框架的源码
spring中注解驱动事务框架的源码
|
9天前
|
XML Java 数据格式
Spring容器启动源码解析
Spring容器启动源码解析
|
2月前
|
XML Java uml
spring 源码解析——第一篇(ioc xml方式)
spring 源码解析——第一篇(ioc xml方式)
39 0