不灭的焱

革命尚未成功,同志仍须努力 下载Java21

作者:AlbertWen  添加时间:2026-05-31 11:47:33  修改时间:2026-06-25 10:56:40  分类:07.Java框架/系统  编辑

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());
    }
}

这体现了自动配置的几个基本原则:

  1. 有相关类才配置:@ConditionalOnClass

  2. 用户开启了才配置:@ConditionalOnProperty

  3. 用户没自定义才配置:@ConditionalOnMissingBean

  4. 配置失败不要影响无关项目:尽量做到“引入但不用也没事”

官方文档也说,自动配置类通常使用 @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

四、常见误区

  1. 把 @AutoConfiguration 用在自己业务项目里 错误!业务配置用 @Configuration,@AutoConfiguration 是给自动配置专用的。
  2. 让 @AutoConfiguration 被 @ComponentScan 扫描到 错误!自动配置类必须放在扫描包外,否则会变成普通配置类,导致条件失效、重复加载。
  3. 认为 @AutoConfiguration 可以替代 @Configuration 错误!它是 @Configuration 的特定场景加强版,不是替代关系。

总结

  1. 业务项目配置 → 用 @Configuration,手动注册 Bean,靠扫描加载。
  2. 自定义 Starter / 框架自动配置 → 用 @AutoConfiguration,无需扫描,靠条件注解自动生效。
  3. @AutoConfiguration 是 SpringBoot 为自动配置量身定制的加强版 @Configuration。