一句话总结
Spring Boot 自动配置核心:@SpringBootApplication → @EnableAutoConfiguration → @Import(AutoConfigurationImportSelector) → 读取 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports → 加载所有自动配置类 → @Conditional 条件判断 → 按需装配 Bean。本质是 SPI 机制 + 条件注解 的组合,根据 classpath 中的 jar 依赖和配置,自动创建对应的 Bean,实现"约定大于配置"。
初级理解
@SpringBootApplication 拆解
# @SpringBootApplication 是一个组合注解
@SpringBootConfiguration # 本质是 @Configuration
@EnableAutoConfiguration # 开启自动配置(核心)
@ComponentScan( # 组件扫描
excludeFilters = {
@Filter(type = FilterType.CUSTOM,
classes = TypeExcludeFilter.class)
})
# 等价于同时标注了三个注解
# 1. @Configuration:标记为配置类
# 2. @EnableAutoConfiguration:开启自动配置
# 3. @ComponentScan:扫描当前包及子包的组件
自动配置做了什么?
# 没有 Spring Boot 时配置 DataSource
# 需要手动写大量配置
@Bean
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
ds.setUsername("root");
ds.setPassword("123456");
return ds;
}
# 有了 Spring Boot 自动配置
# 只需在 application.yml 中配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
# DataSource、JdbcTemplate、TransactionManager 全部自动创建
一句话总结:自动配置 = 根据依赖和配置,自动创建 Bean,省去手动配置。
中级深入
AutoConfigurationImportSelector 源码
# 核心流程
# 1. @EnableAutoConfiguration 导入 AutoConfigurationImportSelector
# 2. selectImports() 方法被调用
# 3. 读取 META-INF/spring/org.springframework.boot.autoconfigure
# .AutoConfiguration.imports 文件
# 4. 获取所有自动配置类全限定名
# 5. 通过 @Conditional 过滤
# 6. 将符合条件的配置类导入容器
# 关键源码(简化)
protected List<String> getCandidateConfigurations(...) {
# 使用 SpringFactoriesLoader 加载
return SpringFactoriesLoader.loadFactoryNames(
EnableAutoConfiguration.class,
getBeanClassLoader()
);
}
# Spring Boot 2.7 之前:META-INF/spring.factories
# Spring Boot 2.7 之后:META-INF/spring/
# org.springframework.boot.autoconfigure.AutoConfiguration.imports
@Conditional 条件注解体系
| 注解 | 条件 | 示例 |
| @ConditionalOnClass | classpath 存在指定类 | 有 HikariCP 才配 DataSource |
| @ConditionalOnMissingClass | classpath 不存在指定类 | 没有某个类时启用备选 |
| @ConditionalOnBean | 容器中存在指定 Bean | 有 DataSource 才配 JdbcTemplate |
| @ConditionalOnMissingBean | 容器中不存在指定 Bean | 用户没定义才用默认 |
| @ConditionalOnProperty | 配置项有指定值 | spring.cache.type=redis |
| @ConditionalOnWebApplication | 是 Web 应用 | Web 环境才配 DispatcherServlet |
中级要点:AutoConfigurationImportSelector 读取配置文件 → @Conditional 过滤 → 按需装配。
高级拓展
自动配置类示例:DataSourceAutoConfiguration
# DataSourceAutoConfiguration 源码分析
@AutoConfiguration # 标记为自动配置类
@ConditionalOnClass({DataSource.class, # classpath 有 DataSource
EmbeddedDatabaseType.class})
@EnableConfigurationProperties( # 绑定配置属性
DataSourceProperties.class)
@Import({DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceCheckpointRestoreConfiguration.class})
public class DataSourceAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(DataSource.class) # 用户没定义才创建
static class EmbeddedDatabaseConfiguration {
@Bean
DataSource dataSource(DataSourceProperties properties) {
# 创建内嵌数据库(H2/Derby)
}
}
@Configuration
@ConditionalOnClass(HikariDataSource.class) # classpath 有 HikariCP
@ConditionalOnMissingBean(DataSource.class)
static class HikariDataSourceConfiguration {
@Bean
DataSource dataSource(DataSourceProperties properties) {
# 创建 HikariCP 数据源
}
}
}
如何排除自动配置?
# 方式1:注解排除
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
RedisAutoConfiguration.class
})
# 方式2:配置文件排除
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc
.DataSourceAutoConfiguration
# 方式3:条件注解覆盖
# 自己定义同类型 Bean,@ConditionalOnMissingBean 会跳过自动配置
@Bean
public DataSource dataSource() {
# 自定义 DataSource
}
实战场景
场景:自定义 Starter
# 1. 创建自动配置类
@AutoConfiguration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties.getUrl());
}
}
# 2. 创建配置文件
# META-INF/spring/org.springframework.boot.autoconfigure
# .AutoConfiguration.imports
# 内容:
com.example.MyAutoConfiguration
# 3. 创建属性类
@ConfigurationProperties(prefix = "my")
public class MyProperties {
private String url = "http://localhost:8080";
# getter/setter
}
面试模拟
面试官:Spring Boot 自动配置原理是什么?
你:@SpringBootApplication 包含 @EnableAutoConfiguration,它通过 @Import 导入 AutoConfigurationImportSelector。该选择器读取 META-INF/spring/...AutoConfiguration.imports 文件获取所有自动配置类,然后通过 @Conditional 条件注解(如 @ConditionalOnClass、@ConditionalOnMissingBean)过滤,只装配符合条件的 Bean。本质是 SPI + 条件注解。
面试官:如何自定义一个 Starter?
你:三步:1)写自动配置类(@AutoConfiguration + @ConditionalOnClass + @Bean);2)在 META-INF/spring/...AutoConfiguration.imports 中注册;3)写属性类(@ConfigurationProperties)。引入 Starter 后自动配置生效。