5月28日 01:31

什么是 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

properties
org.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 文件:

shell
org.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,自动配置就不会再创建同类型的。

第三步:属性绑定定制默认值

自动配置类通过 @ConfigurationPropertiesapplication.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 就能自动注入。框架提供合理的默认值,你想改就改,不想改直接用。

执行时机:自动配置在什么时候生效?

shell
SpringApplication.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 中添加:

shell
com.example.MyAutoConfiguration

Spring Boot 2.x 则在 META-INF/spring.factories 中注册。

如何排除不需要的自动配置?

注解方式:

java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class}) public class Application {}

配置文件方式:

yaml
spring: autoconfigure: exclude: - org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration

还可以用 @ConditionalOnProperty 做开关,通过配置项控制是否启用某个自动配置,比硬编码 exclude 更灵活。

一句话总结

Spring Boot 自动配置的本质:SPI 机制发现候选类 → @Conditional 条件过滤 → @ConfigurationProperties 属性绑定,三条线串起来,实现了"约定优于配置"。你引了依赖它就帮你配,你想改就改,不改也有合理默认。


追问方向:spring.factories 和 imports 文件的区别是什么?@ConditionalOnMissingBean 如何保证用户自定义优先?自动配置的加载顺序怎么控制(@AutoConfigureBefore/After)?AutoConfigurationImportSelector 的过滤去重逻辑是怎样的?

标签:Spring Boot