BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor用法与原理
BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor都是接口,BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口。实现类用来修改Spring容器的beanDefinition行为的,注意这里的两个不是bean的后置处理器,可以称为bean工厂的后置处理器和bean注册中心的后置处理器,针对的时beanDefinition的map,并不是单个的beanDefinition,关键的一点是,此时的这些bean还没有被实例化。具体用法参考下面例子。
用法案例
-
搭建一个spring环境,本案例使用5.2.10版本,配置文件
<?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:tx="http://www.springframework.org/schema/tool" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tool http://www.springframework.org/schema/tool/spring-tool.xsd"> <bean id="user" class="com.li.study.bean.User"/> </beans>
创建两个测试bean,省略get,set方法,重写toString()方法
public class User { private String name="li"; public User(String name) { this.name = name; } public User() { } }
public class Studant { private int id; private String name; private int age; public Studant() { } }
测试主程序入口
public class TestBean { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); // AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); final Object bean = context.getBean("user"); System.out.println(bean); } }
执行结果:User{name=‘li’}
-
由于BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子接口,这里只测试BeanDefinitionRegistryPostProcessor接口功能。创建一个实现BeanDefinitionRegistryPostProcessor接口的类MyBeanDefinitionRegistryPostProcessor
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { GenericBeanDefinition beanDefinition = (GenericBeanDefinition) registry.getBeanDefinition("user"); System.out.println("修改user的类型"); beanDefinition.setBeanClass(Studant.class); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Object bean = beanFactory.getBean("user"); System.out.println(bean+"\tbean的hash值="+bean.hashCode()); } }
将加入到上面的xml配置中,再次执行,查看结果:
修改user的类型 Studant{id=0, name='null', age=0} bean的hash值=1223685984 Studant{id=0, name='null', age=0}
通过观察结果可以发现,bean的类型发生了改变,因为在实例化bean之前通过MyBeanDefinitionRegistryPostProcessor中的postProcessBeanDefinitionRegistry方法改变了bean的类型,在postProcessBeanFactory方法中将bean实例化。可以判断出两个方法的执行顺序。
-
总结
通过两个方法的参数可以推断出两个方法的作用,BeanDefinitionRegistry只可以获取,修改beanDefinition,ConfigurableListableBeanFactory不但可以修改beanDefinition,还可以getBean(),也就是实例化某个bean,将bean的实例化过程提前,可以满足用户的某些特殊需求。除此之外,可以配置多个实现BeanDefinitionRegistryPostProcessor接口的bean,会按照被加载的顺序执行,并且可以通过配置指定执行的先后顺序。
原理分析
通过分析源代码的方式解释上述案例,以下源码分析需要spring源码基础,不可能从头开始介绍spring源码。如果不熟悉可能会引起不适,请做好准备。
首先说明,本阶段是bean加载完成后,实例化之前。
源码入口在AbstractApplicationContext类的public void refresh() 方法中的invokeBeanFactoryPostProcessors(beanFactory);往下走一步就来到这个方法,这里有全部的实现逻辑。
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
//这里beanFactory的类型DefaultListableBeanFactory,通过xml配置加载容器
//就是实例化的DefaultListableBeanFactory对象,DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
if (beanFactory instanceof BeanDefinitionRegistry)
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
//beanFactoryPostProcessors获取的是容器本身的beanFactory后置处理器,不包括在用户自定义的
//这里逻辑就是将BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor分开处理
//先执行所有postProcessBeanDefinitionRegistry方法
//找到所有的BeanFactoryPostProcessor接口保存到regularPostProcessors起来,先不执行
for (beanFactoryPostProcessors postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
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.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
//找到所有实现BeanDefinitionRegistryPostProcessor的bean的name
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//实例化同时实现类PriorityOrdered接口的bean,保存到currentRegistryProcessors
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
//BeanFactoryPostProcessor接口的方法保存,先不执行
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);//排序
registryProcessors.addAll(currentRegistryProcessors);
//只执行同时实现PriorityOrdered接口的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
//实例化同时实现Ordered接口的
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);//排序
registryProcessors.addAll(currentRegistryProcessors);
//只执行同时实现Ordered接口的postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
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);
//执行所有postProcessBeanDefinitionRegistry方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
//执行所有找到的BeanDefinitionRegistryPostProcessor接口中的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
//执行所有找到的BeanFactoryPostProcessor接口中的postProcessBeanFactory方法
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
//到此,执行了所有实现了的BeanDefinitionRegistryPostProcessor接口的postProcessBeanFactory方法,包括内置的和自定义的
//执行了所有内置的实现类BeanFactoryPostProcessor接口中的postProcessBeanFactory方法,不包括自定义配置的
//下面的逻辑就是,寻找,实例化自定义的BeanFactoryPostProcessor接口并执行
//找到所有实现BeanFactoryPostProcessor接口的bean的name
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//实现PriorityOrdered接口的
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
//实现Ordered接口的
orderedPostProcessorNames.add(ppName);
}
else {
//普通的
nonOrderedPostProcessorNames.add(ppName);
}
}
//执行实现PriorityOrdered接口的
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);//排序
//执行实现Ordered接口的
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
//最后执行其他的
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
整个代码虽然长,但是逻辑还是比较清晰的,总结起来就是
- 按顺序查找,实例化,执行,内置的,实现 PriorityOrdered接口的,实现Ordered接口的和正常的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry方法,
- 将所有的BeanDefinitionRegistryPostProcessor的父接口BeanFactoryPostProcessor保存起来,然后执行postProcessBeanFactory方法
- 按顺序查找,实例化,执行内置的,实现 PriorityOrdered接口的,实现Ordered接口的和正常的BeanFactoryPostProcessor的行postProcessBeanFactory方法