目录
[① 导读卡片](#① 导读卡片)
[② 背景与目标](#② 背景与目标)
[③ 概念与原理](#③ 概念与原理)
[@Conditional 条件判断示例](#@Conditional 条件判断示例)
[④ 逻辑与对比](#④ 逻辑与对比)
[自动配置 vs 手动 @Bean](#自动配置 vs 手动 @Bean)
[⑤ 核心详解](#⑤ 核心详解)
[1. 启动入口:@SpringBootApplication](#1. 启动入口:@SpringBootApplication)
[2. 配置清单:AutoConfiguration.imports](#2. 配置清单:AutoConfiguration.imports)
[3. @Conditional 条件注解大全](#3. @Conditional 条件注解大全)
[4. 经典案例:RedisAutoConfiguration 源码](#4. 经典案例:RedisAutoConfiguration 源码)
[5. 自动配置的执行顺序](#5. 自动配置的执行顺序)
[⑥ 案例实战](#⑥ 案例实战)
[实战 1:查看哪些自动配置生效了](#实战 1:查看哪些自动配置生效了)
[实战 2:覆盖默认自动配置](#实战 2:覆盖默认自动配置)
[实战 3:关闭不必要的自动配置](#实战 3:关闭不必要的自动配置)
[实战 4:自定义 Starter(让其他人也能自动配置你的组件)](#实战 4:自定义 Starter(让其他人也能自动配置你的组件))
[⑦ 避坑 & 最佳实践](#⑦ 避坑 & 最佳实践)
[❌ 常见坑点](#❌ 常见坑点)
[✅ 最佳实践](#✅ 最佳实践)
[⑧ 总结 & 路线图](#⑧ 总结 & 路线图)
① 导读卡片
| 项目 | 内容 |
|---|---|
| 一句话定位 | 搞懂 Spring Boot 自动配置(AutoConfiguration)的原理,理解为什么引入依赖就能直接用,不用写一行 @Bean |
| 适合人群 | Spring Boot 初学者、想理解「约定大于配置」的开发者 |
| 难度 | ⭐⭐⭐(中等) |
| 阅读时长 | 12 分钟 |
| 前置知识 | 会用 @Bean 注册组件,了解 Spring IoC 基本概念 |
② 背景与目标
为什么需要自动配置?
传统 Spring 项目时代,你要用 Redis,得写这样的代码:
java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, String> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new Jackson2JsonRedisSerializer<>(Object.class));
return template;
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory("localhost", 6379);
}
}
每个项目都写一遍,烦不烦?
自动配置(AutoConfiguration) 就是 Spring Boot 帮你解决了这个痛点------提前写好这些 @Bean 代码,你引入依赖就能直接用。
学完本文,你能够:
理解自动配置「自动」在哪里
知道什么组件有自动配置、什么需要手动写 @Bean
学会查找和覆盖自动配置
能用启停日志诊断自动配置问题
③ 概念与原理
什么是自动配置?
一句话:
自动配置 = Spring Boot 提前写好的 @Bean 配置类,按需生效,无需手动注册。
自动配置是 Spring Boot 实现**「约定大于配置(Convention over Configuration)」**的核心机制。
底层原理三件套
自动配置靠三个「法宝」实现:
| 组件 | 作用 | 类比 |
|---|---|---|
@EnableAutoConfiguration |
开启自动配置的总开关 | 家里的总电闸 |
spring.factories |
记录所有自动配置类的名单 | 通讯录 |
@Conditional 系列注解 |
判断条件是否满足才生效 | 过滤器 |
启动时发生了啥?
@Conditional 条件判断示例
java
@Configuration
@ConditionalOnClass(RedisOperations.class) // 必须有 Redis 相关类
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate") // 没有自定义才创建
public RedisTemplate<Object, Object> redisTemplate() {
// ...
}
@Bean
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate() {
// ...
}
}
执行逻辑:
-
类路径上有
RedisOperations(即引入了spring-boot-starter-data-redis)→ ✅ 条件满足 -
容器中没有用户自定义的
redisTemplate→ ✅ 条件满足,创建默认 Bean -
用户自己写了一个
@Bean redisTemplate()→ ❌ 条件不满足,自动配置不覆盖
④ 逻辑与对比
自动配置 vs 手动 @Bean
| 场景 | 需要手动写 @Bean? | 核心原因 |
|---|---|---|
| Redis - StringRedisTemplate | ❌ 不需要 | 有 RedisAutoConfiguration 兜底 |
| Redis - 自定义序列化 | ✅ 需要 | 自动配置是默认行为,自定义需求要覆盖 |
| MyBatis-Plus 核心 Mapper | ❌ 不需要 | MybatisPlusAutoConfiguration 自动注册 |
| MyBatis-Plus 分页拦截器 | ✅ 需要 | 数据库类型无法自动推断 |
| RestTemplate(无配置) | ❌ 不需要 | RestTemplateAutoConfiguration 有默认 |
| RestTemplate(配置超时) | ✅ 需要 | 默认 Bean 无法满足定制需求 |
| 自己的业务类 | ❌ 用 @Component | 在自己的包路径下,组件扫描即可 |
自动配置的生效原则

├── 我引入的 Starter # 触发条件
│ └── AutoConfiguration 类被加载 # spring.factories 注册
│ └── @Conditional 条件全通过 # 类存在 + 属性配置 + Bean 不存在
│ └── 自动注册默认 Bean # 可以注入使用
│
└── 我手动写了 @Bean # 优先级高于自动配置
└── @ConditionalOnMissingBean 条件不满足
└── 自动配置跳过,用我的
⑤ 核心详解
1. 启动入口:@SpringBootApplication
java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Configuration // 标记为配置类
@EnableAutoConfiguration // ⭐ 开启自动配置
@ComponentScan // 开启组件扫描
public @interface SpringBootApplication {
}
三个注解合成一个,所以你只需要写
@SpringBootApplication。
2. 配置清单:AutoConfiguration.imports
Spring Boot 3.x 的自动配置名单文件路径:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
内容示例(来自 spring-boot-autoconfigure 包):
java
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
... 上百个自动配置类
// Spring Boot 2.x 及之前版本使用 META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
...
3. @Conditional 条件注解大全
| 注解 | 判断条件 | 示例场景 |
|---|---|---|
@ConditionalOnClass |
类路径上有指定类 | RedisAutoConfiguration 需要 RedisOperations.class |
@ConditionalOnMissingClass |
类路径上没有指定类 | 排除某些依赖时生效 |
@ConditionalOnBean |
容器中有指定 Bean | 依赖其他 Bean 时 |
@ConditionalOnMissingBean |
容器中没有指定 Bean | 用户未自定义时才创建默认 Bean |
@ConditionalOnProperty |
配置文件中指定属性满足条件 | 通过 application.yml 控制开关 |
@ConditionalOnResource |
类路径上有指定资源文件 | 检查配置文件是否存在 |
@ConditionalOnWebApplication |
当前是 Web 环境 | Web 相关功能才注册 |
@ConditionalOnNotWebApplication |
当前不是 Web 环境 | 非 Web 项目排除 Web 功能 |
@ConditionalOnExpression |
SpEL 表达式为 true | 复杂条件判断 |
4. 经典案例:RedisAutoConfiguration 源码
java
@AutoConfiguration // @Configuration 的别名
@ConditionalOnClass(RedisOperations.class) // 1. 必须有 Redis 相关类
@EnableConfigurationProperties(RedisProperties.class) // 2. 绑定配置属性
public class RedisAutoConfiguration {
@Bean // 3. 默认的 RedisTemplate
@ConditionalOnMissingBean(name = "redisTemplate")
public RedisTemplate<Object, Object> redisTemplate(
RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
@Bean // 4. 默认的 StringRedisTemplate
@ConditionalOnMissingBean(StringRedisTemplate.class)
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory redisConnectionFactory) {
StringRedisTemplate template = new StringRedisTemplate();
template.setConnectionFactory(redisConnectionFactory);
return template;
}
}
RedisProperties 绑定 spring.redis.* 配置:
java
@ConfigurationProperties(prefix = "spring.redis")
public class RedisProperties {
private String host = "localhost"; // 默认值
private int port = 6379; // 默认值
private String password;
private int database = 0;
// getter / setter ...
}
所以你在 application.yml 写这个就能连接 Redis:
java
spring:
redis:
host: 192.168.1.100
port: 6379
password: mypass
5. 自动配置的执行顺序
多个自动配置类之间有依赖关系时,用 @AutoConfigureOrder 和 @AutoConfigureAfter/Before 控制:
java
@AutoConfiguration
@AutoConfigureAfter(DataSourceAutoConfiguration.class) // 在数据源之后执行
@ConditionalOnClass(DataSource.class)
public class MyBatisPlusAutoConfiguration {
// ...
}
⑥ 案例实战
实战 1:查看哪些自动配置生效了
java
# application.yml
debug: true
启动日志会显示:
java
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches: // ✅ 生效的自动配置
-----------------
RedisAutoConfiguration matched:
- @ConditionalOnClass found required class
'org.springframework.data.redis.core.RedisOperations' (OnClassCondition)
- @ConditionalOnMissingBean (types:
org.springframework.data.redis.core.RedisTemplate;
SearchStrategy: all) did not find any beans (OnBeanCondition)
Negative matches: // ❌ 未生效的自动配置
-----------------
ActiveMQAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class
'jakarta.jms.ConnectionFactory' (OnClassCondition)
Positive matches- 生效的;Negative matches- 未生效的(通常因为没引入对应依赖)
实战 2:覆盖默认自动配置
场景 :Redis 默认的 RedisTemplate 使用 JDK 序列化,存入的值是乱码。我想用 JSON 序列化。
java
@Configuration
public class MyRedisConfig {
// 方法 1:完全覆盖,自己定义所有细节
@Bean
public RedisTemplate<String, Object> redisTemplate(
RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 使用 Jackson JSON 序列化
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(Object.class);
ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
mapper.activateDefaultTyping(
ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);
serializer.setObjectMapper(mapper);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
template.afterPropertiesSet();
return template;
}
// 方法 2:只覆盖部分配置(StringRedisTemplate 保持默认)
@Bean
@ConditionalOnMissingBean // 如果别人也定义了,就不创建
public StringRedisTemplate stringRedisTemplate(
RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);
}
}
⚠️ 原理 :自动配置中的
@ConditionalOnMissingBean检查到你已经定义了同名 Bean,自动跳过。你的@Bean优先级最高。
实战 3:关闭不必要的自动配置
java
# application.yml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
或用注解排除:
java
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
典型场景 :只有 MyBatis 不需要 JPA,或者没有数据源时排除
DataSourceAutoConfiguration避免报错。
实战 4:自定义 Starter(让其他人也能自动配置你的组件)
java
// 1. 自动配置类
@AutoConfiguration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties.getUrl(), properties.getTimeout());
}
}
// 2. 配置属性
@ConfigurationProperties(prefix = "my.service")
public class MyProperties {
private String url = "http://localhost:8080";
private int timeout = 5000;
// getter / setter ...
}
// 3. 注册自动配置
// 在 resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中写入:
// com.example.MyAutoConfiguration
⑦ 避坑 & 最佳实践
❌ 常见坑点
坑 1:自动配置不生效,但没报错
症状:@Autowired 某个 Bean 报 NoSuchBeanDefinitionException
原因:漏了引入 Starter 依赖,或包扫描路径不对
排查:开启 debug=true 看 Negative matches
坑 2:自动配置的 Bean 和自定义的冲突
症状:发现自己的配置没生效
原因:自动配置中有 @ConditionalOnMissingBean,但你的 Bean 名称或类型不匹配
排查:看 Positive matches 确认自动配置是否真的跳过了
坑 3:多个自动配置互相依赖报错
症状:启动时 NoSuchBeanDefinitionException,但依赖明明引入了
原因:自动配置执行顺序问题
排查:使用 @AutoConfigureAfter / @AutoConfigureBefore / @AutoConfigureOrder
坑 4:@ConditionalOnClass 类名写错
@ConditionalOnClass(name = "com.example.NonexistentClass")
// 不会报编译错,但条件永远不满足 -> 自动配置永远不生效
✅ 建议用 Class 字面量而不是字符串:@ConditionalOnClass(RedisOperations.class)
✅ 最佳实践
| 场景 | 做法 |
|---|---|
| 想了解有哪些自动配置 | 开启 debug: true |
| 想排除不需要的自动配置 | 用 spring.autoconfigure.exclude |
| 想覆盖默认 Bean | 自己写 @Bean,自动配置会跳过 |
| 想用自定义配置值 | 用 application.yml 覆盖 @ConfigurationProperties 默认值 |
| 写自己的 Starter | 遵守 spring-boot-starter-* 命名规范 |
⑧ 总结 & 路线图
记住了什么?
自动配置核心三件套:
① @EnableAutoConfiguration - 总开关
② AutoConfiguration.imports - 通讯录(所有自动配置类名单)
③ @Conditional 条件注解 - 按需生效
自动配置 vs 手动 @Bean:
- 自动配置 = 兜底方案(默认行为)
- 手动 @Bean = 自定义覆盖(优先级更高)
一句话:引入 Starter → 条件满足 → 自动注册 → 直接使用
下一步去哪?
| 学习方向 | 推荐内容 |
|---|---|
| 自定义 Starter | 学习如何封装并发布自己的自动配置 |
| @Conditional 源码 | 深入看 Spring 条件判断的实现 |
| 配置文件加载优先级 | 了解 application.yml 加载顺序 |
| 外部化配置 | 学习 @ConfigurationProperties 绑定机制 |
互动:你被自动配置「坑」过吗?某个组件怎么注入都是空?来评论区分享你的诊断经验 🚑