文档章节

Spring5 源码分析-容器刷新-invokeBeanFactoryPostProcessors()方法

特拉仔
 特拉仔
发布于 11/13 12:28
字数 1153
阅读 24
收藏 0

【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>>

上一篇:Spring5 源码分析-容器刷新-prepareBeanFactory()方法 

该方法主要完成以下功能:


1.实例化ConfigurationClassPostProcessor,并调用ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry方法完成对配置类的解析,并对解析结果进行对应动作的执行,比如
1.1处理配置类的嵌套类的配置(这是一个递归的操作)
1.2处理PropertySource
1.3处理@ComponentScan
1.4执行@Import
1.5执行@ImportSource
1.6执行@Bean

2.添加ImportAwareBeanPostProcessor

3.实例化EventListenerMethodPostProcessor

 

方法大致执行逻辑:

这个方法几乎一直在干同一种事情,也就是找到对应的PostProcessor进行调用,包含BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor两种类型。

BeanDefinitionRegistryPostProcessor:用于注册BeanDefinition,它的典型实现类有ConfigurationClassPostProcessor

BeanFactoryPostProcessor:用于获取或者修改容器中的BeanDefinition等

在分别对两种类型的PostProcessor进行处理的时候都是按照“PriorityOrder->Order->两者都不是”顺序执行的,一旦被执行过的PostProcessor在后面就不会被执行了。

注:里面的排序操作由在registerAnnotationConfigProcessors中添加的AnnotationAwareOrderComparator比较器完成,该比较器是PriorityOrder优先于Order,也就是说两个对象一个是PriorityOrder,一个是Order,则PriorityOrder大,返回1,如果两个对象都是同一个类型,则根据属性值大小进行判断。

 


	public static void invokeBeanFactoryPostProcessors(
			ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {

		// Invoke BeanDefinitionRegistryPostProcessors first, if any.
		Set<String> processedBeans = new HashSet<>();

		if (beanFactory instanceof BeanDefinitionRegistry) {
			BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
			List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
			List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();

			for (BeanFactoryPostProcessor 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<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			// 分三步调用BeanDefinitionRegistryPostProcessors
			/**
			 * ###################### first开始 #########################
			 * 首先,调用实现了PriorityOrdered接口的BeanDefinitionRegistryPostProcessor,默认是ConfigurationClassPostProcessor,并实例化默认是ConfigurationClassPostProcessor
			 * ——ConfigurationClassPostProcessor 做了很多事情,根据@ComponentScan扫描和解析处理@Component @Service等类型,以及@Bean @Import @ImportResource 等类型
			 * ##########################################################
			 */
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					//getBean会将ConfigurationClassPostProcessor放到容器中,这个Processor会处理使用@Configuration注解的类
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}

			//根据@Order @Priority注解对Processor进行排序  ,使用到了AnnotationAwareOrderComparator实现类进行排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			//将进行了排序的Processors放到后面要使用的registryProcessors中
			registryProcessors.addAll(currentRegistryProcessors);
			// 第一次PostProcessor
			// 将使用@Configuration注解的类(SpringAPPConfig),根据它的注解功能扫描符合Spring规则的类并放到beanDefinitionMap中,还有属性文件内容
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			currentRegistryProcessors.clear();
			/**
			 * ###################### first 结束 #########################
			 */

			// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
			postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
			for (String ppName : postProcessorNames) {
				//第一次PostProcessor已经处理,在这里就不会再处理了,因为processedBeans已经包含了,那么processedBeans.contains(ppName)则会为true,下面的判断就会为false
				if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			registryProcessors.addAll(currentRegistryProcessors);
			// 第二次PostProcessor
			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) {
					//处理前两次PostProcessor都没有处理的PostProcessor
					if (!processedBeans.contains(ppName)) {
						currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
						processedBeans.add(ppName);
						reiterate = true;
					}
				}
				sortPostProcessors(currentRegistryProcessors, beanFactory);
				registryProcessors.addAll(currentRegistryProcessors);
				// 第三次PostProcessor
				invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
				currentRegistryProcessors.clear();
			}

			// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
			//调用到目前为止所有已经准备(处理过的)好的BeanFactoryPostProcess的callback,比如默认的ConfigurationClassPostProcessor会在这里加载
			// 一个ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor
			// 第四次PostProcessor
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			// 第五次PostProcessor
			invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
		}

		else {
			// Invoke factory processors registered with the context instance.
			invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
		}


		/*##########################################################################################################
		* 分三步调用BeanFactoryPostproccesor
		* */
		// Do not initialize FactoryBeans here: We need to leave all regular beans
		// uninitialized to let the bean factory post-processors apply to them!
		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)) {
				priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				orderedPostProcessorNames.add(ppName);
			}
			else {
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		// 第六次PostProcessor 调用BeanFactoryPostProcessor
		invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);

		// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
		List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String postProcessorName : orderedPostProcessorNames) {
			//实例化BeanFactoryPostProcessor
			orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		sortPostProcessors(orderedPostProcessors, beanFactory);
		// 第七次PostProcessor 调用BeanFactoryPostProcessor
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		// 调用自定义的BeanFactoryPostProcessor和Spring 非实现Order和Priority接口的BeanFactoryPostProcessor
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			//实例化BeanFactoryPostProcessor
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
		}
		// 第八次PostProcessor 调用BeanFactoryPostProcessor
		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();
	}

扩展点:

在本方法中Spring提供了两中扩展点,点击对应链接跳转到介绍的地方

Spring5源码分析-BeanDefinitionRegistryPostProcessor

Spring5源码分析-BeanFactoryPostProcessor

© 著作权归作者所有

特拉仔
粉丝 59
博文 246
码字总数 214127
作品 0
渝中
部门经理
私信 提问
Spring5 源码分析-容器刷新-解析配置类-主流程

上一篇:Spring5 源码分析-容器刷新-invokeBeanFactoryPostProcessors()方法 此篇是上一篇方法中非常非常重要的功能,也是Spring核心功能,完成所有的BeanDefinition注册。 详细的主流程,如...

特拉仔
11/13
33
0
Spring5源码分析-初始化详细流程

上一篇Spring5 源码分析--引导片画了概要流程和简单说明,这篇整一个比较详细一点的,但是一些重要的方法并没有深入进去,接下来会对几个重要的方法进行深度的阅读,到时候会贴出源码注释和动...

特拉仔
11/09
54
0
Spring技术内幕-容器刷新:wac.refresh

继上一篇Spring技术内幕学习:Spring的启动过程之后,关于Spring的源码学习落了一大截,因为菜鸟成长系列是目前最先想完成的,所以这块就被耽误了,不过之后将会持续更新Spring相关的技术知识...

2017/12/24
0
0
SpringBoot 系列-Bean 的生命周期与扩展

本篇基于 SpringBoot 2.2.2.RELEASE 版本,Spring 各个版本之间多少存在一些差异,不过主流程基本相同;大家在阅读过程中需关注这点。 推荐阅读 SpringBoot 系列-FatJar 启动原理 SpringBoot...

glmapper
今天
0
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: 容器的基础XmlBeanFactory已经被...

Ilike_Java
2018/10/17
168
0

没有更多内容

加载失败,请刷新页面

加载更多

如何管stderr,而不是stdout?

我有一个要写入信息的程序stdout和stderr ,我需要grep通过什么是未来标准错误 ,而忽视标准输出 。 我当然可以分2步完成: command > /dev/null 2> temp.filegrep 'something' temp.file...

技术盛宴
28分钟前
5
0
centos7.5上通过docker安装并运行mysql5.7

1. docker pull mysql:5.7 2. docker run --name mysql5.7 -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7...

Ryub
31分钟前
6
0
什么是比赛条件?

在编写多线程应用程序时,遇到的最常见问题之一是竞争条件。 我对社区的问题是: 什么是比赛条件? 您如何检测到它们? 您如何处理它们? 最后,如何防止它们发生? #1楼 当设备或系统试图同...

javail
43分钟前
6
0
SpringMVC源码分析-DispatcherServlet-init方法分析

上一篇:SpringMVC源码分析-DispatcherServlet实例化干了些什么 先吐槽一下。。。写了两小时的博客突然被俺家小屁孩按了刷新,东西不见了,建议OSCHINA能够自动定时保存啊。让我先安静一下。...

特拉仔
50分钟前
7
0
python协程 生成器

协程,又称微线程,纤程。英文名Coroutine。 线程是系统级别的它们由操作系统调度,而协程则是程序级别的由程序根据需要自己调度。在一个线程中会有很多函数,我们把这些函数称为子程序,在子...

沙门行道
今天
7
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部