【Spring篇08】:理解自动装配,从spring.factories到.imports剖析

文章目录

  • [1. 自动化装配的起点:`@SpringBootApplication`](#1. 自动化装配的起点:@SpringBootApplication)
  • [2. 自动化装配的核心机制:`@EnableAutoConfiguration` 和 `AutoConfigurationImportSelector`](#2. 自动化装配的核心机制:@EnableAutoConfigurationAutoConfigurationImportSelector)
  • [3. 自动化配置的注册方式:`spring.factories` 与 `.imports`](#3. 自动化配置的注册方式:spring.factories.imports)
    • [3.1 早期版本:`META-INF/spring.factories`](#3.1 早期版本:META-INF/spring.factories)
    • [3.2 现代版本:`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`](#3.2 现代版本:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports)
  • [4. 运行时类路径:自动化配置的基础](#4. 运行时类路径:自动化配置的基础)
  • [5. 条件判断:决定配置是否生效](#5. 条件判断:决定配置是否生效)
  • [6. 总结](#6. 总结)

Spring Boot 自动化装配是其最引人注目的特性之一,它极大地简化了 Spring 应用的配置,让开发者能够更专注于业务逻辑本文将带深入探讨 Spring Boot 自动化装配的原理,并回顾其从早期版本到现代版本的演进过程

1. 自动化装配的起点:@SpringBootApplication

每个 Spring Boot 应用的入口点通常都有一个 @SpringBootApplication 注解这个复合注解是自动化装配的起点,它集成了三个核心注解:

  • @SpringBootConfiguration : 标记当前类为配置类,等同于 @Configuration
  • @EnableAutoConfiguration : 开启 Spring Boot 自动化装配的关键注解
  • @ComponentScan: 开启组件扫描,用于发现和注册应用内的 Bean

其中,@EnableAutoConfiguration 是自动化装配的核心


2. 自动化装配的核心机制:@EnableAutoConfigurationAutoConfigurationImportSelector

@EnableAutoConfiguration 注解内部通过 @Import 注解导入了一个名为 AutoConfigurationImportSelector 的类

java 复制代码
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class}) // 核心在这里!
public @interface EnableAutoConfiguration {
    // ...
}

AutoConfigurationImportSelector 的主要职责是在应用启动时,找到并加载所有符合条件的自动化配置类


3. 自动化配置的注册方式:spring.factories.imports

Spring Boot 自动化配置类并不是随便放在项目中的,它们需要被"注册"起来,以便 AutoConfigurationImportSelector 能够发现它们在 Spring Boot 的不同版本中,注册方式有所演进

3.1 早期版本:META-INF/spring.factories

在 Spring Boot 2.7 版本之前,自动化配置类主要通过 META-INF/spring.factories 文件进行注册这个文件位于 JAR 包的 META-INF 目录下,遵循 Java 的 Service Provider Interface (SPI) 机制

spring.factories 是一个属性文件,其中 org.springframework.boot.autoconfigure.EnableAutoConfiguration 键对应的值就是自动化配置类的全限定名列表,用逗号分隔

properties 复制代码
# 示例:早期版本 Starter 中的 META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

AutoConfigurationImportSelector 在早期版本中主要依赖 SpringFactoriesLoader 工具类来读取这些 spring.factories 文件SpringFactoriesLoader 会扫描当前应用的整个运行时类路径 ,查找所有 JAR 包中的 META-INF/spring.factories 文件,并加载指定键对应的值

3.2 现代版本:META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

从 Spring Boot 2.7 版本开始,为了使自动化配置的注册更加清晰和规范,引入了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 这个专门用于注册自动化配置类的文件

这个文件每行包含一个自动化配置类的全限定名

properties 复制代码
# 示例:现代版本 Starter 中的 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration

在 Spring Boot 2.7+ 版本中,AutoConfigurationImportSelector 会同时从 spring.factories.imports 文件中加载自动化配置类如我们之前分析的 getCandidateConfigurations 方法所示:

java 复制代码
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
    // 从 spring.factories 加载
    List<String> configurations = new ArrayList(SpringFactoriesLoader.loadFactoryNames(this.getSpringFactoriesLoaderFactoryClass(), this.getBeanClassLoader()));
    // 从 .imports 文件加载 (Spring Boot 2.7+ 新增)
    ImportCandidates.load(AutoConfiguration.class, this.getBeanClassLoader()).forEach(configurations::add);
    // ... 检查是否找到配置类
    return configurations;
}

在 Spring Boot 3.x 版本中,.imports 文件成为了主要和推荐的自动化配置注册方式


4. 运行时类路径:自动化配置的基础

无论是 spring.factories 还是 .imports 文件,AutoConfigurationImportSelector 能够找到它们的前提是它们所在的 JAR 包存在于应用的 运行时类路径 (Runtime Classpath)

运行时类路径是 JVM 在运行的 Java 应用程序时,用来查找和加载 .class 文件的路径集合它包括:

  • 自己的项目编译输出的 .class 文件
  • 项目依赖的所有 JAR 包
  • JDK 自带的类库

SpringFactoriesLoaderImportCandidates 工具类正是利用了 JVM 的类加载机制,遍历整个运行时类路径,查找指定位置的资源文件当通过 Maven 或 Gradle 引入一个 Spring Boot Starter 或其他包含自动化配置的 JAR 包时,这个 JAR 包就会被添加到的运行时类路径中,从而使得其中的 spring.factories.imports 文件能够被 Spring Boot 发现


5. 条件判断:决定配置是否生效

找到自动化配置类只是第一步Spring Boot 的自动化装配之所以智能,是因为它会根据当前应用程序的环境来决定哪些配置类应该真正生效这个决策过程依赖于一系列的条件注解

这些条件注解通常加在自动化配置类或其中的 @Bean 方法上常见的条件注解包括:

  • @ConditionalOnClass: 当指定的类存在于运行时类路径中时生效
  • @ConditionalOnMissingBean: 当 Spring 容器中不存在指定类型的 Bean 时生效
  • @ConditionalOnProperty: 当指定的配置属性存在且符合指定值时生效
  • @ConditionalOnResource: 当指定的资源文件存在于类路径中时生效
  • @ConditionalOnWebApplication: 当应用程序是 Web 应用时生效
  • 等等...

AutoConfigurationImportSelector 在加载了候选的自动化配置类名后,会进一步检查这些类上的条件注解只有当所有条件注解都满足时,这个自动化配置类才会被激活,其中的 Bean 定义才会被注册到 Spring 容器中

举例来说:

如果引入了 spring-boot-starter-data-redis 依赖,那么 Redis 相关的 JAR 包会出现在的运行时类路径中,其中包含 RedisOperations.class 等类spring-boot-autoconfigure 模块中的 RedisAutoConfiguration 类上带有 @ConditionalOnClass({ RedisOperations.class, RedisConnectionFactory.class }) 注解因为这些类存在,条件满足,RedisAutoConfiguration 生效,Spring Boot 自动为配置 Redis 相关的 Bean

如果没有引入该依赖,这些类不存在,条件不满足,RedisAutoConfiguration 被忽略


6. 总结

Spring Boot 自动化装配是一个强大而智能的特性,它通过以下机制实现:

  • @EnableAutoConfiguration: 开启自动化装配
  • AutoConfigurationImportSelector: 核心选择器,负责查找和加载自动化配置类
  • 注册文件 (spring.factories.imports): 声明哪些类是自动化配置类,位于 JAR 包的特定位置
  • 运行时类路径: 这些注册文件必须存在于应用的运行时类路径中才能被发现
  • 条件注解 (@ConditionalOnClass 等): 根据当前环境决定自动化配置是否生效
相关推荐
excel几秒前
使用 Prisma 实现数据库字段的动态迁移实践
前端·后端
转转技术团队2 分钟前
边学边做:图片识别技术的学习与应用
后端·算法
天涯学馆3 分钟前
JS 组合模式在组件化开发中的应用:从原理到实战
前端·javascript·面试
chanalbert4 分钟前
Spring 6 源码深度掘金:66+核心原理与高频面试攻坚指南
python·spring·面试
前端小巷子4 分钟前
浏览器的同源策略与跨域问题
前端·面试·浏览器
程序员爱钓鱼4 分钟前
Go语言项目工程化 —— 日志、配置、错误处理规范
后端·google·go
天天摸鱼的java工程师6 分钟前
假设你在开发订单系统时遇到高并发下库存扣减出错,如何解决?由浅入深分析
java·后端·面试
没逻辑6 分钟前
Go 服务架构性能优化指南(实战精选)
后端·性能优化·go
都叫我大帅哥7 分钟前
Redis的ZSet:从“青铜”到“王者”的排序神器
java·redis
看谷秀8 分钟前
大模型 19 RAG多样使用方法
面试