在 Spring Boot 的开发日常中,我们几乎每天都要和配置类打交道。 很多同学有这样的误区:“配置类不就是加个 @Configuration,再写几个 @Bean 吗?”
如果你只是在写业务项目,这话没毛病。但如果你想进阶架构师,开始尝试封装公共组件、编写 Starter,或者维护公司内部的 SDK,你会发现:简单的 @Configuration 根本不够用,甚至会带来严重的加载顺序问题和包扫描耦合。
今天,我们就从零开始,彻底讲透 Spring Boot 配置体系中的这一对“孪生兄弟”:@Configuration 与 @AutoConfiguration。
环境准备:一切的起点
要演示这两个注解的区别,我们首先需要一个标准的 Spring Boot 环境。
在 Maven 依赖中,我们不需要引入复杂的第三方包,核心只依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
注:本文基于 Spring Boot 2.7+ 及 3.x 版本讲解,这是目前官方推荐的规范。
基础篇:@Configuration 的正确姿势
场景: 你正在开发一个业务系统(Application),比如一个电商平台的订单服务。你需要配置一个数据库连接池,或者注册一个业务 Bean。
用法: 这是我们最熟悉的方式。
- 创建一个类。
- 打上 @Configuration 注解。
- Spring 启动时,通过 @ComponentScan(通常包含在启动类里)扫描当前包及其子包,发现这个类,并加载其中的 Bean。
代码示例:

点评:
@Configuration 是 Spring 框架的原住民。 它的特点是:依赖包扫描。也就是说,这个配置类必须在你的主启动类(Application)的扫描范围内。适用范围: 业务逻辑、应用内部配置。
进阶篇:@AutoConfiguration 的登场
场景: 你的身份变了。你现在要为全公司的 50 个微服务项目封装一个“通用日志组件”。 这个组件作为一个独立的 .jar 包发布。
问题来了:别的项目引入你的 jar 包后,他们的启动类包名是 com.a,而你的组件包名是 com.b。包名不一致,Spring 根本扫不到你的 @Configuration。 强迫别人在启动类上加 @ComponentScan("com.b")?太 Low 了,且高耦合。


解法: 使用 @AutoConfiguration 配合 SPI 机制。
步骤一:修改注解
不再使用 @Configuration,而是使用 Spring Boot 2.7 引入的专用注解:
// 这是一个给别人用的自动配置类
@AutoConfiguration
public class MyLibraryAutoConfig {
@Bean
@ConditionalOnMissingBean // 优雅的退让,允许用户覆盖
public MyService myService() {
return new MyService();
}
}
步骤二:注册 SPI 文件 (关键)
我们不靠扫描,靠“登记”。 在 src/main/resources 下创建目录 META-INF/spring/,并新建文件 org.springframework.boot.autoconfigure.AutoConfiguration.imports。
文件内容:
com.yann.library.MyLibraryAutoConfig
点评:
只要完成了这两步,无论谁引用你的 jar 包,Spring Boot 都会通过读取 .imports 文件自动把配置加载进来。这才是真正的“开箱即用”。
核心篇:为什么要区分这两个?
很多同学会问:“以前用 spring.factories 配 @Configuration 不也能自动装配吗?为什么要搞个新注解?”
这就涉及到了 Spring Boot 的加载生命周期设计哲学。
1. 加载顺序 (Ordering) —— 这是最大的坑
- @Configuration (应用级):被视为“一等公民”,优先加载。
- @AutoConfiguration (组件级):被视为“二等公民”,永远在应用级配置之后加载。
为什么这么设计?是为了方便覆盖! 想象一下:你写了一个 Starter,里面有一个默认的 Bean。用户觉得不好用,在自己的代码里(@Configuration)重写了一个同名的 Bean。
- 因为用户的
@Configuration先执行,容器里先有了 Bean。
- 等到你的
@AutoConfiguration后执行时,配合 @ConditionalOnMissingBean,发现容器里已经有了,你的默认逻辑就会自动跳过。
2. 语义分离
Spring 官方希望明确界限:
- @Configuration = 用户配置(App Domain)
- @AutoConfiguration = 框架/库配置(Infrastructure Domain)
总结与建议
最后,为大家整理了一张决策表,建议保存:
| 维度 |
@Configuration |
@AutoConfiguration |
| 生效机制 |
依赖包扫描 (@ComponentScan) |
依赖 SPI 文件 (.imports) |
| 加载优先级 |
高 (先于自动配置) |
低 (后于应用配置) |
| 典型用途 |
业务逻辑、本项目配置 |
开发 Starter、公共类库 |
| 推荐包名 |
与启动类同包或子包 |
独立包名,无限制 |
一句话总结:如果你在写业务代码,请用 @Configuration;如果你在造轮子、写 SDK,请务必拥抱 @AutoConfiguration。
希望这篇文章能帮你理清这两个核心配置注解的区别。如果你想了解更多关于系统架构或高级 Java 开发技巧,欢迎在 云栈社区 交流探讨。