【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

springboot自动配置

springboot入门(HelloWorld)

初识Spring Framework——Bean注册Bean依赖注入

初识Spring Framework——Bean注册Bean依赖注入

初识Spring Framework——Bean注册Bean依赖注入