Spring Boot 的自动装配(Auto-Configuration)是其最核心的特性,也是“约定优于配置”思想的集中体现。它的本质是:根据项目类路径下的依赖、运行时环境以及用户配置,在应用启动时自动判断并注册所需的 Bean,让开发者免于手动编写大量重复的配置代码。
下面我们从原理、核心流程和关键组件三个维度来深入拆解。
一、核心原理:三大机制协同工作
自动装配的实现依赖于三个核心机制:
1. 条件化装配(Conditional)
通过 @Conditional 系列注解实现按需加载。Spring Boot 内置了大量条件注解,只有当条件满足时,对应的自动配置类才会生效。
| 注解 | 生效条件 |
|---|---|
@ConditionalOnClass |
类路径中存在指定类 |
@ConditionalOnMissingClass |
类路径中不存在指定类 |
@ConditionalOnBean |
容器中存在指定 Bean |
@ConditionalOnMissingBean |
容器中不存在指定 Bean |
@ConditionalOnProperty |
配置文件中存在指定属性且值匹配 |
@ConditionalOnResource |
类路径中存在指定资源文件 |
@ConditionalOnWebApplication |
当前应用是 Web 应用 |
2. SPI 扩展机制(SpringFactoriesLoader)
Spring Boot 通过 SpringFactoriesLoader 加载 META-INF/spring.factories 或 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件中注册的自动配置类。这是一种服务发现机制,允许第三方 Starter 通过配置文件声明自己的自动配置类。
3. 延迟导入机制(DeferredImportSelector)
自动配置类通过 AutoConfigurationImportSelector(实现了 DeferredImportSelector 接口)延迟导入。这意味着自动配置类会在所有用户自定义配置(如 @Configuration、@Bean)处理之后再被处理,确保用户配置优先于自动配置。
二、核心流程:从启动到装配的完整链路
第一步:入口触发
启动类上的 @SpringBootApplication 注解是一个组合注解,它包含了三个核心注解:
@SpringBootConfiguration:标识当前类为配置类(本质是@Configuration)@EnableAutoConfiguration:开启自动装配功能@ComponentScan:开启组件扫描
@EnableAutoConfiguration 通过 @Import(AutoConfigurationImportSelector.class) 导入了核心处理器。
第二步:加载候选配置类
AutoConfigurationImportSelector 的 selectImports() 方法负责加载所有候选自动配置类。加载过程如下:
- 扫描配置文件:从类路径下加载
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件(Spring Boot 2.7+ 新格式),每行一个自动配置类的全限定名。 - 兼容旧格式:若新格式文件不存在,则回退到
META-INF/spring.factories文件中的org.springframework.boot.autoconfigure.EnableAutoConfiguration键。 - 去重与过滤:对加载的配置类进行去重,并应用
AutoConfigurationImportFilter进行初步过滤。
第三步:条件筛选(按需生效)
加载到的候选配置类会经过条件注解的评估。Spring Boot 使用 ConditionEvaluator 组件在运行时动态评估每个配置类上的 @Conditional 注解。
例如,DataSourceAutoConfiguration 上标注了 @ConditionalOnClass(DataSource.class),只有当类路径中存在 DataSource 类(即引入了相关数据库驱动依赖)时,该配置类才会被解析。
第四步:配置属性绑定
满足条件的自动配置类被解析后,会执行 @Bean 方法创建 Bean。同时,通过 @ConfigurationProperties 注解将 application.yml/properties 中的配置绑定到 Bean 的属性上。
例如,ServerProperties 类通过 @ConfigurationProperties(prefix = "server") 绑定 server.port、server.servlet.context-path 等配置。
第五步:注册到容器
最终,所有通过条件筛选的 Bean 被注册到 Spring 容器中,完成自动装配。
三、关键组件详解
1. @SpringBootApplication 组合注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { ... })
public @interface SpringBootApplication {// 通过 exclude 属性排除特定自动配置类Class<?>[] exclude() default {};String[] excludeName() default {};
}
2. AutoConfigurationImportSelector
这是自动装配的核心处理器,实现了 DeferredImportSelector 接口。它的关键方法:
selectImports():加载并筛选自动配置类getAutoConfigurationEntry():执行条件过滤getCandidateConfigurations():从配置文件中读取候选配置类
3. 配置文件演变
| Spring Boot 版本 | 配置文件位置 | 说明 |
|---|---|---|
| 2.7 之前 | META-INF/spring.factories |
旧格式,通过 EnableAutoConfiguration 键注册 |
| 2.7+ | META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
新格式,每行一个配置类,更简洁 |
| 3.x | 同上 | 完全废弃 spring.factories 方式 |
4. 条件注解评估机制
Spring Boot 通过 ConditionEvaluator 组件评估条件注解。为了提高性能,引入了多级缓存:
conditionCache:缓存已评估的条件结果,避免重复计算autoConfigurationMetadata:通过spring-autoconfigure-metadata.properties文件预存条件元数据,加速过滤
四、自动装配的优先级控制
1. 用户配置优先于自动配置
由于 AutoConfigurationImportSelector 实现了 DeferredImportSelector,自动配置类会在用户自定义配置(如 @Configuration 类、@Bean 方法)之后处理。这意味着用户可以通过自定义 @Bean 覆盖自动配置创建的 Bean。
2. 自动配置类之间的顺序
通过 @AutoConfigureOrder、@AutoConfigureBefore、@AutoConfigureAfter 注解控制自动配置类之间的加载顺序。
3. 排除不需要的自动配置
// 方式一:通过注解排除
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})// 方式二:通过配置文件排除
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
五、实战:自定义 Starter 的自动配置
要创建一个自定义 Starter,需要完成以下步骤:
- 编写配置属性类:使用
@ConfigurationProperties绑定配置 - 编写自动配置类:使用
@Configuration和@Conditional注解 - 注册自动配置类:在
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中注册 - 打包发布:作为独立依赖供其他项目引用
六、一句话总结
Spring Boot 自动装配 = @EnableAutoConfiguration 触发 + AutoConfigurationImportSelector 加载候选配置 + @Conditional 系列注解按需筛选 + @ConfigurationProperties 绑定配置属性。 它通过 SPI 机制发现配置类,通过条件注解实现按需加载,通过延迟导入确保用户配置优先,最终实现“引入即用、零配置启动”的开发体验。
