spring扩展点一:BeanDefinitionRegistryPostProcessor

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这个扩展机制如何进行扩展、以及对应的原理进行了解析

猜你喜欢

转载自blog.csdn.net/CPLASF_/article/details/115004016
今日推荐