spring提供了一系列的扩展点,这篇主要记录BeanDefinitionRegistryPostProcessor如何进行扩展,实现自己的逻辑;
这个扩展点可以干什么
在扩展之前,首先要搞明白,这个类是来干什么的
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
@FunctionalInterface
public interface BeanFactoryPostProcessor {
/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}
从提供的方法中,可以看到,入参是一个BeanDefinitionRegistry对象,这个对象是干什么的?spring在向beanDefinitionMap中添加beanDefinition的时候,就是调用的BeanDefinitionRegistry实现类的registerBeanDefinition方法,所以,我们如果打开这个接口来看的话,基本上都是对beanDefinition进行操作的,比如:添加一个beanDefinition到beanDefinitionMap中;或者是remove一个beanDefinition;或者是修改beanDefinitionMap中某个beanDefinition的属性等等
所以,我们可以知道在这个扩展类中,可以对beanDefinitionMap中的beanDefinition进行修改、可以注入一个beanDefinition、可以删除一个beanDefinition等
扩展类的注入方式
BeanDefinitionRegistryPostProcessor
在整个spring启动的过程中,这个扩展点无疑是最为靠前的,基本上,在一些底层框架中,除了通过该扩展接口去进行class扫描之外,没见到过其他的扩展点,我觉得,原因是:这个扩展点太靠前,这个接口的实现类,我们既可以在spring扫描@ComponentScan之前去做自己的业务逻辑,也可以在spring扫描了之后去做自己的业务逻辑
第一个实现类
@Component
public class MyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
System.out.println("测试自己的beanDefinitionRegistry,通过@Component注解注入");
String[] beanDefinitionNames = beanDefinitionRegistry.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println("Component注解注入方式,打印此时的beanDefinition有:" + name);
}
GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionRegistry.getBeanDefinition("testUpdateAutowireMode");
beanDefinition.setAutowireMode(2);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
System.out.println("测试自己的beanFactory");
}
}
第二个实现类
public class MyBeanFactoryPostProcessor01 implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
String[] beanDefinitionNames = beanDefinitionRegistry.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println("通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:" + name);
}
System.out.println("测试自己的beanDefinitionRegistry01,通过addBeanFactoryPostProcessor注入");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory)
throws BeansException {
System.out.println("测试自己的beanFactory01");
}
}
configuration配置类
@Configuration
@ComponentScan("com.spring.study.beandefinitionregistrypostprocessor")
@Import(MyImportBeanDefinitionRegistrar.class)
public class BeanFactoryConfig {
}
启动类
public class TestBDRPP {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
ac.register(BeanFactoryConfig.class);
ac.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor01());
ac.refresh();
}
}
上面这个代码,是我自己写的demo;可以看到,我自己写了两个实现类,分别通过
一是通过@Component注解,让spring在扫描的时候,将该实现类扫描到spring容器中
二是通过AnnotationConfigApplicationContext.addBeanFactoryPostProcessor()这种方式来注入
这两种注入方式的执行时机是完全不一样的
对于第二种注入方式,会先执行,在spring还没有开始扫描@ComponentScan对应的包之前,就会先执行
对于第一种注入方式,是依赖于spring对@ComponentScan的扫描,所以是在此之后才执行的
从打印结果可以看出来:
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:org.springframework.context.annotation.internalCommonAnnotationProcessor
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:org.springframework.context.event.internalEventListenerProcessor
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:org.springframework.context.event.internalEventListenerFactory
通过addBeanFactoryPostProcessor注入,打印此时的beanDefinition有:beanFactoryConfig
测试自己的beanDefinitionRegistry01,通过addBeanFactoryPostProcessor注入
09:16:15.632 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
09:16:15.724 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\mpy\devWorkspace\spring-studycode\target\classes\com\spring\study\beandefinitionregistrypostprocessor\MyBeanFactoryPostProcessor.class]
09:16:15.724 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\mpy\devWorkspace\spring-studycode\target\classes\com\spring\study\beandefinitionregistrypostprocessor\TestUpdateAutowireMode.class]
importbeanDefinitionRegistrar执行
09:16:15.755 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'myBeanFactoryPostProcessor'
测试自己的beanDefinitionRegistry,通过@Component注解注入
Component注解注入方式,打印此时的beanDefinition有:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
Component注解注入方式,打印此时的beanDefinition有:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
Component注解注入方式,打印此时的beanDefinition有:org.springframework.context.annotation.internalCommonAnnotationProcessor
Component注解注入方式,打印此时的beanDefinition有:org.springframework.context.event.internalEventListenerProcessor
Component注解注入方式,打印此时的beanDefinition有:org.springframework.context.event.internalEventListenerFactory
Component注解注入方式,打印此时的beanDefinition有:beanFactoryConfig
Component注解注入方式,打印此时的beanDefinition有:myBeanFactoryPostProcessor
Component注解注入方式,打印此时的beanDefinition有:testUpdateAutowireMode
测试自己的beanFactory01
测试自己的beanFactory
在通过addBeanFactoryPostProcessor()注入的实现类在执行的时候,beanDefinitionMap中还没有我们自己的业务bean,在@Component注入的beanDefinitionRegistryPostProcessor实现类在执行的时候,spring已经完成了扫描,此时beanDefinitionMap中已经有我们自己注入的业务bean了
源码
接着来分析下为什么这两种注入方式的执行时机不同,这个和spring源码的实现先后顺序有关系了
org.springframework.context.support.AbstractApplicationContext#refresh
org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors
对于bean的扫描,是在这个方法完成的,所以,我们从这个代码开始看
AbstractApplicationContext#invokeBeanFactoryPostProcessors
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
/**
* getBeanFactoryPostProcessors 是获取手动给spring的beanFactoryPostProcessor,
* 自定义并不仅仅是程序员自己写的
* 自己写的可以加@Component,也可以不加
* 如果加了注解,getBeanFactoryPostProcessors()这里是获取不到的,加了注解的beanFactoryPostProcessor是spring自己扫描的
*
* 这里为什么得不到@Component注解修饰的BeanFactoryPostProcessor的实现类?因为这个方法是直接获取一个list,这个list是在AnnotationConfigApplicationContext中被定义的,只有在调用ac.addBeanFactoryPostProcessor();的时候,才会给list赋值
*
* 简单而言,这里说的自定义是指:程序员自己的bean,并且没有加@Component注解的类;(手动添加到spring容器中的)如果没有加注解,怎么交给spring呢?
* 在调用annotationConfigApplicationContext的refresh()方法之前 将自定义的beanFactoryPostProcessor添加到容器ac中
*
*
* 总结而言:
* 我们自己实现一个beanFactoryPostProcessor的实现类,交给spring有两种方式
* 1.通过api的方式:ac.addBeanFactoryPostProcessor();
* 但是这种方式,需要在refresh()方法之前执行,否则是没有意义的
* 这种方式注入的实现类如果是BeanDefinitionRegistrarPostProcessor的实现类,是在spring自动扫描之前就执行的,
* 如果是BeanFactoryPostProcessor的实现类,则是在spring自动扫描之后执行的;
* 2.通过添加@Component注解,这种方式是spring在扫描配置类的时候,会对@Component的实现类进行处理
*
* 而这里的getBeanFactoryPostProcessors(); 就是获取通过api的形式注入的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()));
}
}
注释中也解释的比较明白了,在方法中,有一个关键的代码:getBeanFactoryPostProcessors()
getBeanFactoryPostProcessors
// 在调用ac.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor01());的时候,会赋值给这个list集合
@Override
public void addBeanFactoryPostProcessor(BeanFactoryPostProcessor postProcessor) {
Assert.notNull(postProcessor, "BeanFactoryPostProcessor must not be null");
this.beanFactoryPostProcessors.add(postProcessor);
}
/**
* Return the list of BeanFactoryPostProcessors that will get applied
* to the internal BeanFactory. 在初始化流程中,会先调用这个list集合,获取到通过add方法添加的实现类
*/
public List<BeanFactoryPostProcessor> getBeanFactoryPostProcessors() {
return this.beanFactoryPostProcessors;
}
下面来看具体执行的过程
PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()
源码在执行的时候,会调用到这里按照优先级去执行实现类的方法
/**
* @param beanFactory
* @param beanFactoryPostProcessors
*
* 这里是对beanDefinitionRegistryPostProcessor和beanFactoryPostProcessor实现类的处理
* 1.先执行程序员通过API提供的beanDefinitionRegistryPostProcessor的实现类
* 2.执行spring中,实现了PriorityOrdered接口且实现了beanDefinitionRegistryPostProcessor接口的实现类
* 3.执行spring中,实现了Ordered接口且实现了beanDefinitionRegistryPostProcessor接口的实现类
* 4.执行spring中,只实现了beanDefinitionRegistryPostProcessor接口的实现类
* 5.执行实现了beanFactoryPostProcessor接口的实现类
*/
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
//这个set集合可以理解为存储的是已经执行过的beanDefinitionRegistryPostProcessor
Set<String> processedBeans = new HashSet<>();
/**
* 这里之所以要判断beanFactory是哪种类型的,应该和org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry(org.springframework.beans.factory.support.BeanDefinitionRegistry)
* 的入参有关系
*/
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
//regularPostProcessors这个list存储的是beanFactoryPostProcessor接口的实现类
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
//registryProcessors 这个list存储的是beanDefinitionRegistryPostProcessor接口的实现类
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
/**
* 序号1
* 这里的beanFactoryPostProcessors是程序员自己提供的BeanFactoryPostProcessor的实现类
*/
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
/**
* 区分当前bean是BeanDefinitionRegistryPostProcessor还是 beanFactoryPostProcessor
* 因为前者是后者的子类,所以在获取beanFactoryPostprocessor的时候 也可以获取到
*
* 在本方法中 是先执行实现了BeanDefinitionRegistryPostProcessor的类
* 再执行beanFactoryPostProcessor的类
* 序号1.1
*/
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// 这里会进行一个强转,因为有可能这里的postProcessor是BeanDefinitionRegistryPostProcessor的子接口的实现类,所以向上转型
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//这里直接执行程序员通过API注入的beanDefinitionRegistryPostProcessor的实现类
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 序号1.2 将beanFactoryPostProcessor添加到regularPostProcessors;执行到这里,说明postProcessor是BeanFactoryPostProcessor的实现类
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是用来存放spring中实现了beanFactoryRegistryPostProcessor接口的实现类
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
/**
* 序号2
*获取到了一个BeanDefinitionRegistryPostProcessor的实现类 -- ConfigurationClassPostprocessor
* 并且这里也只会获取到一个,因为截止到目前,spring容器中还没有我们自己写的业务类,只有spring自己注入的集合bean;
* 而这几个bean中,只有ConfigurationClassPostProcessor是BeanDefinitionRegistryPostProcessor的实现类
*
* 需要注意的是:
* 这个类在spring解析扫描初始化的时候用到了,ConfigurationClassPostProcessor是最重要的一个
*
* 所谓的合并bean,就是判断当前bean是否有父beanDefinition,如果有父beanDefinition,就把父beanDefinition和子beanDefinition合并到一起
* 在这里获取beanDefinitionRegistryPostProcessor类型的bean的时候,会对bean一个合并,也就是所谓的mergeBean
* 在后面finishBeanFactoryInitialization方法中,对bean进行实例化的时候,会再判断一次
*/
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
/**
* 序号3
* spring内部在执行BeanDefinitionRegistryPostProcessor的实现类的时候,是由顺序的
* 实现了PriorityOrdered接口的类 --> 实现了Ordered接口的类 --> other
*
*/
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
//排序,合并spring自己的和程序员自定义的beanFactoryRegistryPostProcessor
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
/**
* 序号3.1
* invokeBeanDefinitionRegistryPostProcessors这行代码,在本方法中调用了三次
* 这里是第一次调用,这是,理论上只有一个,就是ConfigurationClassPostProcessor
*
*/
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
/**
* 可以看到,在第二次和第三次从容器中获取实现类的时候,会先从已经执行过的集合中进行过滤(processedBeans)过滤
* 下面这个判断的意思是:ppName没有在processedBeans中,也就是没有执行过;且实现了Ordered接口;
*/
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
/**
* 序号3.2
* 这里是第二次调用,执行实现了Ordered接口的类
*/
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
/**
* 序号3.3
* 这里执行的是所有实现了beanDefinitionRegistryPostProcessor且无实现其他接口的类
*
* 这里为什么要用while(true)?
* 因为有可能beanDefinitionRegistryPostProcessor的实现类中有可能会又注入了一个beanDefinitionRegistryPostProcessor的实现类,所以这里要循环查找并执行;
* 如果第二次从beanFactory中没有找到beanDefinitionRegistryPostProcessor的实现类,那么,这里reiterate就是false,就不会再执行了
* 如果第二次从beanFactory中找到了未执行的实现类,那么就会继续执行,同时,reiterate变为true;然后进行下一轮的循环
*/
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);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
/**
* 序号4
* 前面说了,registryProcessors是保存beanDefinitionRegistryPostProcessor接口的实现类
* regularPostProcessors保存的是程序员提供的beanFactoryPostProcessor接口的实现类,
* 那为什么这里还会有 invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);这行代码?
* 原因很简单,一个接口在实现beanDefinitionRegistryPostProcessor接口的同时,必然会实现beanFactoryPostProcessor接口
* 所以,这里要执行
* registryProcessors中是spring内置的beanFactoryPostProcessor
* regularPostProcessors是程序员提供的beanFactoryPostProcessor
*
* 所以,spring源码中,
* 1.会先执行程序员提供的BeanDefinitionRegistryPostProcessor接口的实现类,
* 2.会执行spring自带的 BeanDefinitionRegistryPostProcessor接口的实现类
* 3.然后执行spring自带的 BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanFactory方法
* 4.最后执行程序员提供的 BeanDefinitionRegistryPostProcessor接口的实现类中的postProcessBeanFactory方法
*/
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
/**
* 如果beanFactory不是BeanDefinitionRegistry类型,就执行BeanFactoryPostProcessor的实现类
*/
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
}
这个方法的部分代码我进行了删减,从上面可以看到,入参的List beanFactoryPostProcessors就是我们通过add方法添加的实现类
1.在序号1这里可以看到,会先对通过add添加的实现类进行遍历
2.在序号1.1这里看到,会对BeanDefinitionRegistryPostProcessor的实现类进行调用处理,这里的前提是通过add方法添加的
最起码,代码执行到这里,我们看到,通过add添加的实现类的方法在序号1.1这里已经被执行了
对于通过@Component注解注入的实现类,是在什么时候被执行的呢?
在序号3.2或者序号3.3这里,为什么会有可能是在两个地方?因为要看我们自己声明的实现类有没有实现Ordered接口,如果实现了就是在3.2,没有实现,就是在3.3
大前提
通过@Component注解注入的实现类,在3.2或者3.3执行,有一个大前提,就是这种方式,依赖于序号3.1这里,在这里,是spring去解析@ComponentScan注解的位置,spring进行自动扫描,依赖的是ConfigurationClassPostProcessor
根据接口的继承、实现关系,可以发现,他PriorityOrdered实现了这个接口,所以会在序号3.1位置被执行
以上就是对BeanDefinitionRegistryPostProcessor这个扩展机制如何进行扩展、以及对应的原理进行了解析