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