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
,每个人的理解不同,如果博主有说错的地方或者大家有不同的见解,欢迎大家评论补充。