Spring Framework 源码阅读(五):BeanFactoryPostProcessor
在上一篇博客中介绍了BeanPostProcessor和Bean的生命周期,BeanPostProcessor是允许自定义修改新bean实例的工厂钩子,在新bean实例初始化前后调用BeanPostProcessor中的方法,而通过FactoryBean创建的新bean实例和Spring通过反射创建的新bean实例在应用BeanPostProcessor方面有所不同,前者只会调用BeanPostProcessor中的postProcessAfterInitialization方法,而后者会调用BeanPostProcessor中的所有方法,想详细了解这些内容可以阅读这篇博客:
- Spring Framework 源码阅读(四):BeanPostProcessor和Bean的生命周期
那BeanFactoryPostProcessor有啥用?看命名跟BeanPostProcessor差不多,其实功能也差不多,都是自定义修改实例,只是修改的主体不同,BeanPostProcessor修改的主体是bean,而BeanFactoryPostProcessor修改的主体是bean定义,不了解bean定义,可以阅读这篇博客:
- Spring Framework 源码阅读(二):BeanDefinition的作用
注意,BeanFactoryPostProcessor和BeanPostProcessor都是自定义修改实例(实例主体不同),在两者应用时,实例肯定是已经实例化了(通过反射调用或者FactoryBean直接调用这两种方式,调用了实例类的构造函数)。
BeanFactoryPostProcessor接口源码如下(@FunctionalInterface表示该接口是函数式接口,可以使用lambda表达式直接赋值):
@FunctionalInterface
public interface BeanFactoryPostProcessor {
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
- 工厂钩子:允许自定义修改应用程序上下文(
application context)的 bean 定义,调整上下文底层 bean 工厂的 bean 属性值。对于自定义配置文件很有用,这些文件覆盖了应用程序上下文中配置的 bean 属性。 有关满足此类配置需求的开箱即用解决方案,请参阅PropertyResourceConfigurer及其具体实现。BeanFactoryPostProcessor可以与bean定义交互并修改bean定义,但绝不能与bean实例交互(这样做可能会导致 bean过早实例化、违反容器意愿并导致意外的副作用)。 如果需要与bean实例交互,请考虑实现BeanPostProcessor 。 - 注册:
ApplicationContext在其bean定义中自动检测BeanFactoryPostProcessor bean,并在创建任何其他bean之前应用它们。 BeanFactoryPostProcessor也可以通过ConfigurableApplicationContext以编程方式注册。 - 顺序:在
ApplicationContext中自动检测的BeanFactoryPostProcessor bean将根据PriorityOrdered和Ordered语义进行排序。 相比之下,使用ConfigurableApplicationContext以编程方式注册的BeanFactoryPostProcessor bean将按注册顺序应用; 对于以编程方式注册的PostProcessor,通过实现PriorityOrdered或Ordered接口表达的任何排序语义都将被忽略。 此外,@Order注解不会被BeanFactoryPostProcessor bean考虑在内。
博主早期的博客,可能排版不好看以及语言不严谨,也推荐阅读一下,可以对函数式接口(@FunctionalInterface)有一个直观的认识。
- JDK8 新特性Function接口
创建module
先在Spring Framework源码中增加一个application module,这在之前的博文中已经介绍过了,这里就不再赘述:
- 编译 Spring Framework 5.2.17源码 & 在源码中使用 ApplicationContext 获取定义的Bean

TaskBeanDefinitionProcess类(实现BeanFactoryPostProcessor接口):
package com.kaven.process;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.stereotype.Component;
import java.util.Objects;
/**
* @Author: ITKaven
* @Date: 2021/11/03 10:34
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@Component
public class TaskBeanDefinitionProcess implements BeanFactoryPostProcessor {
// 将自定义的作用域字符串myScope转换成singleton
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition bd = beanFactory.getBeanDefinition("myTask");
if(Objects.equals(bd.getScope(), "myScope")) {
bd.setScope("singleton");
}
}
}
启动类Application:
package com.kaven;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.*;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @Author: ITKaven
* @Date: 2021/09/25 13:54
* @Leetcode: https://leetcode-cn.com/u/kavenit
* @Notes:
*/
@ComponentScan({"com.kaven"})
public class Application {
public static void main(String[] args) {
// 创建应用上下文
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
// 在应用上下文中添加BeanFactoryPostProcessor
// 将myTask bean的BeanDefinition的懒加载设置为false
applicationContext.addBeanFactoryPostProcessor((beanFactory) -> {
beanFactory.getBeanDefinition("myTask").setLazyInit(false);
});
// 注册组件类
applicationContext.register(Application.class);
// refresh
applicationContext.refresh();
// 获取myTask bean
Task task = (Task) applicationContext.getBean("myTask");
System.out.println("taskCount: " + task.addTask());
// 获取myTask bean的BeanDefinition
BeanDefinition taskBeanDefinition = applicationContext.getBeanDefinition("myTask");
System.out.println(taskBeanDefinition.getScope());
System.out.println(taskBeanDefinition.isLazyInit());
// 获取应用上下文中的BeanDefinition数量和名称
System.out.println("BeanDefinitionCount: " + applicationContext.getBeanDefinitionCount());
Arrays.stream(applicationContext.getBeanDefinitionNames()).forEach(System.out::println);
}
// myTask bean
@Bean(value = "myTask")
@Scope("myScope")
@Lazy
public Task getTask() {
return new Task();
}
public static class Task{
private final AtomicInteger taskCount;
public Task() {
taskCount = new AtomicInteger(0);
}
public int addTask() {
return taskCount.incrementAndGet();
}
}
}
输出结果:
taskCount: 1
singleton
false
BeanDefinitionCount: 7
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
application
taskBeanDefinitionProcess
myTask
很显然符合预期,myTask bean的作用域从自定义作用域字符串myScope转换成了singleton,懒加载也设置成了false,这些都是因为TaskBeanDefinitionProcess类的postProcessBeanFactory方法以及下方的lambda表达式起作用了。
(beanFactory) -> {
beanFactory.getBeanDefinition("myTask").setLazyInit(false);
}源码分析
开始Debug。


执行这行代码:
applicationContext.refresh();
调用了AbstractApplicationContext抽象类的refresh方法(删除了部分代码):
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// 准备此上下文以进行刷新
prepareRefresh();
// 告诉子类刷新内部bean工厂
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 准备在此上下文中使用的bean工厂
prepareBeanFactory(beanFactory);
try {
// 允许在上下文子类中对bean工厂进行postProcess
postProcessBeanFactory(beanFactory);
// 调用在上下文中注册的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactory);
// 注册BeanPostProcessor
registerBeanPostProcessors(beanFactory);
// 初始化此上下文的消息源
initMessageSource();
// 为此上下文初始化事件多播器
initApplicationEventMulticaster();
// 初始化特定上下文子类中的其他特殊bean
onRefresh();
// 检查监听器bean并注册它们
registerListeners();
// 实例化所有剩余的(非延迟加载)单例
finishBeanFactoryInitialization(beanFactory);
// 发布相应的事件
finishRefresh();
}
}
}
之后会调用PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors方法(删除了部分代码,看注释即可):
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 如果有的话,首先调用BeanDefinitionRegistryPostProcessor
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
// 调用BeanDefinitionRegistryPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 调用到目前为止处理的所有处理器的postProcessBeanFactory回调
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// 调用在上下文实例中注册的BeanFactoryPostProcessor
// 但beanFactory不能instanceof BeanDefinitionRegistry
// 如果beanFactory instanceof BeanDefinitionRegistry
// 执行上面的invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory)
// 也会调用在上下文实例中注册的BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 获取BeanFactoryPostProcessor bean的名称
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// 调用BeanFactoryPostProcessor
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// 清除缓存的合并bean定义
// 因为BeanFactoryPostProcessor可能已经修改了原始元数据,例如替换值中的占位符
beanFactory.clearMetadataCache();
}
BeanDefinitionRegistryPostProcessor接口源码:
// 对标准BeanFactoryPostProcessor SPI的扩展
// 允许在常规BeanFactoryPostProcessor检测开始之前注册bean定义
// 特别是, BeanDefinitionRegistryPostProcessor可以注册BeanFactoryPostProcessor bean定义。
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
// 在标准初始化之后修改应用程序上下文的内部bean定义注册表
// 所有常规bean定义都将被加载,但尚未实例化任何bean
// 这允许在下一个后处理阶段开始之前添加更多的bean定义
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
所以,BeanFactoryPostProcessor应用时,bean定义已经注册好了,和前面描述的一致。
但我们并没有提供BeanDefinitionRegistryPostProcessor接口的实现,为什么还能注册bean定义?还记得代码的输出结果中有几个Spring内置的bean定义:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
org.springframework.context.annotation.internalConfigurationAnnotationProcessor对应的bean类是ConfigurationClassPostProcessor类。
这在BeanDefinition的作用这篇博客中有介绍。
/**
* 内部管理Configuration注解的处理器的bean名称
*/
public static final String CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME =
"org.springframework.context.annotation.internalConfigurationAnnotationProcessor";
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}
ConfigurationClassPostProcessor类(实现了BeanDefinitionRegistryPostProcessor接口):
// 这个PostProcessor是优先级排序的,因为在任何其他BeanFactoryPostProcessor执行之前
// 在@Configuration类中声明的任何@Bean方法都必须注册其相应的bean定义,这一点很重要
public class ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor,
PriorityOrdered, ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware {
...
}
当然我们这里没有使用@Configuration注解,但很显然@ComponentScan({"com.kaven"})的效果也是类似的。
再回到PostProcessorRegistrationDelegate类的invokeBeanFactoryPostProcessors方法,通过Debug,可以知道在调用invokeBeanFactoryPostProcessors方法前,如下图所示的5个bean定义就已经注册了,这在BeanDefinition的作用这篇博客中有介绍,这里不再赘述。所以,还剩下myTask和taskBeanDefinitionProcess这两个bean的bean定义没有注册。

调用了ConfigurationClassPostProcessor类的postProcessBeanDefinitionRegistry方法后,myTask和taskBeanDefinitionProcess这两个bean的bean定义也会被注册。

而myTask bean的bean定义还没有被修改,因为自定义的两个BeanFactoryPostProcessor还没有应用。

在这里会应用使用lambda表达式定义的BeanFactoryPostProcessor(beanFactory instanceof BeanDefinitionRegistry为true,不然下面else部分那一行代码也会执行该BeanFactoryPostProcessor)。


懒加载设置成了false,而作用域还是自定义的作用域字符串myScope。

在这里会应用我们实现的BeanFactoryPostProcessor(TaskBeanDefinitionProcess类)。


到这里作用域也修改成功了。

BeanFactoryPostProcessor能被应用,说明这些BeanFactoryPostProcessor bean已经创建好了(能修改其他bean的bean定义,当然需要提取创建好,以便应用,当然使用lambda表达式定义的BeanFactoryPostProcessor不需要被创建,类似使用匿名内部类,本身就是一个实例,只是原理有些不同):

invokeBeanFactoryPostProcessors方法开始执行时,还没有已经创建的对象。

执行完下面这部分代码,ConfigurationClassPostProcessor类对应的bean就被创建好了(通过beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)创建),该bean也会注册之前说过的那两个bean定义。
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();

执行完下面这部分代码,BeanFactoryPostProcessor bean(TaskBeanDefinitionProcess实例)也创建好了(通过beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)创建)。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}

通过上面的分析,可以知道BeanFactoryPostProcessor可以用于注册bean定义以及修改bean定义等,修改bean定义时,这些bean定义已经注册到了bean工厂中。
阅读源码需要耐心,一步步进行Debug,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。










