★ Spring Boot 自动配置原理是什么?条件注解与 AutoConfiguration.imports 如何生效?
结论先行:Spring Boot 的自动配置 = 启动注解(@EnableAutoConfiguration)+ 候选清单(META-INF/spring/…AutoConfiguration.imports)+ 条件注解(@ConditionalOnXxx)三层协作。它只负责“按条件装配官方/三方组件的默认 Bean”,用户 Bean 与自定义配置永远优先,冲突时用 @ConditionalOnMissingBean 让位给用户。
一、三层结构各干什么
| 层次 | 载体 | 作用 |
|---|---|---|
| 入口 | @SpringBootApplication 内含 @EnableAutoConfiguration | 触发自动配置候选扫描 |
| 清单 | AutoConfiguration.imports 文件 | 列出候选自动配置类(类名每行一个) |
| 裁决 | @Conditional 系列注解 | 逐个判断是否创建该自动配置类里的 Bean |
@SpringBootApplication = @SpringBootConfiguration + @EnableAutoConfiguration + @ComponentScan。
二、候选清单文件
- Boot 2.7 起新增
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports; - Boot 3.x 起不再读取 spring.factories 中的 EnableAutoConfiguration 键,统一用 imports 文件;
- 自动配置类上用 @AutoConfiguration 标记(该注解本身包含 @Configuration 语义)。
三、常用条件注解
@AutoConfiguration
@ConditionalOnClass(name = "org.springframework.data.redis.core.RedisTemplate") // 类路径条件
@ConditionalOnProperty(prefix = "app.cache", name = "enabled", havingValue = "true") // 配置条件
@EnableConfigurationProperties(CacheProperties.class) // 注册属性绑定类
public class DemoCacheAutoConfiguration {
@Bean
@ConditionalOnMissingBean // 用户已定义则跳过
public CacheManager cacheManager() { return new ConcurrentMapCacheManager(); }
}
条件注解家族:类条件 @ConditionalOnClass / @ConditionalOnMissingClass;Bean 条件 @ConditionalOnBean / @ConditionalOnMissingBean;属性条件 @ConditionalOnProperty;资源条件 @ConditionalOnResource;Web 条件 @ConditionalOnWebApplication;表达式条件 @ConditionalOnExpression。
四、为什么用户配置总能覆盖自动配置
- 自动配置类在所有用户 @Configuration 与 @ComponentScan 之后才被处理;
- 因此 @ConditionalOnMissingBean 判断的是“用户是否已注册同名 Bean”;
- 排序用 @AutoConfigureBefore / @AutoConfigureAfter / @AutoConfigureOrder,只约束自动配置类之间;
- 禁用单个自动配置:
spring.autoconfigure.exclude或 exclude 属性。
常见追问 / 记忆点
- 追问:为什么 3.x 用 imports 文件?答:spring.factories 被大量第三方复用导致解析重、易冲突,imports 文件更聚焦、支持 IDE 定位。
- 追问:启动时想知道哪些自动配置生效?答:开启 debug 日志或访问 Actuator 的 conditions 端点。
- 记忆点:自动配置本质是“有条件地替你 new Bean”,口诀“清单注册、条件裁决、缺 Bean 才上”。