Spring extension point one: BeanDefinitionRegistryPostProcessor

Spring provides a series of extension points, this article mainly records how BeanDefinitionRegistryPostProcessor can be extended to implement its own logic;

What can this extension point do

Before extending, we must first understand what this class is for
Insert picture description here

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;

}

From the provided method, you can see that the input parameter is a BeanDefinitionRegistry object. What does this object do? When spring adds beanDefinition to beanDefinitionMap, it calls the registerBeanDefinition method of the BeanDefinitionRegistry implementation class. Therefore, if we open this interface to see, we basically operate on beanDefinition, such as adding a beanDefinition to beanDefinitionMap; Or remove a beanDefinition; or modify the properties of a beanDefinition in the beanDefinitionMap, etc.

So, we can know that in this extended class, the beanDefinition in the beanDefinitionMap can be modified, a beanDefinition can be injected, a beanDefinition can be deleted, etc.

The injection method of the extension class

BeanDefinitionRegistryPostProcessor
is undoubtedly the most advanced in the entire spring startup process. Basically, in some underlying frameworks, except for class scanning through the extension interface, I have not seen other extension points. I I think the reason is: this extension point is too high, the implementation class of this interface, we can either do our own business logic before spring scans @ComponentScan, or we can do our own business logic after spring scans

The first implementation class

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

The second implementation class

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 class

@Configuration
@ComponentScan("com.spring.study.beandefinitionregistrypostprocessor")
@Import(MyImportBeanDefinitionRegistrar.class)
public class BeanFactoryConfig {
    
    
}

Start class

public class TestBDRPP {
    
    
    public static void main(String[] args) {
    
    
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
        ac.register(BeanFactoryConfig.class);
        ac.addBeanFactoryPostProcessor(new MyBeanFactoryPostProcessor01());

        ac.refresh();
    }
}

The above code, I wrote it myself demo; you can see, I wrote two implementation classes, respectively, by
one through the @Component annotation, so spring when scanning, scan to spring the implementation class vessels
two It is injected through AnnotationConfigApplicationContext.addBeanFactoryPostProcessor()

The timing of execution of these two injection methods is completely different

For the second injection method, it will be executed first. Before spring starts scanning the package corresponding to @ComponentScan, it will execute first.
For the first injection method, it relies on spring's scanning of @ComponentScan, so it is after this. Just executed

It can be seen from the print result:

通过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

When the implementation class injected through addBeanFactoryPostProcessor() is executed, there is no business bean of our own in beanDefinitionMap. When the beanDefinitionRegistryPostProcessor implementation class injected by @Component is executed, spring has completed the scan, and at this time we have us in beanDefinitionMap The business bean injected by myself

Source code

Next, let’s analyze why the execution timing of these two injection methods are different. This is related to the order of implementation of the spring source code.

org.springframework.context.support.AbstractApplicationContext#refresh
	org.springframework.context.support.AbstractApplicationContext#invokeBeanFactoryPostProcessors

The scanning of beans is done in this method, so let’s start with this code.

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

The comment also explains it more clearly. In the method, there is a key code: 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;
}

Let's look at the specific implementation process

PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors()

When the source code is executed, it will call here to execute the method of the implementation class according to the priority

/**
 * @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);
	}

}

I have deleted part of the code of this method. As you can see from the above, the List beanFactoryPostProcessors that enter the parameters are the implementation classes we added through the add method.
1. As you can see in the serial number 1, the implementation classes added through add will be first Carry out traversal
2. As seen here in the serial number 1.1, the implementation class of BeanDefinitionRegistryPostProcessor will be called and processed. The premise here is to add through the add method

At the very least, the code execution ends here, we see that the method of the implementation class added by add has been executed here in the serial number 1.1

When is the implementation class injected through the @Component annotation executed?
In the serial number 3.2 or the serial number 3.3, why might it be in two places? Because it depends on whether the implementation class declared by ourselves implements the Ordered interface. If it is implemented, it is in 3.2, and if it is not implemented, it is in 3.3.

Major premise

The implementation class injected through the @Component annotation, executed in 3.2 or 3.3, has a major premise, that is, this method depends on the serial number 3.1. Here, here, it is the location where spring resolves the @ComponentScan annotation, and spring performs automatic scanning, depending on Is ConfigurationClassPostProcessor

Insert picture description here
According to the inheritance and implementation relationship of the interface, it can be found that his PriorityOrdered implements this interface, so it will be executed in the position of serial number 3.1

The above is an analysis of how the extension mechanism of BeanDefinitionRegistryPostProcessor is extended and the corresponding principle.

Guess you like

Origin blog.csdn.net/CPLASF_/article/details/115004016