一、概述
- 本方法会实例化和调用所有
BeanFactoryPostProcessor
(包括其子类BeanDefinitionRegistryPostProcessor
)。 BeanFactoryPostProcessor
接口是 Spring 初始化BeanFactory
时对外暴露的扩展点,Spring IoC
容器允许BeanFactoryPostProcessor
在容器实例化任何 bean 之前读取 bean 的定义,并可以修改它。BeanDefinitionRegistryPostProcessor
继承自BeanFactoryPostProcessor
,比BeanFactoryPostProcessor
具有更高的优先级,主要用来在常规的 BeanFactoryPostProcessor 检测开始之前注册其他 bean 定义。(关于BeanDefinitionRegistryPostProcessor
更加详细一些的介绍可以查看这边博客中的内容:https://www.cnblogs.com/tdyang/p/12088554.html)- 特别是,你可以通过 BeanDefinitionRegistryPostProcessor 来注册一些常规的 BeanFactoryPostProcessor,因为此时所有常规的 BeanFactoryPostProcessor 都还没开始被处理。
注:这边的 “常规 BeanFactoryPostProcessor” 主要用来跟 BeanDefinitionRegistryPostProcessor 区分。
首先我们回到AbstractApplicationContext.refresh()
方法,找到代码:invokeBeanFactoryPostProcessors(beanFactory)
,单击该行代码跳转到具体的实现。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 1.getBeanFactoryPostProcessors(): 拿到当前应用上下文beanFactoryPostProcessors变量中的值
// 2.invokeBeanFactoryPostProcessors: 实例化并调用所有已注册的BeanFactoryPostProcessor
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
1.拿到当前应用上下文 beanFactoryPostProcessors
变量中的值,见代码块1详解。
2.实例化并调用所有已注册的 BeanFactoryPostProcessor
,见代码块2详解。
二、getBeanFactoryPostProcessors
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
这边 getBeanFactoryPostProcessors()
会拿到当前应用上下文中已经注册的BeanFactoryPostProcessor
,在默认情况下,this.beanFactoryPostProcessors
是返回空的。
如何添加自定义 BeanFactoryPostProcessor 到 this.beanFactoryPostProcessors 变量中了?
该成员变量的值是哪里设置的呢?查找后发现,来自AbstractApplicationContext.addBeanFactoryPostProcessor()
方法被调用的时候设置的。
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
AbstractApplicationContext.addBeanFactoryPostProcessor()
方法是留给业务扩展时调用的,例如在springboot初始化时,ConfigurationWarningsApplicationContextInitializer
类的initialize
方法中就有调用:
@Override
public void initialize(ConfigurableApplicationContext context) {
context.addBeanFactoryPostProcessor(
new ConfigurationWarningsPostProcessor(getChecks()));
}
三、invokeBeanFactoryPostProcessors
invokeBeanFactoryPostProcessors
方法是:调用beanFactory
的后置处理器,后面s表示复数,该方法两个参数:beanFactory
一个单对象,和beanFactoryPostProcessors
1个beanFactory
后置处理器列表。- bean后置处理器处理的是bean实例
- beanfactory后置处理器处理的是bean的定义,就是尚未实例化的bean
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<String>();
// 1.判断beanFactory是否为BeanDefinitionRegistry,beanFactory为DefaultListableBeanFactory,
// 而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口,因此这边为true
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用于存放普通的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<BeanFactoryPostProcessor>();
// 用于存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<BeanDefinitionRegistryPostProcessor>();
// 2.首先处理入参中的beanFactoryPostProcessors
// 遍历所有的beanFactoryPostProcessors, 将BeanDefinitionRegistryPostProcessor和普通BeanFactoryPostProcessor区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// 2.1 如果是BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 2.1.1 直接执行BeanDefinitionRegistryPostProcessor接口的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
// 2.1.2 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
registryProcessors.add(registryProcessor);
} else {
// 2.2 否则,只是普通的BeanFactoryPostProcessor
// 2.2.1 添加到regularPostProcessors(用于最后执行postProcessBeanFactory方法)
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// =====================================================================
// 这后面的代码都是执行的是第一个参数beanFactory的获取到的BeanFactoryPostProcessor
// 用于保存本次要执行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<BeanDefinitionRegistryPostProcessor>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 3.调用所有实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor实现类
// 3.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的Bean的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 3.2 遍历postProcessorNames
for (String ppName : postProcessorNames) {
// 3.3 校验是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 3.4 获取ppName对应的bean实例, 添加到currentRegistryProcessors中,
// beanFactory.getBean: 这边getBean方法会触发创建ppName对应的bean对象, 目前暂不深入解析
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 3.5 将要被执行的加入processedBeans,避免后续重复执行
processedBeans.add(ppName);
}
}
// 3.6 进行排序(根据是否实现PriorityOrdered、Ordered接口和order值来排序)
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 3.7 添加到registryProcessors(用于最后执行postProcessBeanFactory方法)
// 因为实现了BeanDefinitionRegistryPostProcessor接口的类,会执行两个方法,
// 第一个方法是:postProcessBeanDefinitionRegistry方法
// 第二个方法是:postProcessBeanFactory方法,这个方法放在后面执行
registryProcessors.addAll(currentRegistryProcessors);
// 3.8 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 3.9 执行完毕后, 清空currentRegistryProcessors
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// 4.调用所有实现了Ordered接口的BeanDefinitionRegistryPostProcessor实现类(过程跟上面的步骤3基本一样)
// 4.1 找出所有实现BeanDefinitionRegistryPostProcessor接口的类, 这边重复查找是因为执行完上面的BeanDefinitionRegistryPostProcessor,
// 可能会新增了其他的BeanDefinitionRegistryPostProcessor, 因此需要重新查找
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 校验是否实现了Ordered接口,并且还未执行过
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 4.2 遍历currentRegistryProcessors, 执行postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
1.判断beanFactory
是否为 BeanDefinitionRegistry
。beanFactory
是在之前的 obtainFreshBeanFactory
方法获取的,obtainFreshBeanFactory
方法如果这里是基于注解的情况下,是在初始化的时候就已经是构建好的,初始化的时候构建的是DefaultListableBeanFactory
。而 DefaultListableBeanFactory
实现了BeanDefinitionRegistry
接口,因此beanFactory instanceof BeanDefinitionRegistry
结果为 true
。
3.4 获取ppName
对应的 bean
实例,添加到 currentRegistryProcessors
中,准备执行。beanFactory.getBean
方法会触发创建 ppName 对应的 bean 实例对象
,创建 bean 实例是 IoC 的另一个核心内容,之后会单独解析,目前暂不深入解析。
优秀的博主:https://www.zhihu.com/people/opiece.me/posts
四、基本使用
我们通常在使用 Mybatis + Spring 时,经常用到的 org.mybatis.spring.mapper.MapperScannerConfigurer 就是一个BeanDefinitionRegistryPostProcessor。MapperScannerConfigurer 在 postProcessBeanDefinitionRegistry 方法中进行了一些操作,主要是:扫描 basePackage 指定的目录,将该目录下的类(通常是 DAO/MAPPER 接口)封装成 BeanDefinition 并加载到 BeanFactory 中。因此,我们可以看到我们项目中的 DAO(MAPPER)接口,通常都没有使用注解或 XML 的方式注册到 Spring 容器,但是我们还是可以在 Service 服务中,使用 @Autowire 注解来将其注入到 Service 中,就是因为这个原因。
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--basePackage指定要扫描的包,在此包之下的映射器都会被搜索到。可指定多个包,包与包之间用逗号或分号分隔-->
<property name="basePackage" value="com.joonwhee.open.demo.mapper"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>