自动配置

自动配置(Auto-configuration)是 Spring Boot 的核心特性:根据类路径上存在的依赖、用户定义的 Bean 及配置属性,自动推断并注册合适的 Bean,无需手动写 XML 或 @Configuration


触发入口

@SpringBootApplication
// ↑ 等价于以下三个注解的组合
@SpringBootConfiguration   // 标记为配置类
@EnableAutoConfiguration   // 开启自动配置(核心)
@ComponentScan             // 扫描当前包及子包的组件
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@EnableAutoConfiguration 触发 AutoConfigurationImportSelector,它负责从候选配置列表中筛选出当前环境适用的配置类并注册到容器。


加载机制

Spring Boot 3.x — .imports 文件

META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports

每行一个配置类全限定名,Spring Boot 启动时逐行读取:

org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration
...(共 100+ 条)

Spring Boot 2.x — spring.factories

# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
  org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration

Spring Boot 3.x 仍向后兼容 spring.factories,但新项目统一使用 .imports 文件。


自动配置类的结构

JacksonAutoConfiguration 为例,解析典型结构:

@AutoConfiguration                         // 标记为自动配置类(Spring Boot 3.x)
@ConditionalOnClass(ObjectMapper.class)    // Jackson 在类路径上才生效
@ConditionalOnMissingBean(ObjectMapper.class)  // 用户已定义则退出
public class JacksonAutoConfiguration {
 
    @Bean
    @ConditionalOnSingleCandidate(ObjectMapper.class)
    public Jackson2ObjectMapperBuilder jacksonObjectMapperBuilder(
            JacksonProperties jacksonProperties,
            ObjectProvider<Jackson2ObjectMapperBuilderCustomizer> customizers) {
        // 根据 spring.jackson.* 属性构建 ObjectMapper
        Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
        customizers.orderedStream().forEach(c -> c.customize(builder));
        return builder;
    }
}

核心设计模式:先提供合理默认值,再通过 @ConditionalOnMissingBean 允许用户完全覆盖


条件注解体系

自动配置类大量依赖条件注解决定是否生效:

注解生效条件
@ConditionalOnClass类路径上存在指定类
@ConditionalOnMissingClass类路径上不存在指定类
@ConditionalOnBean容器中存在指定 Bean
@ConditionalOnMissingBean容器中不存在指定 Bean(最常用于”默认可覆盖”)
@ConditionalOnProperty配置属性满足条件
@ConditionalOnExpressionSpEL 表达式为真
@ConditionalOnWebApplication是 Web 应用(Servlet / Reactive)
@ConditionalOnResource类路径 / 文件系统存在指定资源
@ConditionalOnJavaJVM 版本满足条件
@ConditionalOnSingleCandidate容器中只有一个候选 Bean

完整用法详见 条件注解


配置顺序控制

自动配置类之间可能存在依赖关系,通过以下注解控制顺序:

// 必须在 DataSourceAutoConfiguration 之后加载(保证 DataSource 已就绪)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
 
// 必须在 TransactionAutoConfiguration 之前加载
@AutoConfigureBefore(TransactionAutoConfiguration.class)
 
// 数字越小优先级越高(先加载)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)

@AutoConfigureAfter / @AutoConfigureBefore 只影响自动配置类之间的顺序,不影响用户 @Configuration 类(用户 Bean 始终优先)。


调试自动配置

方法一:--debug 启动参数

java -jar app.jar --debug
# 或
./mvnw spring-boot:run -Dspring-boot.run.arguments=--debug

输出 ConditionEvaluationReport,显示每个自动配置类的生效/跳过原因:

CONDITIONS EVALUATION REPORT
============================

Positive matches:     ← 生效的配置
-----------------
   JacksonAutoConfiguration matched:
      - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper'

Negative matches:     ← 未生效的配置(及原因)
-----------------
   ActiveMQAutoConfiguration:
      Did not match:
         - @ConditionalOnClass did not find required class 'javax.jms.ConnectionFactory'

Exclusions:           ← 被显式排除的配置
-----------
   org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

方法二:Actuator /actuator/conditions

management:
  endpoints:
    web:
      exposure:
        include: conditions
curl http://localhost:8080/actuator/conditions | jq .

返回 JSON,包含每个配置类的匹配结果,便于程序化分析。

方法三:@SpringBootTest 中检查

@SpringBootTest
class AutoConfigurationTest {
 
    @Autowired
    private ApplicationContext context;
 
    @Test
    void shouldHaveJacksonBean() {
        assertThat(context.containsBean("jacksonObjectMapper")).isTrue();
    }
 
    @Test
    void shouldNotHaveRedisBean() {
        assertThatThrownBy(() -> context.getBean(RedisConnectionFactory.class))
            .isInstanceOf(NoSuchBeanDefinitionException.class);
    }
}

排除不需要的自动配置

方式一:注解排除

@SpringBootApplication(exclude = {
    DataSourceAutoConfiguration.class,      // 不需要数据库
    SecurityAutoConfiguration.class         // 不需要 Spring Security
})
public class Application {}

方式二:配置文件排除

spring:
  autoconfigure:
    exclude:
      - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
      - org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

用户配置 vs 自动配置的优先级

用户 @Configuration(最高优先级)
    │
    ├── @Primary Bean(主候选)
    ├── @Bean 定义(覆盖自动配置)
    └── @Component 扫描
                │
自动配置(低优先级,通过 @ConditionalOnMissingBean 让步)
    │
    └── spring.factories / .imports 中声明的配置类

典型覆盖场景:

// 用户自定义 ObjectMapper,Jackson 自动配置检测到后不再注册默认的
@Configuration
public class JacksonConfig {
 
    @Bean
    @Primary
    public ObjectMapper customObjectMapper() {
        return Jackson2ObjectMapperBuilder.json()
            .propertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE)
            .build();
    }
}

自动配置与 Profile

自动配置类也可结合 @Profile 按环境生效:

@AutoConfiguration
@Profile("!test")   // 非 test 环境才加载
@ConditionalOnClass(DataSource.class)
public class ProductionDataSourceAutoConfiguration {
    // 生产数据源配置
}

环境与 Profile 详见 环境与Profile


自定义自动配置(编写 Starter)

编写自定义自动配置的完整流程:

// 1. 声明自动配置类
@AutoConfiguration
@ConditionalOnClass(MyService.class)
@ConditionalOnProperty(prefix = "my", name = "enabled",
                       havingValue = "true", matchIfMissing = true)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
 
    @Bean
    @ConditionalOnMissingBean
    public MyService myService(MyProperties props) {
        return new MyService(props);
    }
}
 
// 2. 注册到 .imports 文件
// META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// com.example.MyAutoConfiguration

自定义 Starter 的完整步骤详见 自定义Starter


常见自动配置类速查

自动配置类触发条件注册的核心 Bean
DataSourceAutoConfiguration类路径有 JDBC 驱动DataSource(HikariCP)
JpaRepositoriesAutoConfiguration类路径有 JPAEntityManagerFactoryJpaTransactionManager
WebMvcAutoConfigurationServlet + Spring MVCDispatcherServletHandlerMapping
SecurityAutoConfigurationSpring Security 在类路径AuthenticationManager、默认过滤链
RedisAutoConfigurationlettuce/jedis 在类路径RedisConnectionFactoryRedisTemplate
RabbitAutoConfigurationspring-amqp 在类路径ConnectionFactoryRabbitTemplate
KafkaAutoConfigurationspring-kafka 在类路径KafkaTemplateConsumerFactory
CacheAutoConfiguration@EnableCaching 存在CacheManager
TaskExecutionAutoConfigurationThreadPoolTaskExecutor(默认 @Async 执行器)
SchedulingAutoConfiguration@EnableScheduling 存在TaskScheduler

Spring Boot 4 变更(基于 Spring Framework 7)

Spring Boot 4 以 Spring Framework 7 + Java 21 为基线,自动配置机制在继承 3.x 架构的基础上有以下重要变化。

Java 21 最低要求

Spring Framework 7 / Spring Boot 4 将 Java 21 设为强制最低版本,低于 Java 21 无法编译运行。

这一变化带来的自动配置红利:

// 自动配置类可直接使用 Java 21 语法(Record、Pattern Matching、Sealed Classes)
@AutoConfiguration
@ConditionalOnClass(MyService.class)
public class MyAutoConfiguration {
 
    // 使用 Record 作为轻量配置载体
    public record ConnectionConfig(String host, int port, boolean ssl) {}
 
    @Bean
    @ConditionalOnMissingBean
    public MyService myService(MyProperties props) {
        var config = new ConnectionConfig(props.getHost(), props.getPort(), props.isSsl());
        return new MyService(config);
    }
}

虚拟线程相关自动配置参见 虚拟线程


spring.factories 彻底移除

Spring Boot 3.x 已废弃 spring.factories 中的 EnableAutoConfiguration 键,Spring Boot 4 完全移除该支持,只认 .imports 文件:

版本自动配置注册方式spring.factories
Spring Boot 2.xspring.factories完全支持
Spring Boot 3.x.imports 文件(推荐)兼容但已废弃
Spring Boot 4.x.imports 文件(唯一)不再支持

迁移检查:

# 扫描项目中是否还有旧的 spring.factories 自动配置声明
grep -r "EnableAutoConfiguration" src/main/resources/META-INF/spring.factories

若有依赖的第三方 Starter 仍使用 spring.factories,需等待对方升级或自行 fork 迁移。


@Fallback — Bean 回退声明(Spring Framework 7 新增)

@Fallback 是 Spring Framework 7 引入的新注解,用于将一个 @Bean 标记为回退实现:当容器中存在其他同类型的非回退 Bean 时,该 Bean 自动被忽略;只有在没有任何非回退 Bean 时才生效。

它是 @ConditionalOnMissingBean声明式等价物,语义更清晰:

// Spring Boot 3.x 写法(命令式条件)
@Bean
@ConditionalOnMissingBean(PasswordEncoder.class)
public PasswordEncoder defaultPasswordEncoder() {
    return new BCryptPasswordEncoder();
}
 
// Spring Boot 4.x 写法(声明式回退)
@Bean
@Fallback                      // 标记为回退 Bean
public PasswordEncoder defaultPasswordEncoder() {
    return new BCryptPasswordEncoder();
}

两者的关键区别:

对比@ConditionalOnMissingBean@Fallback
判断时机Bean 定义阶段(条件评估)Bean 选择阶段(依赖注入时)
AOT 支持需要额外 AOT hints原生支持,无需 hints
适用范围仅用于 @Bean 方法也可用于 @Component
多回退候选多个 @Fallback Bean 时保留所有(普通注入时报错需配合 @Primary

@Fallback 用于 @Component 类:

// 默认 HTTP 客户端实现,只在没有其他实现时才被装配
@Component
@Fallback
public class DefaultHttpClientAdapter implements HttpClientAdapter {
    // ...
}
 
// 用户提供的自定义实现,会使 DefaultHttpClientAdapter 自动退出
@Service
public class OkHttpClientAdapter implements HttpClientAdapter {
    // ...
}

在自动配置类中混合使用:

@AutoConfiguration
@ConditionalOnClass(HttpClientAdapter.class)
public class HttpClientAutoConfiguration {
 
    // 用户未自定义任何实现时,此 Bean 作为兜底
    @Bean
    @Fallback
    public HttpClientAdapter defaultAdapter(HttpClientProperties props) {
        return new DefaultHttpClientAdapter(props.getBaseUrl());
    }
}

AOT 处理增强(GraalVM Native Image)

Spring Boot 4 对 AOT(Ahead-of-Time)编译的支持更为成熟,自动配置类无需额外标注 @RegisterReflectionForBinding 等 hints,框架在编译期自动推断:

// Spring Boot 3.x:可能需要手动补充 AOT hints
@AutoConfiguration
@ImportRuntimeHints(MyAutoConfiguration.Hints.class)
public class MyAutoConfiguration {
 
    static class Hints implements RuntimeHintsRegistrar {
        @Override
        public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
            hints.reflection().registerType(MyService.class,
                MemberCategory.INVOKE_DECLARED_CONSTRUCTORS,
                MemberCategory.INVOKE_PUBLIC_METHODS);
        }
    }
}
 
// Spring Boot 4:框架自动推断,通常无需手动注册
@AutoConfiguration
public class MyAutoConfiguration {
    // AOT hints 由框架根据 @Bean 方法签名自动生成
}

条件注解在 AOT 模式下的行为:

// AOT 编译时,条件在编译期求值并固化
// @ConditionalOnClass 和 @ConditionalOnProperty 均可在 AOT 阶段处理
// @ConditionalOnBean / @ConditionalOnMissingBean 涉及运行时容器状态,
// AOT 处理时会保守地保留(不在编译期裁剪)
@AutoConfiguration
@ConditionalOnClass(DataSource.class)          // AOT:编译期可确定,直接裁剪
@ConditionalOnProperty("app.db.enabled")       // AOT:编译期可确定(属性固定时)
@ConditionalOnMissingBean(DataSource.class)    // AOT:保守保留,运行时判断
public class CustomDataSourceAutoConfiguration { ... }

GraalVM 原生编译详见 GraalVM原生编译


条件注解新增:@ConditionalOnThreading

Spring Boot 4 新增 @ConditionalOnThreading,专门用于根据线程模型(平台线程 / 虚拟线程)决定是否装配:

// 只在虚拟线程模式下注册的执行器
@Bean
@ConditionalOnThreading(Threading.VIRTUAL)
public Executor virtualThreadExecutor() {
    return Executors.newVirtualThreadPerTaskExecutor();
}
 
// 只在平台线程模式下注册的执行器
@Bean
@ConditionalOnThreading(Threading.PLATFORM)
public Executor platformThreadExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(8);
    executor.initialize();
    return executor;
}

配合配置:

spring:
  threads:
    virtual:
      enabled: true   # true → Threading.VIRTUAL;false → Threading.PLATFORM

版本对照速查

特性Spring Boot 2.xSpring Boot 3.xSpring Boot 4.x
最低 Java 版本Java 8Java 17Java 21
自动配置注册spring.factories.imports(推荐)/ spring.factories(兼容).imports 唯一
@AutoConfiguration无(用 @Configuration引入保持
@Fallback新增
@ConditionalOnThreading部分支持完整支持
AOT / Native实验性正式支持增强,hints 自动推断
Jakarta EE 命名空间javax.*jakarta.*jakarta.*

相关链接