likes
comments
collection
share

Spring 源码阅读 14:注册 BeanPostProcessor

作者站长头像
站长
· 阅读数 18

基于 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 接口。

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 中的两个方法。具体见下图:

Spring 源码阅读 14:注册 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);
   }
}

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

// 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);

两段相同的逻辑如下:

  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(new ApplicationListenerDetector(applicationContext));

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

重复注册和顺序

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

  1. 将实现了 MergedBeanDefinitionPostProcessor 的 BeanPostProcessor 放到一个内部后处理器的列表中时,并没有在原来的列表中移除,这不是重复注册了吗?
  2. 为什么重新注册一个 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 容器初始化之后的流程。