Spring Boot 自动配置原理
一句话
Spring Boot 启动时根据引入的 starter 和 application.yml 配置,通过 @Conditional 条件过滤候选自动配置类,有条件地注册基础设施 Bean,用户自定义优先,框架默认兜底。
1. 核心链路
① 启动类 @SpringBootApplication ├── @SpringBootConfiguration(配置类,等价 @Configuration) ├── @ComponentScan(扫描业务 Bean) └── @EnableAutoConfiguration(自动配置开关) ↓ ② @Import(AutoConfigurationImportSelector.class) ↓ ③ 读取所有 jar 包的 META-INF/spring.factories 拿到候选自动配置类列表(130+ 个) ↓ ④ 逐个检查每个自动配置类上的 @Conditional 条件 满足 → 注册 Bean 不满足 → 跳过 ↓ ⑤ 最终通常只有 30~40 个自动配置类真正生效2. @Conditional 条件注解家族
自动配置类不是全部生效,而是通过条件注解过滤:
| 注解 | 判断依据 | 举例 |
|---|---|---|
| @ConditionalOnClass | classpath 里有某个类 | 有 RedisTemplate.class → 说明引了 Redis |
| @ConditionalOnProperty | 配置文件属性匹配 | pans.basic.cache.type=redis → 走 Redis |
| @ConditionalOnMissingBean | 容器里还没人定义 | 没自定义 DataSource → 帮你创建默认的 |
| @ConditionalOnBean | 容器里已有某个 Bean | 有 DataSource → 才继续配事务管理器 |
| @ConditionalOnWebApplication | 当前是 Web 应用 | 才配 DispatcherServlet |
3. @ConditionalOnMissingBean — 用户优先原则
@Bean@ConditionalOnMissingBeanpublicObjectMapperobjectMapper(){returnnewObjectMapper();}体现的核心设计原则:
你没用,我帮你配一个默认的 你用了,我尊重你,不覆盖用户自定义的同类型 Bean 优先生效,自动配置退让。这是 Spring Boot 灵活性的关键。
4. spring.factories
位置:每个 starter jar 包的 META-INF/spring.factories 关键 key: org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.xxx.RedisAutoConfiguration,\ com.xxx.DataSourceAutoConfiguration,\ ...(130+ 个候选类) Spring Boot 3.x 新格式: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 作用:列出所有候选自动配置类,启动时由 AutoConfigurationImportSelector 读取注意:这个文件在 jar 包内部,不是在业务项目里。业务项目通过引 starter 来"获得"这些候选类。
5. starter 是什么
starter 不是功能代码本身,而是"依赖集合 + 自动配置入口":
spring-boot-starter-web 包含: ├── spring-webmvc(Spring MVC) ├── jackson(JSON 序列化) ├── tomcat(内嵌 Web 容器) └── spring-boot-starter(内含自动配置类入口)企业项目里公司会把常用能力封装成平台 starter:
basic-starter-cache → 引了就自动配好缓存能力 basic-starter-log → 引了就自动配好日志能力 basic-starter-data-translate → 引了就自动配好数据翻译能力业务项目只需要引依赖 + 写 application.yml 配置,不需要手写 @Bean。
6. 自动配置 vs 组件扫描 vs MapperScan
三者职责不同,面试别混:
| 职责 | 注解 | 负责什么 |
|---|---|---|
| 自动配置 | @EnableAutoConfiguration | 框架基础设施 Bean(DataSource、DispatcherServlet、TransactionManager 等) |
| 组件扫描 | @ComponentScan | 业务 Bean(Service、Controller、Repository) |
| Mapper 扫描 | @MapperScan | Mapper 接口 |
默认 @ComponentScan 只扫描启动类所在包及子包。如果业务代码在其他包,需要显式指定:
@ComponentScan({"com.longjitech","com.longji"})7. exclude 排除
@SpringBootApplication(exclude={FreeMarkerAutoConfiguration.class})即使 classpath 满足条件,也明确不让该自动配置类生效。常见原因:不需要该功能、与已有配置冲突、启动报错。
也可以通过配置文件排除:
spring:autoconfigure:exclude:-org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration8. 自动配置为什么不会越引越慢
候选类 130+ → @Conditional 过滤 → 实际生效 30~40 个 没引 MongoDB → MongoAutoConfiguration 条件不满足,跳过 没引 Kafka → KafkaAutoConfiguration 条件不满足,跳过 没引的依赖对应的自动配置类只是"被读到"但不会真正注册 Bean面试回答模板
"Spring Boot 自动配置的核心是 @EnableAutoConfiguration。 它通过 AutoConfigurationImportSelector 在启动时读取 classpath 下 spring.factories 中声明的自动配置类,拿到 130+ 个候选类。 这些候选类不会全部生效,而是通过 @Conditional 系列条件注解过滤。 @ConditionalOnClass 判断依赖是否存在, @ConditionalOnProperty 判断配置项是否开启, @ConditionalOnMissingBean 判断容器中是否已有用户自定义 Bean。 满足条件的自动配置类会注册基础设施 Bean, 比如 DataSource、DispatcherServlet、TransactionManager 等。 如果用户自己定义了同类型 Bean,@ConditionalOnMissingBean 会让用户配置优先于框架默认配置。 所以自动配置本质上是:根据 classpath 依赖、配置文件和容器已有 Bean, 有条件地注册默认 Bean。"参考来源
- Day11-Spring 与 SpringBoot
01_Raw【原始素材】/面试资料-B站博主/SpringBoot篇(18题) - 飞书云文档.md