问题
SpringBoot是如何实现自动配置的?
答案
1. 核心概念
SpringBoot的自动配置(Auto-Configuration)是其核心特性之一,通过约定优于配置的理念,在应用启动时自动加载和配置所需的Bean,无需手动编写大量配置代码。
2. 自动配置原理详解
(1) 核心注解:@SpringBootApplication
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
@SpringBootApplication 是一个组合注解,包含三个核心注解:
@SpringBootConfiguration // 标识为配置类(等同于@Configuration)
@EnableAutoConfiguration // 启用自动配置
@ComponentScan // 自动扫描组件
public @interface SpringBootApplication {
}
(2) @EnableAutoConfiguration工作机制
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}
关键点:
@Import导入AutoConfigurationImportSelector,这是自动配置的核心类AutoConfigurationImportSelector会加载所有候选的自动配置类
(3) 自动配置类加载流程
SpringBoot 2.x 流程:
// AutoConfigurationImportSelector.selectImports()方法
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata,
AnnotationAttributes attributes) {
// 加载 META-INF/spring.factories 文件
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
EnableAutoConfiguration.class,
getBeanClassLoader()
);
return configurations;
}
SpringBoot 3.x 流程(改进):
- 从
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件加载 - 采用更简洁的文本格式,每行一个配置类全限定名
(4) 条件注解控制加载
自动配置类通过条件注解决定是否生效:
@Configuration
@ConditionalOnClass(DataSource.class) // classpath存在DataSource类才生效
@ConditionalOnMissingBean(DataSource.class) // 不存在用户自定义DataSource才生效
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {
@Bean
@ConditionalOnProperty(name = "spring.datasource.type", havingValue = "hikari")
public DataSource hikariDataSource(DataSourceProperties properties) {
return DataSourceBuilder.create()
.type(HikariDataSource.class)
.build();
}
}
常用条件注解:
@ConditionalOnClass/@ConditionalOnMissingClass:判断类是否存在@ConditionalOnBean/@ConditionalOnMissingBean:判断Bean是否存在@ConditionalOnProperty:判断配置属性值@ConditionalOnResource:判断资源文件是否存在@ConditionalOnWebApplication:判断是否为Web应用
(5) 配置属性绑定
@ConfigurationProperties(prefix = "spring.datasource")
public class DataSourceProperties {
private String url;
private String username;
private String password;
// getters and setters
}
通过 @EnableConfigurationProperties 将配置文件中的属性绑定到Java对象。
3. 完整执行流程
1. SpringApplication.run() 启动
↓
2. 刷新ApplicationContext
↓
3. 解析@SpringBootApplication注解
↓
4. 触发@EnableAutoConfiguration
↓
5. AutoConfigurationImportSelector.selectImports()
↓
6. 加载spring.factories/AutoConfiguration.imports
↓
7. 获取所有候选配置类(130+个)
↓
8. 去重、排序、过滤
↓
9. 条件注解评估(@ConditionalOnXxx)
↓
10. 注册符合条件的Bean到容器
↓
11. 绑定配置属性
↓
12. 完成自动配置
4. 实战示例:查看生效的自动配置
方法1:启用Debug日志
# application.properties
debug=true
输出:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:(生效的配置)
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required class 'javax.sql.DataSource'
Negative matches:(未生效的配置)
-----------------
RedisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations'
方法2:使用Actuator
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
访问:http://localhost:8080/actuator/conditions
5. 性能优化考量
- 延迟加载:通过
@ConditionalOnClass避免不必要的类加载 - 缓存机制:条件注解的评估结果会被缓存
- 排序优化:通过
@AutoConfigureAfter、@AutoConfigureBefore控制加载顺序 - 排除配置:显式排除不需要的自动配置减少启动时间
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
6. 面试答题要点总结
- 核心机制:通过
@EnableAutoConfiguration+AutoConfigurationImportSelector加载配置类 - 加载源:从
spring.factories(2.x)或AutoConfiguration.imports(3.x)读取候选配置 - 条件控制:利用
@ConditionalOnXxx条件注解决定是否生效 - 属性绑定:通过
@ConfigurationProperties绑定外部配置 - 设计优势:约定优于配置、按需加载、用户配置优先
一句话总结:SpringBoot通过 @EnableAutoConfiguration 触发 AutoConfigurationImportSelector 加载所有候选配置类,再通过条件注解筛选出符合当前环境的配置,最终自动注册Bean到Spring容器。