Spring Boot: Spring Boot 自动配置原理
最后更新:2026-08-26
自动配置是 Spring Boot 的灵魂——它根据 classpath 上的类自动注册 Bean,让你"约定优于配置"。
1. 你将学到
@EnableAutoConfiguration与自动配置加载机制- 条件注解:
@ConditionalOnClass/@ConditionalOnMissingBean/@ConditionalOnProperty - 自定义 Starter 的创建步骤与命名规范
- 使用
--debug模式查看自动配置报告 @SpringBootApplication(exclude = {...})排除特定自动配置
2. 一个框架开发者的真实故事
(1) 痛点:每次集成都要写一堆配置
Alice 的团队要为 OrderFlow 集成一个新的支付 SDK。每次集成新组件,都要写 @Configuration 类、声明 Bean、配置属性、处理条件加载。团队成员 Bob 经常因为 Bean 冲突和循环依赖加班到深夜,光是一个 Redis 集成就配了 3 天。
(2) 自动配置的解法
Spring Boot Starter 把"集成一个组件"简化为"加一个依赖":
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
加了这个依赖后,Redis 连接工厂、RedisTemplate 全部自动配置好。
(3) 收益
Alice 创建了 OrderFlow 自定义 Starter 后,新成员集成支付 SDK 只需加一个依赖,不再需要手动配置任何 Bean,集成时间从 3 天降到 30 分钟。
3. 自动配置加载机制
(1) 从 @EnableAutoConfiguration 到 AutoConfiguration.imports
flowchart LR
A["@EnableAutoConfiguration"] --> B["Import<br/>AutoConfigurationImportSelector"]
B --> C["Read<br/>META-INF/spring/<br/>AutoConfiguration.imports"]
C --> D["Filter via<br/>@Conditional<br/>Annotations"]
D --> E["Register<br/>Qualified<br/>Auto-Configuration Classes"]
| 版本 | 加载文件 | 格式 |
|---|---|---|
| Spring Boot 2.x | META-INF/spring.factories |
key=class1,class2 |
| Spring Boot 3.x | META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports |
每行一个全限定类名 |
AutoConfiguration.imports 文件,不再使用 spring.factories 注册自动配置。
(2) 自动配置类的本质
自动配置类就是带条件注解的 @Configuration 类:
▶ 示例: DataSource 自动配置源码简化
@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnMissingBean(DataSource.class)
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConfigurationProperties("spring.datasource")
public DataSource dataSource(DataSourceProperties properties) {
return DataSourceBuilder.create()
.url(properties.getUrl())
.username(properties.getUsername())
.password(properties.getPassword())
.build();
}
}
输出:
// 执行成功
4. 条件注解详解
(1) 核心条件注解
| 注解 | 条件 | 典型用途 |
|---|---|---|
@ConditionalOnClass |
classpath 存在指定类 | 只有引入依赖才生效 |
@ConditionalOnMissingClass |
classpath 不存在指定类 | 缺少依赖时提供替代方案 |
@ConditionalOnBean |
容器中存在指定 Bean | 依赖其他 Bean 时使用 |
@ConditionalOnMissingBean |
容器中不存在指定 Bean | 提供默认 Bean,用户自定义时让路 |
@ConditionalOnProperty |
配置属性满足条件 | 通过配置开关控制功能 |
▶ 示例: @ConditionalOnProperty 开关控制
@Configuration
@ConditionalOnProperty(
prefix = "orderflow.notification",
name = "enabled",
havingValue = "true",
matchIfMissing = false
)
public class NotificationConfig {
@Bean
public NotificationService emailNotificationService() {
return new EmailNotificationService();
}
}
输出:
// 执行成功
orderflow:
notification:
enabled: true # Set false to disable notification
▶ 示例: @ConditionalOnMissingBean 提供默认实现
@Configuration
public class OrderFlowAutoConfiguration {
@Bean
@ConditionalOnMissingBean(IdGenerator.class)
public IdGenerator uuidIdGenerator() {
return new UuidIdGenerator();
}
@Bean
@ConditionalOnMissingBean(OrderNumberGenerator.class)
@ConditionalOnProperty(
prefix = "orderflow.order",
name = "number-prefix",
havingValue = "ORD",
matchIfMissing = true
)
public OrderNumberGenerator defaultOrderNumberGenerator() {
return new SequentialOrderNumberGenerator("ORD");
}
}
输出:
// 执行成功
5. 自定义 Starter
(1) Starter 命名规范
| 类型 | 命名规范 | 示例 |
|---|---|---|
| 官方 Starter | spring-boot-starter-* |
spring-boot-starter-web |
| 第三方 Starter | *-spring-boot-starter |
orderflow-spring-boot-starter |
(2) Starter 项目结构
orderflow-spring-boot-starter/
├── src/main/
│ ├── java/com/orderflow/autoconfigure/
│ │ ├── OrderFlowAutoConfiguration.java
│ │ └── OrderFlowProperties.java
│ └── resources/
│ └── META-INF/spring/
│ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
└── pom.xml
▶ 示例: 自定义 Starter 完整代码
// OrderFlowProperties.java
@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
boolean enabled,
String fromEmail,
String templatePath
) {}
// OrderFlowAutoConfiguration.java
@AutoConfiguration
@ConditionalOnClass(JavaMailSender.class)
@ConditionalOnProperty(
prefix = "orderflow.notification",
name = "enabled",
havingValue = "true"
)
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowAutoConfiguration {
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService notificationService(
OrderFlowNotificationProperties props) {
return new EmailNotificationService(
props.fromEmail(),
props.templatePath()
);
}
}
输出:
执行成功
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowAutoConfiguration
6. 调试与排除自动配置
(1) --debug 模式
启动时加 --debug 参数,Spring Boot 输出自动配置报告:
java -jar orderflow-service.jar --debug
▶ 示例: 自动配置报告解读
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required class 'javax.sql.DataSource'
Negative matches:
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory'
Exclusions:
-----------
None
Unconditional classes:
----------------------
org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration
输出:
执行成功
| 报告区域 | 含义 |
|---|---|
| Positive matches | 条件满足,已生效的自动配置 |
| Negative matches | 条件不满足,未生效的自动配置 |
| Exclusions | 被显式排除的自动配置 |
| Unconditional classes | 无条件注册的自动配置 |
(2) 排除自动配置
▶ 示例: 排除不需要的自动配置
// Method 1: Annotation exclusion
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class OrderFlowApplication { ... }
// Method 2: Configuration property
// application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
输出:
// 执行成功
| 排除方式 | 适用场景 | 灵活度 |
|---|---|---|
@SpringBootApplication(exclude) |
永远排除 | 编译时确定 |
spring.autoconfigure.exclude |
按环境排除 | 运行时可变 |
@ConditionalOnProperty |
按条件排除 | 最灵活 |
7. 综合示例:OrderFlow 通知 Starter 完整实现
// orderflow-notification-spring-boot-starter
// OrderFlowNotificationProperties.java
package com.orderflow.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
@ConfigurationProperties(prefix = "orderflow.notification")
public record OrderFlowNotificationProperties(
boolean enabled,
String fromEmail,
String templatePath,
SmtpConfig smtp
) {
public record SmtpConfig(String host, int port, boolean ssl) {}
}
// NotificationService.java
package com.orderflow.autoconfigure;
public interface NotificationService {
void send(String to, String subject, String body);
}
// EmailNotificationService.java
package com.orderflow.autoconfigure;
public class EmailNotificationService implements NotificationService {
private final String fromEmail;
private final String templatePath;
public EmailNotificationService(String fromEmail, String templatePath) {
this.fromEmail = fromEmail;
this.templatePath = templatePath;
}
@Override
public void send(String to, String subject, String body) {
// Email sending logic
System.out.printf("Send to %s: [%s] %s%n", to, subject, body);
}
}
// OrderFlowNotificationAutoConfiguration.java
package com.orderflow.autoconfigure;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
@AutoConfiguration
@ConditionalOnClass(name = "org.springframework.mail.javamail.JavaMailSender")
@ConditionalOnProperty(prefix = "orderflow.notification", name = "enabled", havingValue = "true")
@EnableConfigurationProperties(OrderFlowNotificationProperties.class)
public class OrderFlowNotificationAutoConfiguration {
@Bean
@ConditionalOnMissingBean(NotificationService.class)
public NotificationService notificationService(OrderFlowNotificationProperties props) {
return new EmailNotificationService(props.fromEmail(), props.templatePath());
}
}
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.orderflow.autoconfigure.OrderFlowNotificationAutoConfiguration
❓ 常见问题
📖 小节
- Spring Boot 3.x 使用
AutoConfiguration.imports文件注册自动配置类 - 自动配置类的核心是条件注解:
@ConditionalOnClass、@ConditionalOnMissingBean、@ConditionalOnProperty @ConditionalOnMissingBean实现"用户定义优先"原则- 自定义 Starter 命名:官方
spring-boot-starter-*,第三方*-spring-boot-starter --debug模式和 Actuator 端点可查看自动配置报告
📝 作业
-
基础题(难度⭐):使用
--debug模式启动 OrderFlow 项目,列出所有 Positive matches 中的自动配置类,理解每个自动配置依赖的 classpath 条件。 -
进阶题(难度⭐⭐):创建一个
orderflow-spring-boot-starter,包含@ConditionalOnProperty开关控制的通知功能,在 OrderFlow 项目中引入并验证。 -
挑战题(难度⭐⭐⭐):实现一个支持多实现的自动配置——当 classpath 有 Kafka 时使用 Kafka 通知,否则使用 Email 通知,两者都不可用时使用日志通知,思考条件注解的优先级和互斥设计。