一、基础知识
BFPP和BDRPP介绍
BeanFactoryPostProcessor的主要作用是对Bean的定义信息进行修改,即修改BeanDefinition。
一种比较常见的操作就是对BeanDefinition中的占位符替换成实际的值,如:
> <bean id="person" class="com.yk.entity.Person">
> <property name="id" value="${person.id}"/>
> <property name="name" value="${person.name}"/>
> </bean>
BeanDefinitionRegistryPostProcessor,是对BeanFactoryPostProcessor的一种扩展,BeanFactoryPostProcessor只侧重于对容器中的BeanDefinition进行修改,而BeanDefinitionRegistryPostProcessor除了具有BeanDefinitionPostProcessor的功能之外还可以对容器中的BeanDefinition进行增加和删除操作。
类图:
BFPP代码:
public interface BeanFactoryPostProcessor {
// 传入的是ConfigurableListableBeanFactory类型的对象
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
BDRPP代码:
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
// 传入的是BeanDefinitionRegistry
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
二、自定义BFPP
自定义BFPP,只需要实现BeanFactoryPostProcessor
接口并实现postProcessBeanFactory
方法就行。
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("Execute MyBeanFactoryPostProcessor.postProcessBeanFactory");
}
}
定义了BFPP之后,Spring并不能自动识别到自定义的BFPP,需要我们做些额外的操作才行。
让Spring识别到自定义的BFPP的两种方式:
- 方式一:
将自定义的BFPP作为一个Bean定义到配置文件中,即:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 自定义的BFPP -->
<bean class="com.yk.bfpp.MyBeanFactoryPostProcessor"></bean>
<!-- 自定义的BDRPP -->
<bean class="com.yk.bfpp.MyBeanFactoryRegistryPostProcessor"></bean>
</beans>
- 方式二:
在创建完IOC容器之后,有一个customizeBeanFactory
的方法,我们通过重写这个方法,可以进行一些扩展实现。
protected final void refreshBeanFactory() throws BeansException {
// ......
try {
DefaultListableBeanFactory beanFactory = createBeanFactory();
// ......
// 重新这个方法进行扩展实现
customizeBeanFactory(beanFactory);
// ......
}
// ......
}
这个方法在AbstractRefreshableApplicationContext
这个Java类中,直接继承这个文件是否可行?首先查看下我们常用的ApplicationContext
是ClassPathXmlApplicationContext
,查看一下两者的关系:
通过类图可以发现,ClassPathXmlApplicationContext
是AbstractRefreshableApplicationContext
的一个子类,所以我们可以直接继承ClassPathXmlApplicationContext
,并重新customizeBeanFactory
方法,如果直接继承AbstractRefreshableApplicationContext
我们的ApplicationContext会丢失掉AbstractXmlApplicationContext
和ClassPathXmlApplicationContext
中实现的功能。
两种实现方式有什么区别?
通过配置文件注册的BFPP和BDRPP会在解析XML配置文件的时候被解析成BeanDefinition,而通过
customizeBeanFactory
注册的BFPP和BDRPP不会被解析成BeanDefinition,我们在注册的时候就已经将其实例化。
BFPP的执行顺序
上面是实现BFPP的最简单形式,如果想改变下BFPP在系统中的执行顺序,可以让BFPP实现
Ordered
接口或者PriorityOrdered
接口,其中实现PriorityOrdered
接口的BFPP会优先与实现了Ordered
接口的BFPP,实现了Ordered
接口的BFPP会优先与未实现Ordered
和PriorityOrdered
接口的BFPP;
三、自定义BDRPP
实现方式与BFPP大致相同。
四、BFPP在Spring中的执行流程分析
在
AbstractApplicationContext
中的refresh()
方法中会调用invokeBeanFactoryPostProcessors()
方法,这个方法就是用来执行调用并执行BFPP的
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 执行BFPP的过程就是在这行代码中实现的
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// ......
}
上述代码首先会执行getBeanFactoryPostProcessors()
方法,通过方法名猜测出它是来获取BFPP的?
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
// private final List<BeanFactoryPostProcessor> beanFactoryPostProcessors = new ArrayList<>();
return this.beanFactoryPostProcessors;
}
可以看出,这个方法返回的是一个BFPP的列表,但这里并不是我们容器中所有的BFPP,而是我们通过重写customizeBeanFactory
并在方法中添加类似于:this.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor());
这种代码注册进去的,而我们通过配置文件的并没有被注册到这个列表中,而是和其他Bean一样,被解析成了BeanDefinition,那这两种方式注册的BFPP分别是怎么被执行的?
执行流程:
- 首先是对通过
customizeBeanFactory
注册的BFPP和BDRPP进行处理- 如果是BDRPP,那么就执行BDRPP的
postProcessBeanDefinitionRegistry
方法,并将其加入到一个集合中; - 如果是BFPP,那么就将其加入到另外一个集合中;
- 如果是BDRPP,那么就执行BDRPP的
- 继续获取BDRPP,此时获取的是通过XML配置文件注册的和系统中提供的BDRPP,它们都会被解析成BeanDefinition。
- 获取所有的实现了
PriorityOrdered
接口的BDRPP,对它们排序并依次执行postProcessBeanDefinitionRegistry
方法; - 获取所有的实现了
Ordered
接口的BDRPP,对它们排序并依次执行postProcessBeanDefinitionRegistry
方法; - 获取剩余的BDRPP并依次执行
postProcessBeanDefinitionRegistry
方法;
- 获取所有的实现了
- 经过上面的两步操作,系统中所有的BDRPP都被记录在集合中,因为它们是BFPP的子类,所以它们也是BFPP,这里就是执行它们继承的BFPP的
postProcessBeanFactory
方法; - 获取系统中的BFPP,并按照实现
PriorityOrdered
,Ordered
和未实现上面两个接口进行分组执行- 执行实现了
PriorityOrdered
接口的BFPP,对它们排序并依次执行postProcessBeanFactory
方法,若上面步骤中已经执行过则跳过执行操作; - 执行实现了
Ordered
接口的BFPP,对它们排序并依次执行postProcessBeanFactory
方法,若上面步骤中已经执行过则跳过执行操作; - 执行剩余的BFPP的
postProcessBeanFactory
方法,若上面步骤中已经执行过则跳过执行操作;
- 执行实现了
- 到这里系统中所有的BDRPP和BFPP都已经处理完成。
下面是具体的代码及详细注释:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// 总的执行思路:
// 因为BeanDefinitionRegistryPostProcessor可能会生成新的BeanDefinition,而BeanFactoryPostProcessor
// 可能会对每一个BeanDefinition进行处理,所以BeanDefinitionRegistryPostProcessor必须要在
// BeanFactoryPostProcessor执行之前进行执行。
// 存放已经调用执行过的BeanFactoryPostProcessor的beanName
Set<String> processedBeans = new HashSet<>();
// 先处理通过重写customizeBeanFactory方法注册到容器中的BeanFactoryPostProcessor
// beanFactory默认是DefaultListableBeanFactory,if条件成立
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 存放BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 存放BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 如果当前postProcessor是BeanDefinitionRegistryPostProcessor,会先执行
// 当前postProcessor的postProcessBeanDefinitionRegistry方法,然后把当前
// postProcessor添加到registryProcessor集合中
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 如果当前postProcessor就是一个普通的BeanFactoryPostProcessor,那么把当前
// postProcessor加入到regularPostProcessors
regularPostProcessors.add(postProcessor);
}
}
// 到这里为止,通过customizeBeanFactory方法注册到容器中的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry均已经执行完成。
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// 从这里开始,处理的是通过配置文件注册的自定义的BeanDefinitionRegistryPostProcessor和系统中提供的BeanDefinitionRegistryPostProcessor
// 从容器中获取到类型为BeanDefinitionRegistryPostProcessor的beanName的一个数组
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 获取到实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 这里会创建BeanDefinitionRegistryPostProcessor类型的对象
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 获取到实现了Ordered接口的BeanDefinitionRegistryPostProcessor
// 上面已经获取过一次了,这里重复获取的原因是在上面执行BDRPP的postProcessBeanDefinitionRegistry方法时可能会生成新的BDRPP
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 这里会创建BeanDefinitionRegistryPostProcessor类型的对象
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// 接下来是处理剩余的还未被处理的BDRPP
boolean reiterate = true;
// 这里循环执行原因依然是执行BDRPP的postProcessBeanDefinitionRegistry可能会生成新的BDRPP,所以循环执行,直至所有的BDRPP都被处理过。
while (reiterate) {
reiterate = false;
// 依然要重复获取,原因同上
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
// 排序
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
// 执行BeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// 方法执行到这里,所有的BDRPP的postProcessBeanDefinitionRegistry都已被执行完成。
// 接下来就是执行BFPP和BDRPP的postProcessBeanFactory方法
// 这里执行用户自定义的BDRPP和Spring中定义的BDRPP的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
// 这里执行用户自定义的BFPP的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// 方法执行到这里,所有自定义的BFPP和系统中所有的BDRPP均已调用完成,接下来就是处理系统中的BFPP
// 获取系统中的BFPP,这里获取的BFPP包括通过配置文件注册到Spring中的自定义的BFPP和系统中自带的BFPP
// 获取BeanFactoryPostProcessor类型的beanName
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
// 遍历获取到的BFPP
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// BFPP已经被处理过则不做任何操作
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 实现了PriorityOrdered接口的BFPP,这里通过getBean会创建BFPP类型的对象,所以下面在执行BFPP的时候不需要再进行对象创建
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
// 实现了Ordered接口的BFPP,这里存入的只是beanName
orderedPostProcessorNames.add(ppName);
}
else {
// 剩余的BFPP,这里存入的只是beanName
nonOrderedPostProcessorNames.add(ppName);
}
}
// 对实现了PriorityOrdered接口的BFPP进行排序,然后执行BFPP的postProcessBeanFactory方法
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// 对实现了Ordered接口的BFPP进行实例化,然后排序和执行postProcessBeanFactory方法
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// 对未实现了PriorityOrdered和Ordered接口的BFPP(也就是剩余的BFPP)进行实例化,然后执行postProcessBeanFactory方法
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
beanFactory.clearMetadataCache();
}
参考链接:
https://blog.csdn.net/aqin1012/article/details/125189197
参考书籍:
《Spring源码深度解析第二版》