前言
自动配置是 Spring Boot 最核心的特性之一。它让我们无需繁琐的 XML 配置,只需引入 starter 依赖,Spring Boot 就能自动配置好相应的 Bean。本文将深入剖析自动配置的实现原理。
自动配置是什么
传统 Spring 的配置
在传统 Spring 应用中,我们需要手动配置大量 Bean:
@Configuration
public class DataSourceConfig {
@Bean
public DataSource dataSource() {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/demo");
config.setUsername("root");
config.setPassword("123456");
config.setDriverClassName("com.mysql.cj.jdbc.Driver");
return new HikariDataSource(config);
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
Spring Boot 的自动配置
在 Spring Boot 中,只需引入依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
然后在配置文件中简单配置:
spring:
datasource:
url: jdbc:mysql://localhost:3306/demo
username: root
password: 123456
Spring Boot 会自动创建 DataSource、JdbcTemplate 等 Bean。
核心注解
@SpringBootApplication
@SpringBootApplication 是 Spring Boot 的核心注解,它是一个组合注解:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = {
@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class)
})
public @interface SpringBootApplication {
// ...
}
关键注解:
- @SpringBootConfiguration - 标识为配置类
- @EnableAutoConfiguration - 启用自动配置
- @ComponentScan - 组件扫描
@EnableAutoConfiguration
@EnableAutoConfiguration 是自动配置的核心:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// ...
}
关键是通过 @Import(AutoConfigurationImportSelector.class) 导入自动配置类。
自动配置流程
1. AutoConfigurationImportSelector
AutoConfigurationImportSelector 负责加载所有自动配置类:
public class AutoConfigurationImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 获取所有自动配置类
List<String> configurations = getCandidateConfigurations(
annotationMetadata.getAnnotationAttributes(EnableAutoConfiguration.class.getName())
);
// 去重
configurations = removeDuplicates(configurations);
// 排除不需要的配置
configurations = getExclusionFilter().filter(configurations);
// 返回配置类列表
return configurations.toArray(new String[0]);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
// 加载 META-INF/spring.factories 中的配置
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(
EnableAutoConfiguration.class, getClassLoader()
);
return configurations;
}
}
2. SPI 机制
Spring Boot 使用 SPI(Service Provider Interface)机制加载自动配置类:
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\
...
Spring Boot 4 中,spring.factories 迁移到新的位置:
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration
3. 条件注解
自动配置类使用条件注解控制是否生效:
@Configuration
@ConditionalOnClass({DataSource.class, JdbcTemplate.class})
@ConditionalOnMissingBean(JdbcTemplate.class)
@EnableConfigurationProperties(JdbcProperties.class)
public class JdbcTemplateAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public JdbcTemplate jdbcTemplate(DataSource dataSource, JdbcProperties properties) {
return new JdbcTemplate(dataSource);
}
}
常用条件注解:
| 注解 | 说明 |
|---|---|
@ConditionalOnClass | 类路径存在指定类时生效 |
@ConditionalOnMissingClass | 类路径不存在指定类时生效 |
@ConditionalOnBean | 容器中存在指定 Bean 时生效 |
@ConditionalOnMissingBean | 容器中不存在指定 Bean 时生效 |
@ConditionalOnProperty | 配置属性满足条件时生效 |
@ConditionalOnWebApplication | Web 应用时生效 |
@ConditionalOnExpression | SpEL 表达式为 true 时生效 |
自定义自动配置
1. 创建配置类
@Configuration
@ConditionalOnClass(MyService.class)
@ConditionalOnMissingBean(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
public MyService myService(MyProperties properties) {
return new MyService(properties.getPrefix());
}
}
2. 创建配置属性类
@ConfigurationProperties(prefix = "my")
public class MyProperties {
private String prefix = "default";
// getters and setters
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
}
3. 注册自动配置
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.demo.autoconfigure.MyAutoConfiguration
4. 测试自动配置
@SpringBootTest
public class MyAutoConfigurationTest {
@Autowired
private MyService myService;
@Test
public void testMyService() {
assertNotNull(myService);
}
}
调试自动配置
1. 启用调试日志
logging:
level:
org.springframework.boot.autoconfigure: DEBUG
2. 使用 ConditionEvaluationReport
启动时添加参数:
--debug
查看自动配置报告:
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(DemoApplication.class);
app.addListeners(event -> {
if (event instanceof ApplicationReadyEvent) {
ConditionEvaluationReport report =
((ConfigurableApplicationContext) event.getApplicationContext())
.getBean(ConditionEvaluationReport.class);
// 打印自动配置报告
}
});
app.run(args);
}
}
3. 排除自动配置
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
RedisAutoConfiguration.class
})
或者:
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
- org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
自动配置顺序
Spring Boot 4 支持通过 @AutoConfigureOrder 控制自动配置顺序:
@Configuration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
public class FirstAutoConfiguration {
// ...
}
@Configuration
@AutoConfigureOrder(Ordered.LOWEST_PRECEDENCE)
public class LastAutoConfiguration {
// ...
}
也可以使用 @AutoConfigureBefore 和 @AutoConfigureAfter:
@Configuration
@AutoConfigureBefore(DataSourceAutoConfiguration.class)
public class CustomDataSourceAutoConfiguration {
// ...
}
总结
自动配置是 Spring Boot 的核心特性:
- ✅ @EnableAutoConfiguration - 启用自动配置
- ✅ SPI 机制 - 加载自动配置类
- ✅ 条件注解 - 控制配置生效
- ✅ 自定义自动配置 - 扩展 Spring Boot
- ✅ 调试技巧 - 查看自动配置报告
理解自动配置原理,能帮助你更好地使用 Spring Boot,并在需要时进行扩展和定制。