Spring 源码阅读 35:Spring 如何解析 @Configuration 中的配置

简介: 本文梳理了配置类的配置信息,是由其对应的 BeanFactory 后处理器负责执行的,这个后处理器在上下文创建时被注册到容器中,当容器的预处理完成后会执行其中的后处理方法。

基于 Spring Framework v5.2.6.RELEASE

概述

上一篇中介绍了@Component注解,被它标记的类会被 Spring 的组件扫描逻辑筛选出来生成对应的 BeanDefinition,另外,@Controller@Service@Repository注解标记的类型也会被筛选,因为这几个注解都被标记了@Component元注解。除此之外,还有一个常见的注解@Configuration会被 Spring 扫描到,它不仅用来生成 BeanDefinition,还用来进行 Spring 应用的配置。

本文主要分析@Configuration中的配置是如何被读取和执行的。

@Configuration注解

注解@Configuration 的源码如下。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented@Componentpublic@interfaceConfiguration {
@AliasFor(annotation=Component.class)
Stringvalue() default"";
booleanproxyBeanMethods() defaulttrue;
}

因为它也被标记了@Component注解,因此,标记了@Configuration注解的类也会被 Spring 识别到,并且生成其对应的 BeanDefinition。不过,@Configuration的作用并非是用来配置 BeanDefinition 的,而是可以像一个 XML 配置文件一样,配置 Bean 的信息,或者其他的一些配置。

比如,可以如下这样配置一个单例 Bean 极其创建的逻辑:

@ConfigurationpublicclassUserConfig {
@BeanpublicUseruser() {
returnnewUser();
    }
}

然后,便可以在上下文中获取到名为user的对象。

publicclassMain {
publicstaticvoidmain(String[] args) {
ApplicationContextcontext=newAnnotationConfigApplicationContext("com.pseudocode.labs");
Useruser= (User)context.getBean("user");
user.sayHello();
    }
}

在 Spring 扫描包路径的时候,只会将扫描到的类型创建成对应的 BeanDefinition 并注册到容器中,那么,这里的配置是如何被加载到 Spring 容器中的呢?

后处理器的注册

这里需要回顾一下之前文章的内容,在《Spring 源码阅读 31:基于注解初始化 Spring 上下文的原理(1) 》中,曾经分析过,AnnotationConfigApplicationContext 初始化时,会初始化一个 AnnotatedBeanDefinitionReader 对象,初始化的过程中,会调用 AnnotationConfigUtils 的registerAnnotationConfigProcessors方法,其中,会向容器中注册一些后处理器类,这里面就包含了处理被标记了@Configuration的类型的后处理器 ConfigurationClassPostProcessor。

// org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME)) {
RootBeanDefinitiondef=newRootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
}

我们看一下 ConfigurationClassPostProcessor 的继承关系。

image.png

这里可以注意到两点:

  1. 它实现了 BeanDefinitionRegistryPostProcessor 接口,而 BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,因此,它是一个处理 BeanFactory 的后处理器。这一点需要留意,后面会涉及到。
  2. 它实现了 PriorityOrdered 及 Ordered 接口,因此可以为它指定优先级和执行顺序。

至此可以得到结论,AnnotationConfigApplicationContext 默认包含了一个后处理器,能够处理被@Configuration标记的类型中的配置内容,那么接下来的问题就是,这个后处理器中的处理方法是什么时候执行的?

后处理器的执行

在 Spring 初始化上下文的过程中,当处理完准备工作之后,会通过调用refresh方法进入到核心流程中,refresh方法被定义在 AbstractApplicationContext 抽象类中,也就是说,所有继承了 AbstractApplicationContext 的上下文类型的上下文类型,都执行了同样的refresh方法,包括基于注解的上下文类型 AnnotationConfigApplicationContext 和基于 XML 配置文件的上下文类型 ClassPathXmlApplicationContext。

refresh方法中,完成 BeanFactory 的创建和预处理之后,会执行 BeanFactory 的后处理逻辑,具体对应 AbstractApplicationContext 的invokeBeanFactoryPostProcessors方法,具体的执行步骤,被委托给了 PostProcessorRegistrationDelegate 的invokeBeanFactoryPostProcessors方法。

具体的执行逻辑,在之前的源码分析文章中有过详细的介绍,可以参考:Spring 源码阅读 13:执行 BeanFactoryPostProcessor 中的处理方法

具体到 ConfigurationClassPostProcessor 后处理器,前面提到它实现了 BeanDefinitionRegistryPostProcessor,因此,它的postProcessBeanDefinitionRegistry方法会被先执行,之后它的postProcessBeanFactory会被执行。

因此,对@Configuration标记的类型的处理都在这两个方法只中了。

总结

本文梳理了@Configuration标记的配置类的配置信息,是由其对应的 BeanFactory 后处理器负责执行的,这个后处理器在上下文创建时被注册到容器中,当容器的预处理了完成后会执行其中的后处理方法。之后的文章,会进入 ConfigurationClassPostProcessor 中,详细分析两个处理方法。


目录
相关文章
|
1天前
|
Java 开发者 Spring
Spring Boot中的资源文件属性配置
【4月更文挑战第28天】在Spring Boot应用程序中,配置文件是管理应用程序行为的重要组成部分。资源文件属性配置允许开发者在不重新编译代码的情况下,对应用程序进行灵活地配置和调整。本篇博客将介绍Spring Boot中资源文件属性配置的基本概念,并通过实际示例展示如何利用这一功能。
8 1
|
4天前
|
canal 缓存 关系型数据库
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
Spring Boot整合canal实现数据一致性解决方案解析-部署+实战
|
5天前
|
XML 人工智能 Java
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
Spring Bean名称生成规则(含源码解析、自定义Spring Bean名称方式)
|
10天前
|
存储 安全 Java
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(下)
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(下)
18 0
|
10天前
|
安全 Java 数据库
第2章 Spring Security 的环境设置与基础配置(2024 最新版)(上)
第2章 Spring Security 的环境设置与基础配置(2024 最新版)
35 0
|
12天前
|
安全 Java Spring
Spring Security 5.7 最新配置细节(直接就能用),WebSecurityConfigurerAdapter 已废弃
Spring Security 5.7 最新配置细节(直接就能用),WebSecurityConfigurerAdapter 已废弃
29 0
|
12天前
|
安全 Java 应用服务中间件
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
26 0
江帅帅:Spring Boot 底层级探索系列 03 - 简单配置
|
12天前
|
Java 关系型数据库 MySQL
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
UWB (ULTRA WIDE BAND, UWB) 技术是一种无线载波通讯技术,它不采用正弦载波,而是利用纳秒级的非正弦波窄脉冲传输数据,因此其所占的频谱范围很宽。一套UWB精确定位系统,最高定位精度可达10cm,具有高精度,高动态,高容量,低功耗的应用。
一套java+ spring boot与vue+ mysql技术开发的UWB高精度工厂人员定位全套系统源码有应用案例
|
17天前
|
XML Java 数据格式
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
21 0
Bean工厂探秘:解析Spring底层工厂体系BeanFactory的神奇之道
|
17天前
|
JSON Java 数据库连接
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
属性注入掌握:Spring Boot配置属性的高级技巧与最佳实践
27 1

推荐镜像

更多