这是《Spring Boot 与 Spring Cloud 零基础实战指南》的独立章节版。本章从概念、实操和生产排查三个视角展开,代码块保留了原书可直接运行的版本。 自动装配是 Spring Boot 的核心能力:根据 classpath、已有 Bean、属性条件和环境类型,自动创建一组合理的默认配置。它不是魔法,而是条件化 BeanDefinition 注册机制。
8.1 @SpringBootApplication
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan
public @interface SpringBootApplication {
}
职责:
| 注解 | 作用 |
|---|---|
@SpringBootConfiguration |
声明配置类 |
@EnableAutoConfiguration |
开启自动装配 |
@ComponentScan |
扫描主类包及子包 |
如果主类放在错误包下,例如放在 com.example,业务代码在 com.example.order,没有显式扫描参数时默认能扫到;反之主类放在深层包而业务在外层包,就扫不到。
8.2 自动装配入口
Spring Boot 3 使用:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Spring Boot 2 使用:
META-INF/spring.factories
自动配置类示例:
@AutoConfiguration
@ConditionalOnClass(ObjectMapper.class)
@ConditionalOnMissingBean(ObjectMapper.class)
public class JacksonAutoConfiguration {
@Bean
public ObjectMapper objectMapper() {
return new ObjectMapper();
}
}
自动配置不是全部加载,而是逐个评估条件。
8.3 常用条件
| 注解 | 条件 |
|---|---|
@ConditionalOnClass |
类存在 |
@ConditionalOnMissingClass |
类不存在 |
@ConditionalOnBean |
Bean 存在 |
@ConditionalOnMissingBean |
Bean 不存在 |
@ConditionalOnProperty |
属性匹配 |
@ConditionalOnResource |
资源存在 |
@ConditionalOnWebApplication |
Web 应用 |
@ConditionalOnNotWebApplication |
非 Web 应用 |
@ConditionalOnExpression |
SpEL 为 true |
@AutoConfigureBefore / @AutoConfigureAfter |
配置顺序 |
示例:
@Bean
@ConditionalOnProperty(prefix = "app.cache", name = "enabled", havingValue = "true")
public LocalCache localCache() {
return new LocalCache();
}
8.4 自动装配报告
启动时开启 debug:
java -jar app.jar --debug
输出:
Positive matches:
JacksonAutoConfiguration matched:
- @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper'
Negative matches:
DataSourceAutoConfiguration did not match:
- @ConditionalOnClass did not find required class 'javax.sql.DataSource'
也可以通过 Actuator:
/actuator/conditions
排查思路:
看配置类是否匹配
-> 看 Positive / Negative 原因
-> 检查依赖
-> 检查属性
-> 检查用户是否覆盖 Bean
8.5 用户配置优先
自动配置通常使用 @ConditionalOnMissingBean:
@Bean
@ConditionalOnMissingBean(DataSource.class)
public DataSource defaultDataSource() {
return embeddedDataSource();
}
用户覆盖:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
return customDataSource();
}
}
这样用户配置优先,框架提供默认值。为了避免误覆盖,覆盖重要 Bean 时应清楚版本行为和配置类的 @AutoConfigureBefore 顺序。
8.6 自动配置顺序
@AutoConfiguration
@AutoConfigureAfter(CacheAutoConfiguration.class)
public class ReportAutoConfiguration {
}
顺序影响:
@ConditionalOnBean的判断结果;- Bean 初始化顺序;
- 代理生成;
- 属性绑定;
- Bean 覆盖关系。
在 Starter 中应显式声明顺序,而不是依赖偶然加载顺序。
8.7 编写一个自动配置
业务客户端:
public class SmsClient {
private final String endpoint;
private final RestClient restClient;
public SmsClient(String endpoint, RestClient restClient) {
this.endpoint = endpoint;
this.restClient = restClient;
}
public void send(String phone, String content) {
restClient.post().uri(endpoint).body(Map.of("phone", phone, "content", content)).retrieve().toBodilessEntity();
}
}
配置属性:
@ConfigurationProperties(prefix = "sms")
public record SmsProperties(String endpoint, Duration timeout) {
}
自动配置:
@AutoConfiguration
@EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnClass(SmsClient.class)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean(SmsClient.class)
public SmsClient smsClient(SmsProperties properties, RestClient.Builder builder) {
return new SmsClient(properties.endpoint(), builder.build());
}
}
Spring Boot 3 注册文件:
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
内容:
com.example.sms.SmsAutoConfiguration
8.8 测试自动配置
验证默认创建:
@SpringBootTest(properties = "sms.endpoint=http://localhost:8080")
class SmsAutoConfigurationTests {
@Autowired
private SmsClient smsClient;
@Test
void shouldCreateDefaultClient() {
assertThat(smsClient).isNotNull();
}
}
验证条件不满足:
@SpringBootTest(properties = "sms.enabled=false")
class SmsDisabledTests {
@Autowired
private ApplicationContext context;
@Test
void shouldNotCreateClient() {
assertThat(context.containsBean("smsClient")).isFalse();
}
}
必须覆盖:
- 默认创建;
- 用户覆盖;
- 条件不满足;
- 配置校验失败;
- 版本兼容。
8.9 常见坑
| 问题 | 原因 |
|---|---|
| 自动配置未生效 | 注册文件路径错误 |
| 条件不匹配 | 依赖缺失、属性错误 |
| Bean 被意外覆盖 | @ConditionalOnMissingBean |
| 顺序不稳定 | 未声明 @AutoConfigureAfter |
| 属性没有提示 | 缺少 metadata |
| 版本不兼容 | Starter 与 Boot 版本不匹配 |
| 打包后可用 IDE 不可用 | resources 未进入 jar |
配置提示依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
本章小结
自动装配通过注册文件和条件注解,把常见配置变成可推导的默认行为。Spring Boot 3 使用 AutoConfiguration.imports,旧版本使用 spring.factories。排查时要善用 debug 自动装配报告,理解 Positive/Negative matches。设计 Starter 时应显式声明条件、顺序、属性绑定和测试矩阵。
思考题
@ComponentScan和自动装配有什么区别?- Spring Boot 2 与 3 的自动装配注册方式有何不同?
@ConditionalOnMissingBean为什么能让用户配置优先?- 自动配置顺序为什么会影响条件判断?
- 如何为 Starter 写完整自动化测试?