栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

分析-ConfigurationClassPostProcessor原理

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

分析-ConfigurationClassPostProcessor原理

目录

一、概述

二、运行流程

1、refresh()

2、processConfigBeanDefinitions()

3、processConfigurationClass()

4、doProcessConfigurationClass()


一、概述

ConfigurationClassPostProcessor是用来容器启动时处理解析容器的配置类,实现了BeanDefinitionRegistry、PriorityOrdered接口。

当容器开启组件扫描或使用ComponentScan会默认注册到容器中,否则,将如同其他的BeanFactoryPostProcessor后置处理器一样手动被声明到容器中。

配置类通过ConfigurationClassUtils工具类判断:

1、标识@Configuration注解

2、标识@Component、@ComponentScan、@Import、@ImportResource、方法标识@Bean

 

二、运行流程

1、refresh()

创建容器时,在refresh方法中调用invokeBeanFactoryPostProcessors方法创建运行BeanFactory后置处理器。

进入invokeBeanFactoryPostProcessors方法的PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors方法, ConfigurationClassPostProcessor由于实现了BeanDefinitionRegistry、PriorityOrdered接口,在如图红框被容器扫描出来并创建对象,在invokeBeanDefinitionRegistryPostProcessors方法中运行ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法。

ConfigurationClassPostProcessor的postProcessBeanDefinitionRegistry方法主要是设置registryId,防止postProcessBeanDefinitionRegistry方法被多次调用,processConfigBeanDefinitions方法开始解析配置类。

2、processConfigBeanDefinitions()

在processConfigBeanDefinitions方法中遍历容器的beanDefinition集合,通过ConfigurationClassUtils工具类找到配置类beanDefinition,将其放入configCandidates集合中。

创建ConfigurationClassParser对象,调用对象的parse方法对配置类进行解析。

进入parse方法,根据bd的类型进入不同的parse方法,而那些parse方法都调用一个processConfigurationClass方法。

3、processConfigurationClass()

先根据配置类是否标识了@Conditional,判断是否跳过不解析。

通过doProcessConfigurationClass方法对配置类信息进行详细解析,若是当前配置类含有父类(排除java开头的类,例如Object),则会返回该配置类的父类,进行对父类进行解析,然后最后将已解析的配置类放到configurationClasses集合中,防止多次解析。

4、doProcessConfigurationClass()

该方法主要是解析多个spring注解,例如@PropertySource、@ComponentScan、@Import、@ImportResource、@Bean、解析配置类的内部类等。

进入doProcessConfigurationClass方法,先判断该配置类是否含有@Component注解(isAnnotated方法会找当前类标识的注解,包括注解内部的元注解),

若是有,则通过processMemberClasses方法会遍历配置类定义的内部类,判断内部类是否是配置类,若是则将内部类放入candidates集合中,并遍历candidates集合调用processConfigurationClass方法解析。

private void processMemberClasses(ConfigurationClass configClass, SourceClass sourceClass) throws IOException {
		Collection memberClasses = sourceClass.getMemberClasses();
		if (!memberClasses.isEmpty()) {
			List candidates = new ArrayList<>(memberClasses.size());
			for (SourceClass memberClass : memberClasses) {
				if (ConfigurationClassUtils.isConfigurationCandidate(memberClass.getMetadata()) &&
						!memberClass.getMetadata().getClassName().equals(configClass.getMetadata().getClassName())) {
					candidates.add(memberClass);
				}
			}
			OrderComparator.sort(candidates);
			for (SourceClass candidate : candidates) {
				if (this.importStack.contains(configClass)) {
					this.problemReporter.error(new CircularImportProblem(configClass, this.importStack));
				}
				else {
					this.importStack.push(configClass);
					try {
						processConfigurationClass(candidate.asConfigClass(configClass));
					}
					finally {
						this.importStack.pop();
					}
				}
			}
		}
	}

接着解析配置类的@PropertySource,解析配置文件并加载到容器环境中。

解析@ComponentScan组件,扫描得到beanDefinition集合,若是扫描中包含配置类,则会调用parse方法先解析该配置类

 接下来解析@Import组件,解析详情可参考解析@Import底层原理_Just-Today的博客-CSDN博客

 解析@ImportResource

 解析@Bean

最后判断该配置类是否继承类名不是java开头的父类,且父类不在knownSuperclasses集合中,若是有则返回该配置类的父类,继续解析父类,若是没,则返回null结束解析循环方法。

至此,通过解析将容器中的所有配置类、通过解析注解得到的beanDefinition都被保存到容器的beanDefinitions集合中。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1040876.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号