在 Spring Boot 2.7+ / 3.x / 4.x 里,可以这样理解:
@Configuration 是“普通配置类”;@AutoConfiguration 是“给 Spring Boot 自动装配机制使用的特殊配置类”。
@AutoConfiguration 本质上也是 @Configuration,但它不是给业务项目随手写配置用的,而是给 starter / 第三方库 / 自动装配模块 用的。
Spring 官方文档也明确说:实现自动配置的类使用 @AutoConfiguration,它本身被 @Configuration 元注解标注,所以自动配置类也是标准的 @Configuration 类;通常还会配合 @ConditionalOnClass、@ConditionalOnMissingBean 等条件注解。(Home)
1. 核心区别
| 对比点 | @Configuration | @AutoConfiguration |
|---|---|---|
| 来源 | Spring Framework | Spring Boot |
| 作用 | 声明普通配置类,注册 Bean | 声明 Spring Boot 自动配置类 |
| 使用场景 | 业务项目内部手动配置 | starter、组件库、框架集成自动装配 |
| 加载方式 | 通常靠 @ComponentScan、@Import、手动注册 | 通常靠 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 被 Boot 自动发现 |
| 条件判断 | 可以加,也可以不加 | 通常必须配合条件注解,避免强行生效 |
| Bean 方法代理 | 默认 proxyBeanMethods = true | 固定等价于 @Configuration(proxyBeanMethods = false) |
| 排序能力 | 普通配置类没有专门的自动配置排序语义 | 支持 before、after、@AutoConfigureBefore、@AutoConfigureAfter 等自动配置排序 |
| 典型命名 | WebConfig、RedisConfig、MyBatisConfig | XxxAutoConfiguration |
官方 Javadoc 里对 @AutoConfiguration 的描述是:它表示一个类提供可由 Spring Boot 自动应用的配置;自动配置类是普通 @Configuration,但 proxyBeanMethods 总是 false,并且通过 ImportCandidates 定位。(Home)
2. @Configuration 示例:业务项目里主动配置 Bean
假设你在自己的业务系统里要配置一个短信服务:
@Configuration
public class SmsConfig {
@Bean
public SmsClient smsClient() {
return new SmsClient("https://sms.example.com", "your-token");
}
}
只要这个类在 Spring Boot 启动类的扫描路径下,例如:
@SpringBootApplication
public class OrderApplication {
public static void main(String[] args) {
SpringApplication.run(OrderApplication.class, args);
}
}
包结构如下:
com.example.order
├── OrderApplication.java
└── config
└── SmsConfig.java
那么 SmsConfig 会作为普通配置类被扫描到,smsClient 这个 Bean 会注册进 Spring 容器。
这就是 @Configuration 的典型用法:你明确知道当前项目需要这个配置,所以直接写在项目里。 Spring Framework 的 Javadoc 也说明,@Configuration 类可以通过 AnnotationConfigApplicationContext 注册,也可以通过组件扫描被发现,因为它是 @Component 的派生注解。(Home)
3. @AutoConfiguration 示例:做一个自动装配 starter
现在假设你不是在业务项目里写短信配置,而是在开发一个公共组件:
sms-spring-boot-starter
你希望别人只要引入依赖:
<dependency>
<groupId>com.example</groupId>
<artifactId>sms-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
然后在配置文件中写:
sms: enabled: true endpoint: https://sms.example.com token: abc123
就能自动拥有一个 SmsClient Bean。
这时就适合使用 @AutoConfiguration。
第一步:定义属性类
@ConfigurationProperties(prefix = "sms")
public class SmsProperties {
private boolean enabled = true;
private String endpoint;
private String token;
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getEndpoint() {
return endpoint;
}
public void setEndpoint(String endpoint) {
this.endpoint = endpoint;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
第二步:定义自动配置类
@AutoConfiguration
@EnableConfigurationProperties(SmsProperties.class)
@ConditionalOnClass(SmsClient.class)
@ConditionalOnProperty(prefix = "sms", name = "enabled", havingValue = "true", matchIfMissing = true)
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsClient smsClient(SmsProperties properties) {
return new SmsClient(properties.getEndpoint(), properties.getToken());
}
}
这里的含义是:
@AutoConfiguration
表示这是一个 Spring Boot 自动配置类。
@ConditionalOnClass(SmsClient.class)
表示只有 classpath 中存在 SmsClient 这个类时,自动配置才生效。
@ConditionalOnProperty(...)
表示只有用户没有关闭 sms.enabled 时才生效。
@ConditionalOnMissingBean
表示如果用户自己已经定义了 SmsClient,那自动配置就让路。
这正是 Spring Boot 自动配置的核心思想:我可以帮你配,但如果你自己配了,就以你的为准。 Spring Boot 官方文档也说明,自动配置是非侵入式的;例如用户自己定义 DataSource Bean 后,默认的嵌入式数据库支持就会退让。(Home)
4. 关键点:@AutoConfiguration 不是只写注解就会生效
自动配置类还需要在 starter 的资源目录中声明。
文件位置必须是:
src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件内容:
com.example.sms.autoconfigure.SmsAutoConfiguration
Spring Boot 会检查 jar 包中的这个文件,并把里面列出的自动配置类作为候选自动配置类加载;文件里每行写一个自动配置类全限定名。(Home)
所以,完整结构大概是:
sms-spring-boot-starter
└── src
└── main
├── java
│ └── com.example.sms.autoconfigure
│ ├── SmsAutoConfiguration.java
│ └── SmsProperties.java
└── resources
└── META-INF
└── spring
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports
5. 加载方式差异:这是最容易混淆的地方
@Configuration 的加载方式
普通业务配置类通常这样被加载:
@SpringBootApplication
public class DemoApplication {
}
@SpringBootApplication 默认会扫描当前包及其子包,所以:
com.example.demo
├── DemoApplication.java
└── config
└── RedisConfig.java
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate() {
// ...
}
}
这种配置类通常直接被组件扫描发现。
@AutoConfiguration 的加载方式
自动配置类不应该依赖业务项目的组件扫描路径,而是靠:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
被 Spring Boot 自动配置机制发现。
也就是说,业务项目并不需要写:
@Import(SmsAutoConfiguration.class)
也不需要把 starter 的包放进 @ComponentScan。
它只要引入 starter,Boot 就会根据自动配置候选列表、classpath、条件注解、用户是否已有 Bean 等信息来决定是否启用该配置。Spring Boot 官方文档还特别强调,自动配置类应该只通过 imports 文件加载,不应成为组件扫描的目标,也不应通过组件扫描去发现额外组件。(Home)
6. 为什么 @AutoConfiguration 通常要配条件注解?
因为自动配置是“潜在生效”的。只要用户引入了你的 starter,你的配置就有机会进入候选列表。
如果你这样写:
@AutoConfiguration
public class SmsAutoConfiguration {
@Bean
public SmsClient smsClient() {
return new SmsClient("default-endpoint", "default-token");
}
}
问题是:用户可能只是间接引入了这个依赖,并不想真的启用短信功能。
所以自动配置类通常要写成:
@AutoConfiguration
@ConditionalOnClass(SmsClient.class)
@ConditionalOnProperty(prefix = "sms", name = "enabled", havingValue = "true")
public class SmsAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public SmsClient smsClient(SmsProperties properties) {
return new SmsClient(properties.getEndpoint(), properties.getToken());
}
}
这体现了自动配置的几个基本原则:
-
有相关类才配置:@ConditionalOnClass
-
用户开启了才配置:@ConditionalOnProperty
-
用户没自定义才配置:@ConditionalOnMissingBean
-
配置失败不要影响无关项目:尽量做到“引入但不用也没事”
官方文档也说,自动配置类通常使用 @ConditionalOnClass 和 @ConditionalOnMissingBean,确保只有相关类存在且用户没有声明自己的配置时才应用。(Home)
7. proxyBeanMethods 的区别
@Configuration 默认是 proxyBeanMethods = true
例如:
@Configuration
public class AppConfig {
@Bean
public A a() {
return new A();
}
@Bean
public B b() {
return new B(a());
}
}
在 proxyBeanMethods = true 时,Spring 会通过 CGLIB 代理配置类。b() 方法里调用 a(),拿到的仍然是 Spring 容器中的单例 A,而不是每次 new 一个新的 A。
等价理解:
new B(springContainer.getBean(A.class));
@AutoConfiguration 固定是 proxyBeanMethods = false
@AutoConfiguration 等价于:
@Configuration(proxyBeanMethods = false)
所以自动配置类中通常不建议这样写:
@AutoConfiguration
public class BadAutoConfiguration {
@Bean
public A a() {
return new A();
}
@Bean
public B b() {
return new B(a()); // 不推荐
}
}
更推荐写成方法参数注入:
@AutoConfiguration
public class GoodAutoConfiguration {
@Bean
public A a() {
return new A();
}
@Bean
public B b(A a) {
return new B(a);
}
}
这样 B 依赖的 A 会由 Spring 容器注入,不依赖配置类方法代理。
8. 自动配置可以排序,普通配置通常不关心这个
@AutoConfiguration 可以这样写:
@AutoConfiguration(after = DataSourceAutoConfiguration.class)
public class MyOrmAutoConfiguration {
}
表示当前自动配置应该在 DataSourceAutoConfiguration 之后处理。
也可以使用:
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
@AutoConfiguration
public class MyOrmAutoConfiguration {
}
@AutoConfiguration 的 Javadoc 里也列出了 before、beforeName、after、afterName 等属性,用于指定自动配置类之间的应用顺序。(Home)
不过要注意:自动配置类的顺序主要影响 Bean 定义的注册顺序,不等于 Bean 实例的创建顺序。Bean 的创建顺序仍主要由依赖关系、@DependsOn 等决定;Spring Boot 官方文档也有这个说明。(Home)
9. 一个完整对比例子
场景 A:你在自己的项目中配置对象存储客户端
这时用 @Configuration:
@Configuration
public class OssConfig {
@Bean
public OssClient ossClient() {
return new OssClient(
"https://oss.example.com",
"accessKey",
"secretKey"
);
}
}
这是业务项目自己的配置,简单直接。
场景 B:你开发一个 oss-spring-boot-starter
这时用 @AutoConfiguration:
@AutoConfiguration
@EnableConfigurationProperties(OssProperties.class)
@ConditionalOnClass(OssClient.class)
@ConditionalOnProperty(prefix = "oss", name = "enabled", havingValue = "true", matchIfMissing = true)
public class OssAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public OssClient ossClient(OssProperties properties) {
return new OssClient(
properties.getEndpoint(),
properties.getAccessKey(),
properties.getSecretKey()
);
}
}
配置属性:
@ConfigurationProperties(prefix = "oss")
public class OssProperties {
private String endpoint;
private String accessKey;
private String secretKey;
// getter / setter
}
自动配置声明文件:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
内容:
com.example.oss.autoconfigure.OssAutoConfiguration
使用方只需要:
oss: endpoint: https://oss.example.com access-key: abc secret-key: xyz
然后直接注入:
@Service
public class FileService {
private final OssClient ossClient;
public FileService(OssClient ossClient) {
this.ossClient = ossClient;
}
}
这就是自动配置的价值:starter 作者写自动配置,业务系统按需引入即可。
10. 常见误区
误区 1:@AutoConfiguration 比 @Configuration 更高级,所以业务配置都该用它
不对。
业务系统里的普通配置类应该优先用:
@Configuration
例如:
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
}
只有你在做 自动装配组件、starter、框架集成 时,才考虑:
@AutoConfiguration
误区 2:写了 @AutoConfiguration 就一定会被加载
不对。
通常还必须在:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
中声明它。
只写:
@AutoConfiguration
public class MyAutoConfiguration {
}
但没有 imports 文件,Spring Boot 的自动配置机制通常不会把它作为自动配置候选类加载。
误区 3:自动配置会覆盖用户配置
一般不会,前提是自动配置类写得规范。
规范写法应该加:
@ConditionalOnMissingBean
例如:
@Bean
@ConditionalOnMissingBean
public SmsClient smsClient() {
return new SmsClient();
}
这样用户自己定义了:
@Bean
public SmsClient smsClient() {
return new CustomSmsClient();
}
自动配置就不会再创建默认的 SmsClient。
误区 4:@AutoConfiguration 不能被组件扫描发现
更准确地说:它不应该依赖组件扫描来加载。
因为 @AutoConfiguration 本质上也是 @Configuration,而 @Configuration 又是组件类注解体系的一部分;但 Spring Boot 官方建议自动配置类要放在独立包空间中,并且不要成为组件扫描目标,而是通过 imports 文件加载。(Home)
11. 一句话总结
@Configuration 适合写在当前应用内部,表示“我要主动注册这些 Bean”。
@AutoConfiguration 适合写在starter 或公共组件库里,表示“当用户引入我、条件满足、且用户没有自己配置时,我帮他自动注册这些 Bean”。
最简单的判断方式:
业务项目自己的配置 → @Configuration 给 starter 自动装配使用 → @AutoConfiguration
例如:
// 业务系统内部
@Configuration
public class RedisConfig {
}
// starter / 自动装配模块
@AutoConfiguration
@ConditionalOnClass(RedisTemplate.class)
@ConditionalOnMissingBean(RedisTemplate.class)
public class RedisAutoConfiguration {
}
【豆包】Springboot中 @AutoConfiguration 与 @Configuration 的区别,举例详细说明?
这两个注解都是声明配置类的核心注解,但使用场景、加载时机、作用范围完全不同,是 SpringBoot 自动配置机制的关键设计。
先给你一句话总结:
- @Configuration:手动配置,写在自己项目里,只对当前项目生效,需要被 Spring 主动扫描到。
- @AutoConfiguration:自动配置,专门用于 ** starter 自动配置类 **,无需扫描,SpringBoot 启动时自动加载,给第三方库 / 框架做自动配置。
一、核心区别对照表
表格
| 特性 | @Configuration | @AutoConfiguration |
|---|---|---|
| 来源 | Spring 原生注解 | SpringBoot 2.7.0+ 新增注解 |
| 核心作用 | 定义普通配置类 | 定义自动配置类 |
| 使用场景 | 项目自身业务配置 | 自定义 starter、框架自动配置 |
| 加载方式 | 需要 @ComponentScan 扫描 | 从 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 读取加载 |
| 加载时机 | 与普通 Bean 同步加载 | 专门的自动配置阶段,晚于手动配置 |
| 顺序控制 | 无专门顺序控制 | 支持 @AutoConfigureOrder、@AutoConfigureBefore、@AutoConfigureAfter 精确控制顺序 |
| 条件注解 | 可配合 @Conditional | 必须配合条件注解(如 @ConditionalOnClass),否则会强制加载 |
| 继承关系 | 元注解包含 @Component | 元注解包含 @Configuration,是它的加强版 |
底层原理:@AutoConfiguration 内部就是 @Configuration + 自动配置专属标记,所以它拥有配置类的所有能力,但多了自动配置的专属特性。
二、详细举例说明
1. @Configuration 用法(项目内手动配置)
适用场景:你自己的项目里,需要手动注册 Bean、配置组件(如线程池、拦截器、Redis 连接等)。
步骤 1:编写配置类
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 项目自己的配置类:手动配置线程池
* 必须被 @ComponentScan 扫描到(同包或子包下)
*/
@Configuration
public class MyThreadPoolConfig {
// 手动注册 Bean
@Bean
public ExecutorService myThreadPool() {
return Executors.newFixedThreadPool(5);
}
}
步骤 2:启动类(无需额外配置)
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
// @SpringBootApplication 自带 @ComponentScan,会自动扫描同包下的 @Configuration
@SpringBootApplication
public class MyProjectApplication {
public static void main(String[] args) {
SpringApplication.run(MyProjectApplication.class, args);
}
}
✅ 特点:
- 写在项目里,只对当前项目生效
- 必须被 Spring 扫描到
- 没有顺序控制,加载顺序随机
2. @AutoConfiguration 用法(自动配置 / 自定义 Starter)
适用场景:封装通用组件、自定义 Starter、给第三方框架做自动配置(比如 MyBatis、Redis starter 底层都是用它)。
自动配置类不能被 @ComponentScan 扫描,否则会变成普通配置类,失去自动配置意义。
步骤 1:编写自动配置类
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 自动配置类:用于自定义 Starter
* 注意:不能被 @ComponentScan 扫描!
*/
// 标记这是一个自动配置类
@AutoConfiguration
// 条件:当项目中存在 ThreadPool 类时才生效
@ConditionalOnClass(ExecutorService.class)
public class MyStarterAutoConfig {
// 条件:当用户没有自己注册线程池时,才自动注册
@Bean
@ConditionalOnMissingBean
public ExecutorService autoThreadPool() {
return Executors.newFixedThreadPool(10);
}
}
步骤 2:注册自动配置类(关键)
在 resources/META-INF/spring/ 下创建文件: org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件内容填写自动配置类全限定名:
com.example.mystarter.MyStarterAutoConfig
✅ 特点:
- 无需扫描,SpringBoot 启动自动加载
- 必须配合条件注解(@ConditionalOnXXX)
- 支持精确控制加载顺序
- 用于通用组件 / Starter,给所有引入该依赖的项目自动配置
三、最关键的 3 个核心区别
1. 加载方式完全不同
- @Configuration:靠 @ComponentScan 扫描加载,不扫描就不生效。
- @AutoConfiguration:靠 SpringBoot 读取 imports 文件加载,无需扫描。
2. 加载时机与顺序
- @Configuration:普通配置阶段,顺序不可控。
- @AutoConfiguration:专门的自动配置阶段,晚于所有手动配置,且支持顺序注解:
@AutoConfiguration @AutoConfigureBefore(RedisAutoConfiguration.class) // 在Redis自动配置前加载 @AutoConfigureAfter(DataSourceAutoConfiguration.class) // 在数据源自动配置后加载 public class MyAutoConfig {}
3. 使用场景天差地别
- 你写业务项目 → 永远用 @Configuration
- 你写通用组件、自定义 Starter、框架封装 → 必须用 @AutoConfiguration
四、常见误区
- 把 @AutoConfiguration 用在自己业务项目里 错误!业务配置用 @Configuration,@AutoConfiguration 是给自动配置专用的。
- 让 @AutoConfiguration 被 @ComponentScan 扫描到 错误!自动配置类必须放在扫描包外,否则会变成普通配置类,导致条件失效、重复加载。
- 认为 @AutoConfiguration 可以替代 @Configuration 错误!它是 @Configuration 的特定场景加强版,不是替代关系。
总结
- 业务项目配置 → 用 @Configuration,手动注册 Bean,靠扫描加载。
- 自定义 Starter / 框架自动配置 → 用 @AutoConfiguration,无需扫描,靠条件注解自动生效。
- @AutoConfiguration 是 SpringBoot 为自动配置量身定制的加强版 @Configuration。