Appearance
自动配置原理
自动配置是 Spring Boot 最核心的特性,也是最常被问到的面试题。它让 Spring Boot 能根据 classpath 中的依赖自动配置 Bean,开发者几乎零配置启动项目。
一、自动配置的入口
java
@SpringBootApplication
// ↓ 这个注解开启了自动配置
@EnableAutoConfiguration
// ↓ 导入了自动配置选择器
@Import(AutoConfigurationImportSelector.class)
public class Application { }自动配置的触发链路:
@SpringBootApplication
→ @EnableAutoConfiguration
→ @Import(AutoConfigurationImportSelector.class)
→ selectImports()
→ getAutoConfigurationEntry()
→ getCandidateConfigurations()
→ 读取 spring.factories / .imports 文件
→ 加载所有自动配置类
→ 条件注解过滤
→ 最终生效的配置二、自动配置类的加载
Spring Boot 2.x(spring.factories):
META-INF/spring.factories:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration,\
...
Spring Boot 3.x(.imports 文件,推荐):
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports:
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration
...三、条件注解
条件注解是自动配置的核心筛选机制,决定某个自动配置类是否生效。
| 条件注解 | 作用 | 示例 |
|---|---|---|
| @ConditionalOnClass | classpath 中存在指定类 | 有 DataSource 类 |
| @ConditionalOnMissingClass | classpath 中不存在指定类 | 没有 H2 类 |
| @ConditionalOnBean | 容器中存在指定 Bean | 有 DataSource Bean |
| @ConditionalOnMissingBean | 容器中不存在指定 Bean | 用户没自定义 DataSource |
| @ConditionalOnProperty | 配置文件中存在指定属性 | spring.datasource.url 有值 |
| @ConditionalOnResource | classpath 中存在指定资源 | 有 mybatis-config.xml |
| @ConditionalOnWebApplication | 是 Web 应用 | |
| @ConditionalOnExpression | SpEL 表达式为 true |
四、DataSource 自动配置实战解析
java
// 简化版 DataSourceAutoConfiguration 源码
@AutoConfiguration
@ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) // ① 有 DataSource 类
@EnableConfigurationProperties(DataSourceProperties.class) // ② 绑定配置属性
@Import({DataSourcePoolMetadataProvidersConfiguration.class, ...})
public class DataSourceAutoConfiguration {
@Configuration
@ConditionalOnMissingBean(DataSource.class) // ③ 用户没自定义 DataSource
static class EmbeddedDatabaseConfiguration {
// ④ 创建嵌入式数据库(H2)
}
@Configuration
@Conditional(PooledDataSourceCondition.class) // ③ 连接池条件
static class PooledDataSourceConfiguration {
// ④ 创建连接池 DataSource(HikariCP)
@Bean
@ConfigurationProperties(prefix = "spring.datasource.hikari")
DataSource dataSource(DataSourceProperties properties) {
HikariDataSource dataSource = properties.initializeDataSourceBuilder()
.type(HikariDataSource.class).build();
return dataSource;
}
}
}DataSource 自动配置决策流程:
① 检查 classpath 是否有 DataSource 类
├─ 没有 → 不配置
└─ 有 → 继续
② 检查容器中是否已有 DataSource Bean
├─ 有(用户自定义了) → 使用用户的
└─ 没有 → 继续
③ 检查 spring.datasource.url 是否有值
├─ 有 → 创建连接池 DataSource(HikariCP)
└─ 没有 → 创建嵌入式数据库(H2)五、自定义自动配置
java
// 第一步:创建配置属性类
@ConfigurationProperties(prefix = "my.ratelimit")
@Data
public class RateLimitProperties {
private boolean enabled = true;
private int maxRequests = 100;
private int windowSeconds = 60;
}
// 第二步:创建自动配置类
@AutoConfiguration
@ConditionalOnClass(RateLimiter.class)
@EnableConfigurationProperties(RateLimitProperties.class)
public class RateLimitAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnProperty(prefix = "my.ratelimit", name = "enabled",
havingValue = "true", matchIfMissing = true)
public RateLimiter rateLimiter(RateLimitProperties properties) {
return new RateLimiter(properties.getMaxRequests(), properties.getWindowSeconds());
}
}
// 第三步:注册自动配置类
// 在 resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
// 添加:com.mycompany.autoconfigure.RateLimitAutoConfiguration六、条件注解执行顺序
自动配置的执行顺序由 @AutoConfigureBefore / @AutoConfigureAfter 控制:
@AutoConfiguration
@AutoConfigureAfter(DataSourceAutoConfiguration.class) // 在 DataSource 配置后执行
@AutoConfigureBefore(JdbcTemplateAutoConfiguration.class) // 在 JdbcTemplate 配置前执行
public class MyAutoConfiguration { }七、面试要点
Q1:自动配置的原理是什么?
@EnableAutoConfiguration → @Import(AutoConfigurationImportSelector) → 从 .imports 文件加载所有自动配置类 → 通过条件注解(@ConditionalOnClass、@ConditionalOnMissingBean 等)筛选 → 符合条件的自动配置生效。
Q2:如何自定义一个 starter?
创建自动配置类 → 使用 @ConfigurationProperties 绑定配置 → 通过条件注解控制生效条件 → 在 .imports 文件中注册 → 打包发布。
Q3:Spring Boot 有哪些条件注解?
@ConditionalOnClass、@ConditionalOnMissingClass、@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnProperty、@ConditionalOnResource、@ConditionalOnWebApplication、@ConditionalOnExpression。
