什么是 Spring Boot 的自动配置原理?
Spring Boot 的自动配置原理是什么?
Spring Boot 的自动配置,简单说就是:根据你引入的依赖和已有的配置,自动帮你把该配的 Bean 都配好。你不用手写一堆 XML,也不用挨个注册 Bean,Spring Boot 帮你搞定。
这个能力背后靠的是三个核心机制:SPI 发现配置类 → 条件注解过滤 → 属性绑定定制。下面逐一拆解。
入口:@SpringBootApplication 做了什么?
启动类上的 @SpringBootApplication 是个复合注解,拆开来看:
java@SpringBootConfiguration // 标记当前类是配置类 @EnableAutoConfiguration // 开启自动配置(核心) @ComponentScan // 扫描当前包及子包下的组件 public @interface SpringBootApplication {}
其中 @EnableAutoConfiguration 是关键,它又引入了 AutoConfigurationImportSelector,这就是整个自动配置的调度中心。
自动配置的三步核心流程
第一步:发现候选配置类
Spring Boot 启动时,AutoConfigurationImportSelector 会去类路径下查找自动配置类的注册信息。这里有个重要的版本差异:
Spring Boot 2.7 之前,读取的是 META-INF/spring.factories:
propertiesorg.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
Spring Boot 2.7+ / 3.x,新增了 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件:
shellorg.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration
每行一个全限定类名,格式更简洁。Spring Boot 3.x 中 spring.factories 已被废弃,统一使用 imports 文件。这个变化面试中经常被追问,务必记住。
第二步:条件注解过滤
扫描到的配置类不是全部生效,Spring Boot 用 @Conditional 系列注解做条件判断:
| 条件注解 | 生效条件 | 典型场景 |
|---|---|---|
@ConditionalOnClass | 类路径存在指定类 | 引了 mysql 驱动才配 DataSource |
@ConditionalOnMissingBean | 容器中不存在该 Bean | 用户没自定义才给默认实现 |
@ConditionalOnProperty | 配置项满足指定值 | 开关控制是否启用 |
@ConditionalOnWebApplication | 是 Web 应用 | 只在 Web 环境配 MVC |
@ConditionalOnMissingClass | 类路径不存在指定类 | 互斥依赖场景 |
其中 @ConditionalOnMissingBean 最常被问——它保证了"用户自定义优先,框架兜底默认"的设计原则。你手动声明了一个 Bean,自动配置就不会再创建同类型的。
第三步:属性绑定定制默认值
自动配置类通过 @ConfigurationProperties 把 application.yml 中的属性绑定到 Java 对象:
java@Configuration @ConditionalOnClass(DataSource.class) @EnableConfigurationProperties(DataSourceProperties.class) public class DataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean public DataSource dataSource(DataSourceProperties properties) { return DataSourceBuilder.create() .url(properties.getUrl()) .username(properties.getUsername()) .password(properties.getPassword()) .build(); } }
DataSourceProperties 通过 @ConfigurationProperties(prefix = "spring.datasource") 绑定配置,这样你在 yml 里写的 spring.datasource.url 就能自动注入。框架提供合理的默认值,你想改就改,不想改直接用。
执行时机:自动配置在什么时候生效?
shellSpringApplication.run() └── refreshContext() └── invokeBeanFactoryPostProcessors() └── AutoConfigurationImportSelector.selectImports() ├── 读取 spring.factories / imports 文件 ├── 条件注解过滤 └── 返回满足条件的配置类全限定名数组
自动配置发生在 Spring 容器刷新的早期阶段,在普通 Bean 实例化之前,这样自动配置产生的 Bean 就能被后续流程正常使用。
如何自定义一个 Starter?
理解了原理,写一个自定义 Starter 就是照猫画虎:
1)配置类 + 条件注解
java@AutoConfiguration @ConditionalOnClass(MyService.class) @EnableConfigurationProperties(MyProperties.class) public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyProperties properties) { return new MyService(properties.getName(), properties.isEnabled()); } }
2)属性类
java@ConfigurationProperties(prefix = "my.service") public class MyProperties { private String name = "default"; private boolean enabled = true; // getter/setter }
3)注册配置类
Spring Boot 3.x 在 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 中添加:
shellcom.example.MyAutoConfiguration
Spring Boot 2.x 则在 META-INF/spring.factories 中注册。
如何排除不需要的自动配置?
注解方式:
java@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class Application {}
配置文件方式:
yamlspring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
还可以用 @ConditionalOnProperty 做开关,通过配置项控制是否启用某个自动配置,比硬编码 exclude 更灵活。
一句话总结
Spring Boot 自动配置的本质:SPI 机制发现候选类 → @Conditional 条件过滤 → @ConfigurationProperties 属性绑定,三条线串起来,实现了"约定优于配置"。你引了依赖它就帮你配,你想改就改,不改也有合理默认。
追问方向:spring.factories 和 imports 文件的区别是什么?@ConditionalOnMissingBean 如何保证用户自定义优先?自动配置的加载顺序怎么控制(@AutoConfigureBefore/After)?AutoConfigurationImportSelector 的过滤去重逻辑是怎样的?