第78篇:Spring Boot自动配置(2026版)
📌 系列导航:《Java 100 天进阶之路》完整目录 |
⬅️ 上一篇:第77篇:Spring MVC流程 |
➡️ 下一篇:第79篇:Spring源码阅读技巧(待发布)
🗺️ 本文阅读地图(3 分钟速览)
第77篇搞定了Spring MVC流程,本篇深入 Spring Boot自动配置原理。每天用
@SpringBootApplication启动项目,引入依赖就能自动装配各种功能——但你知道这背后的魔法是怎么运作的吗?搞懂自动配置,就是搞懂了Spring Boot“约定优于配置”的底层逻辑:
| 模块 | 核心问题 | 一句话回答 |
|---|---|---|
| 自动配置是什么 | 为什么引入依赖就能直接用? | Spring Boot启动时根据classpath中的依赖,自动创建和配置需要的Bean |
| @SpringBootApplication | 一个注解干了多少事? | 复合注解——集成了@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个核心注解 |
| @EnableAutoConfiguration | 自动配置的开关是什么? | 通过@Import(AutoConfigurationImportSelector.class)导入配置选择器,触发自动配置加载 |
| SPI机制 | 自动配置类怎么被发现的? | Spring Boot启动时扫描类路径下的META-INF/spring.factories或.imports文件 |
| 条件注解 | 为什么有的配置加载有的不加载? | 通过@ConditionalOnClass、@ConditionalOnMissingBean等条件注解按需装配 |
| 配置绑定 | 配置文件怎么绑定到Java对象? | @ConfigurationProperties将application.yml的属性映射到XxxProperties类 |
| Spring Boot 3.x变化 | 和2.x有什么不同? | 废弃spring.factories,改用AutoConfiguration.imports文件 |
| 面试最爱问 | 高频考点有哪些? | 见文末 🎤 小节 |
一、核心知识点
1. 什么是自动配置?
自动配置(Auto-Configuration)是Spring Boot最核心的能力——它根据类路径中存在的依赖、容器中已存在的Bean以及配置文件中的属性,自动创建和配置Spring Bean,避免了大量手动XML或Java配置。
💡 核心思想:“约定优于配置”(Convention over Configuration) ——Spring Boot预设了大量合理的默认值,你只需要在需要的时候覆盖它们。
2. 为什么需要自动配置?
在Spring Boot出现之前,Spring应用的配置有多繁琐?
| 对比维度 | 传统Spring | Spring Boot |
|---|---|---|
| Web应用配置 | 配置web.xml、DispatcherServlet、ViewResolver | 引入spring-boot-starter-web即可 |
| 数据源配置 | 配置DataSource、事务管理器、SessionFactory | 引入spring-boot-starter-data-jpa,配几个连接参数即可 |
| JSON支持 | 手动配置Jackson的HttpMessageConverter | 自动注入,开箱即用 |
3. 自动配置的三大基石
Spring Boot的自动配置建立在三个核心能力之上:
| 基石 | 说明 |
|---|---|
| @SpringBootApplication | 应用入口与核心注解聚合 |
| 自动配置机制 | 基于条件化的Bean自动注册 |
| SPI扩展机制 | Spring Boot与Spring Framework的底层扩展能力 |
二、通俗讲解(1分钟开心学)
把Spring Boot自动配置想象成“智能家居”
- 传统Spring:你买了一套毛坯房,要自己装水电、铺地板、刷墙、买家具——每样都得自己干(写XML配置)。
- Spring Boot:你买了一套精装智能公寓。进门时系统自动检测——检测到“有人入住”(项目启动),自动开灯(自动配置)、联网(嵌入式Tomcat)、配好智能音箱(Starter依赖)——你拎包入住就行。
自动配置的“智能检测”逻辑:
- 检测到有Tomcat依赖 → 自动配置Spring MVC
- 检测到有MySQL驱动 → 自动配置数据源
- 检测到有Redis客户端 → 自动配置RedisTemplate
- 检测到你自己配了数据源 → 用你的,不用默认的(
@ConditionalOnMissingBean)
把核心组件想象成“智能家居的中控系统” :
| 组件 | 比喻 |
|---|---|
@SpringBootApplication | 智能家居的“总开关” |
@EnableAutoConfiguration | “自动模式”按钮——开启全屋智能 |
AutoConfigurationImportSelector | “中央处理器”——决定开哪些设备 |
META-INF/.../AutoConfiguration.imports | “设备清单”——所有可用的智能设备列表 |
@ConditionalOnXxx | “传感器”——检测条件是否满足才启动设备 |
@ConfigurationProperties | “控制面板”——你在手机上调整的参数 |
三、@SpringBootApplication 注解详解
3.1 注解本质:复合注解
@SpringBootApplication是Spring Boot的入口注解,本质上是一个复合注解(元注解),由三个核心注解组合而成:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
// 继承自三个注解的属性
}
3.2 三个核心组成注解
| 注解 | 作用 | 关键特性 |
|---|---|---|
| @SpringBootConfiguration | 标记类为Spring Boot配置类 | 继承自@Configuration,Spring Boot 3.x中默认使用CGLIB代理模式 |
| @EnableAutoConfiguration | 启用Spring Boot自动配置 | 核心注解,通过SPI机制加载自动配置类 |
| @ComponentScan | 扫描指定包下的Spring组件 | 默认扫描主类所在包及其子包 |
💡 关键理解:
@SpringBootApplication的本质就是这三个注解的“打包”——你写一个注解,等于同时开启了配置类、自动配置和组件扫描。
3.3 常用属性
| 属性 | 作用 | 示例 |
|---|---|---|
exclude | 排除指定的自动配置类 | @SpringBootApplication(exclude = DataSourceAutoConfiguration.class) |
excludeName | 通过全类名排除自动配置类 | @SpringBootApplication(excludeName = "org...") |
scanBasePackages | 指定组件扫描的基础包 | @SpringBootApplication(scanBasePackages = "com.example") |
proxyBeanMethods | 是否代理@Bean方法 | Spring Boot 3.x默认true |
四、自动配置执行流程(6步)
自动配置的本质是:在Spring应用启动时,根据类路径下的依赖、配置文件和环境变量,自动注册符合条件的Bean到Spring容器中。

💡 核心链路:
@SpringBootApplication→@EnableAutoConfiguration→@Import(AutoConfigurationImportSelector.class)→selectImports()→ SPI加载 → 条件过滤 → Bean注册
五、核心组件深度拆解
5.1 @EnableAutoConfiguration —— 自动配置的“开关”
@EnableAutoConfiguration是Spring Boot自动配置的核心注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// ...
}
真正的魔法来自它导入的 AutoConfigurationImportSelector 。
5.2 AutoConfigurationImportSelector —— 自动配置的“CPU”
AutoConfigurationImportSelector实现了DeferredImportSelector接口,会在所有@Configuration配置类处理完之后再执行导入逻辑。
它的核心方法是selectImports(),负责:
- 检查自动配置是否开启
- 加载所有自动配置候选类(通过SPI机制)
- 返回需要导入的配置类数组
5.3 SPI机制 —— 自动配置类的“发现”方式
Spring Boot通过SPI(Service Provider Interface)机制发现自动配置类。
Spring Boot 2.x及之前:
自动配置类定义在META-INF/spring.factories文件中:
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
Spring Boot 3.x(重要变化!) :
Spring Boot 3.0正式废弃了META-INF/spring.factories机制,改用新的声明式配置文件:
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
⚠️ 特别注意:如果你在维护或升级Spring Boot 3.x项目,自动配置的注册方式已经变了——不再是
spring.factories,而是.imports文件。
5.4 条件注解 —— 自动配置的“过滤器”
所有自动配置类都附带条件注解,只有满足条件才会真正生效,实现按需装配。
| 条件注解 | 作用 | 典型场景 |
|---|---|---|
| @ConditionalOnClass | classpath中存在指定类才生效 | 引入MySQL驱动才加载数据源配置 |
| @ConditionalOnMissingBean | 容器中没有用户自定义的Bean才生效 | 用户没配数据源时,Spring Boot才创建默认的 |
| @ConditionalOnProperty | 配置文件中指定参数才生效 | spring.redis.enabled=true时才加载Redis配置 |
| @ConditionalOnBean | 容器中存在指定Bean才生效 | 存在DataSource时才创建JdbcTemplate |
| @ConditionalOnWebApplication | 当前是Web应用才生效 | MVC自动配置只在Web环境下生效 |
代码示例:
@Configuration
@ConditionalOnClass(DataSource.class) // 有DataSource类才加载
@ConditionalOnMissingBean(DataSource.class) // 用户没配才创建默认的
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.datasource.url")
public DataSource dataSource(DataSourceProperties properties) {
return properties.initializeDataSourceBuilder().build();
}
}
5.5 @ConfigurationProperties —— 配置绑定
每个自动配置类都配套一个XxxProperties属性封装类,用于将application.yml中的配置绑定到Java对象:
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
// getters / setters
}
在application.yml中配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
Spring Boot自动将配置值绑定到DataSourceProperties对象,然后DataSourceAutoConfiguration从中读取参数创建数据源。
六、Spring Boot 3.x 重要变化
Spring Boot 3.x基于Spring Framework 6和JDK 17+构建,在自动配置方面有重大变化:
| 变化点 | Spring Boot 2.x | Spring Boot 3.x |
|---|---|---|
| 自动配置文件 | META-INF/spring.factories | META-INF/spring/.../AutoConfiguration.imports |
| Java EE包名 | javax.* | jakarta.* |
| JDK基线 | JDK 8/11 | JDK 17+ |
| GraalVM支持 | 有限支持 | 原生镜像AOT元数据 |
| 虚拟线程 | 不支持 | 支持 |
💡 升级提醒:如果你正在将Spring Boot 2.x项目升级到3.x,自动配置的
spring.factories需要迁移到.imports文件。
七、自定义Starter实战
理解了自动配置原理,就可以自己写一个Starter了。Starter本质上是一个特殊的Maven/Gradle依赖项,通过聚合相关依赖和自动配置逻辑,实现特定功能的“一键启用”。
7.1 自定义Starter四步走
| 步骤 | 做什么 | 核心代码 |
|---|---|---|
| ① | 编写XxxProperties配置属性类 | @ConfigurationProperties(prefix = "xxx") |
| ② | 编写XxxAutoConfiguration自动配置类 | @Configuration + 条件注解 + @Bean |
| ③ | 注册自动配置类 | Spring Boot 3.x:在.imports文件中添加全类名 |
| ④ | 添加spring-boot-autoconfigure-processor依赖 | 生成自动配置元数据 |
7.2 完整代码示例
① 配置属性类:
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
private String apiKey;
private String apiSecret;
private String apiUrl;
private Integer connectTimeout = 5000;
// getters / setters
}
② 自动配置类:
@Configuration
@ConditionalOnClass(SmsClient.class)
@EnableConfigurationProperties(SmsProperties.class)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsClient smsClient(SmsProperties properties) {
SmsClient client = new SmsClient();
client.setApiKey(properties.getApiKey());
client.setApiSecret(properties.getApiSecret());
client.setApiUrl(properties.getApiUrl());
client.setConnectTimeout(properties.getConnectTimeout());
return client;
}
}
③ 注册自动配置(Spring Boot 3.x) :
在src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中写入:
com.example.sms.autoconfigure.SmsAutoConfiguration
④ 使用者体验:
引入依赖后,只需要在application.yml中配置:
sms:
api-key: your-api-key
api-secret: your-api-secret
api-url: https://api.sms.com
然后直接@Autowired使用即可,0行配置代码。
八、避坑要点
| 错误/误区 | 后果 | 正确做法 |
|---|---|---|
不知道Spring Boot 3.x已废弃spring.factories | 自定义Starter在3.x中不生效 | 改用.imports文件 |
在@ConfigurationProperties类上忘记加@Component | 属性绑定不生效 | 配合@EnableConfigurationProperties使用 |
| 条件注解使用不当导致配置不加载 | 自动配置“失灵” | 检查classpath中是否有对应的依赖类 |
在@ConditionalOnClass中直接引用类 | 类不存在时导致编译失败 | 使用name属性指定类名字符串 |
忘记添加spring-boot-autoconfigure-processor | 自动配置元数据缺失 | 在Starter模块中添加该依赖 |
把@ConditionalOnMissingBean放在@Configuration类上 | 整个配置类被跳过 | 放在@Bean方法上更精准 |
九、面试高频考点
Q1:Spring Boot自动配置的原理是什么?
Spring Boot启动时,
@SpringBootApplication中的@EnableAutoConfiguration通过@Import(AutoConfigurationImportSelector.class)导入配置选择器。AutoConfigurationImportSelector.selectImports()方法通过SPI机制扫描类路径下的META-INF/spring.factories(2.x)或AutoConfiguration.imports(3.x)文件,加载所有自动配置候选类。然后通过@Conditional系列条件注解进行筛选,只有满足条件的配置类才会生效,最终将Bean注册到IoC容器中。
Q2:@SpringBootApplication注解包含哪些核心注解?
包含三个核心注解:①**@SpringBootConfiguration**——标记类为Spring Boot配置类,继承自
@Configuration;②**@EnableAutoConfiguration**——开启自动配置的核心开关;③**@ComponentScan**——扫描主类所在包及其子包下的组件。
Q3:Spring Boot 3.x在自动配置方面有什么重大变化?
最大变化是废弃了
META-INF/spring.factories。Spring Boot 3.x改用新的声明式配置文件META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports,每行写一个自动配置类的全限定名。此外,所有javax.*包名改为jakarta.*,JDK基线升级到17+。
Q4:@ConditionalOnMissingBean的作用是什么?
当IoC容器中不存在指定类型的Bean时,条件成立。这是实现“可覆盖默认实现”的核心注解——Spring Boot提供默认Bean,但如果开发者自己定义了同类型的Bean,就会覆盖默认的。
Q5:如何自定义一个Starter?
四步:①编写
XxxProperties配置属性类,用@ConfigurationProperties绑定配置;②编写XxxAutoConfiguration自动配置类,用@Configuration+条件注解+@Bean定义Bean;③在Spring Boot 3.x中,在META-INF/spring/.../AutoConfiguration.imports中注册自动配置类的全限定名;④添加spring-boot-autoconfigure-processor依赖生成元数据。
🎤 面试官追问陷阱(加分题)
追问1:“AutoConfigurationImportSelector和普通的ImportSelector有什么不同?”
👉
AutoConfigurationImportSelector实现的是**DeferredImportSelector** 接口,它是ImportSelector的子接口。关键区别在于执行时机——DeferredImportSelector会在所有@Configuration类处理完之后再执行。这样做的目的是让自动配置类可以感知到用户自定义的Bean,从而实现“用户定义优先”的覆盖机制(@ConditionalOnMissingBean正是依赖这个特性)。
追问2:“spring.factories和AutoConfiguration.imports有什么区别?为什么要改?”
👉
spring.factories是一个key-value格式的通用SPI文件,不仅用于自动配置,还用于各种扩展点(如ApplicationListener、FailureAnalyzer等)。.imports文件是纯列表格式,只用于自动配置。改的原因:①更简洁,不需要写key;②加载性能更好;③避免spring.factories文件中无关配置的干扰。
追问3:“如果我自己配了一个DataSource Bean,Spring Boot还会创建默认的数据源吗?”
👉 不会。因为Spring Boot的
DataSourceAutoConfiguration上使用了@ConditionalOnMissingBean(DataSource.class)——当容器中已经存在DataSource类型的Bean时,这个条件不成立,自动配置类不会生效。这就是“开发者自定义优先于框架默认”的设计哲学。
十、练习题
-
简答题:请简述Spring Boot自动配置的完整执行流程(从
@SpringBootApplication到Bean注册)。 -
代码题:编写一个自定义Starter,实现一个简单的“日志记录工具”——引入依赖后,自动注入一个
LogUtilBean,支持通过application.yml配置日志级别和输出格式。 -
分析题:某项目从Spring Boot 2.7升级到3.0后,自定义的Starter不生效了。请分析可能的原因,并给出解决方案。
📊 你的学习进度
- 当前:第78篇 / 共108篇 · 进阶篇:Spring全家桶(第73~82篇)
- ✅ 已完成:基础篇44篇 + 第45~78篇
- 📖 正在学:第78篇
- ⏳ 待学习:第79~108篇
👉 📚 完整目录 & 学习指南 | 🔥 订阅本专栏,不错过每一篇
👉 下一篇文章预告
🚀 下一篇:《第79篇:Spring源码阅读技巧》
内容简介:Spring源码阅读方法论——如何调试Spring源码、关键类与关键方法速查(
AbstractApplicationContext、BeanFactory)、断点技巧、常见源码阅读误区。
👉 Spring全家桶专题持续推进,拿下Spring源码!
📌 《Java 100 天进阶之路 | 从入门到上岗就业》 每天一篇,建议收藏 + 关注,一起100天拿offer!
👉 点击关注我,更新后第一时间收到推送!
&spm=1001.2101.3001.5002&articleId=164003872&d=1&t=3&u=c9936c87bcd74c8a8c85cf0d0e01ba4e)
120

被折叠的 条评论
为什么被折叠?



