【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程相关的知识,希望对你有一定的参考价值。
参考技术A本文以SpringBoot应用为基础,尝试分析基于注解 @Configuration 的配置类是如何向Spring容器注册BeanDefinition的过程
其中主要分析了 ConfigurationClassPostProcessor 这个 BeanDefinitionRegistryPostProcessor 即Bean定义注册后置处理器,在Spring启动过程中对@Configuration配置类的处理,主要体现在 解析并发现所有配置类,处理配置类的相关逻辑(如配置类上的@ComponentScan、@Import、@Bean注解等),注册其中的BeanDefinition
首先看一下 ConfigurationClassPostProcessor的类继承关系
从红框中可以看出 ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor 接口的实现类,即是一个Bean定义注册的后置处理器,会在Spring容器启动时被调用,具体时机为
invokeBeanFactoryPostProcessors() 会先调用所有的 BeanDefinitionRegistryPostProcessor 之后,再调用所有的 BeanFactoryPostProcessor
ConfigurationClassPostProcessor又是如何被引入Spring的呢??
SpringBoot应用会在ApplicationContext应用上下文被创建的构造函数中 new AnnotatedBeanDefinitionReader 这个用于注册基于注解的BeanDefinition的Reader,在其构造中又会调用 AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry) 使用工具类向Spring容器中注册一些所谓的注解配置处理器,其中就包含 ConfigurationClassPostProcessor
首先,ConfigurationClassPostProcessor后置处理器的处理入口为 postProcessBeanDefinitionRegistry() 方法。其主要使用了 ConfigurationClassParser 配置类解析器解析 @Configuration 配置类上的诸如 @ComponentScan 、 @Import 、 @Bean 等注解,并尝试发现所有的配置类;还使用了 ConfigurationClassBeanDefinitionReader 注册所发现的所有配置类中的所有Bean定义;结束执行的条件是所有配置类都被发现和处理,相应的bean定义注册到容器
大致流程如下:
1、通过BeanDefinitionRegistry查找当前Spring容器中所有BeanDefinition
2、通过 ConfigurationClassUtils.checkConfigurationClassCandidate() 检查BeanDefinition是否为 “完全配置类” 或 “简化配置类” ,并对配置类做标记,放入集合待后续处理
3、通过 ConfigurationClassParser解析器 parse解析配置类集合,尝试通过它们找到其它配置类
4、使用 ConfigurationClassBeanDefinitionReader 注册通过所发现的配置类中找到的所有beanDefinition
5、处理完一轮配置类后,查看BeanDefinitionRegistry中是否存在新加载的且还未被处理过的 “完全配置类” 或 “简化配置类” ,有的话继续上面步骤
其中第3、4步后面重点分析
对于SpringBoot应用来说,参与解析的 种子配置文件 即为SpringBoot的Application启动类
通过ConfigurationClassParser解析器parse解析配置类集合,尝试通过它们找到其它配置类
ConfigurationClassParser#processConfigurationClass()
包含了处理单个配置类的大体流程,先根据 ConfigurationPhase.PARSE_CONFIGURATION 解析配置阶段的 @Conditional 条件判断当前配置类是否应该解析,之后调用 ConfigurationClassParser#doProcessConfigurationClass() 循环解析配置类,直到不存在未处理过的父类
ConfigurationClassParser#doProcessConfigurationClass():真正解析配置类
通过解析配置类上的注解、内部成员类和方法构建一个完整的ConfigurationClass配置类,过程中如果发现了新的配置类可以重复调用此方法
真正解析过程中会处理 成员内部类 、 @PropertySource 、 @ComponentScan 、 @Import 、 @ImportSource 、 @Bean方法 等,流程如下:
在上面解析配置类的过程中,除了构建了一个完整的ConfigurationClass配置类,其实已经向 BeanDefinitionRegistry 中添加了一些beanDefinition了,比如在处理 @ComponentScan 时,扫描到的 @Component相关组件 就已经注册了
而 ConfigurationClassBeanDefinitionReader 会继续读取已经构建好的ConfigurationClass配置类中的成员变量,从而注册beanDefinition
构建好的ConfigurationClass配置类中在本阶段可用的成员变量包括:
通过构建好的配置类的配置信息,使用ConfigurationClassBeanDefinitionReader注册所有能够读取到的beanDefinition:
请放大观看
Spring BeanDefinitionRegistryPostProcessor:ConfigurationClassPostProcessor
Spring 工具类 ConfigurationClassParser 分析得到配置类
Spring 配置类的分类
spring boot中装配依赖包中的@Configuration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\ indi.cyh.jdbctool.modle.DbConfig
https://blog.csdn.net/SkyeBeFreeman/article/details/96291283
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\\
indi.cyh.jdbctool.modle.DbConfig
以上是关于【Spring】简述@Configuration配置类注册BeanDefinition到Spring容器的过程的主要内容,如果未能解决你的问题,请参考以下文章
spring boot中装配依赖包中的@Configuration
初识Spring Framework——Bean注册Bean依赖注入