自动配置原理
2026/1/15大约 3 分钟SpringSpring BootJava微服务后端
自动配置原理
自动配置概述
Spring Boot 的自动配置是其核心特性之一,它能够根据类路径中的依赖、已定义的 Bean 和配置属性,自动配置 Spring 应用。
@EnableAutoConfiguration
@EnableAutoConfiguration 是自动配置的入口注解。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class) // 关键
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
Class<?>[] exclude() default {};
String[] excludeName() default {};
}AutoConfigurationImportSelector
这个类负责加载所有自动配置类:
public class AutoConfigurationImportSelector implements DeferredImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
// 1. 获取所有自动配置类
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
// 2. 去重
configurations = removeDuplicates(configurations);
// 3. 排除指定的配置类
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
configurations.removeAll(exclusions);
// 4. 过滤(条件判断)
configurations = getConfigurationClassFilter().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, getBeanClassLoader());
return configurations;
}
}spring.factories 文件
Spring Boot 2.x 使用 META-INF/spring.factories 文件定义自动配置类:
# spring-boot-autoconfigure.jar 中的 spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\
org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration,\
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration,\
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfigurationSpring Boot 3.x 变化
Spring Boot 3.x 使用 META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 文件替代 spring.factories。
条件注解
自动配置类使用条件注解来决定是否生效。
常用条件注解
| 注解 | 说明 |
|---|---|
@ConditionalOnClass | 类路径存在指定类时生效 |
@ConditionalOnMissingClass | 类路径不存在指定类时生效 |
@ConditionalOnBean | 容器中存在指定 Bean 时生效 |
@ConditionalOnMissingBean | 容器中不存在指定 Bean 时生效 |
@ConditionalOnProperty | 配置属性满足条件时生效 |
@ConditionalOnResource | 资源文件存在时生效 |
@ConditionalOnWebApplication | Web 应用时生效 |
@ConditionalOnNotWebApplication | 非 Web 应用时生效 |
示例:DataSourceAutoConfiguration
@AutoConfiguration(before = SqlInitializationAutoConfiguration.class)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class }) // 类路径有 DataSource
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
@Configuration(proxyBeanMethods = false)
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
@Configuration(proxyBeanMethods = false)
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.OracleUcp.class,
DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration {
}
}示例:RedisAutoConfiguration
@AutoConfiguration
@ConditionalOnClass(RedisOperations.class) // 类路径有 Redis 依赖
@EnableConfigurationProperties(RedisProperties.class)
@Import({ LettuceConnectionConfiguration.class, JedisConnectionConfiguration.class })
public class RedisAutoConfiguration {
@Bean
@ConditionalOnMissingBean(name = "redisTemplate") // 用户没有自定义
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<Object, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
return template;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(RedisConnectionFactory.class)
public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory factory) {
return new StringRedisTemplate(factory);
}
}自定义条件注解
// 自定义条件
public class OnLinuxCondition implements Condition {
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
String os = System.getProperty("os.name");
return os != null && os.toLowerCase().contains("linux");
}
}
// 使用自定义条件
@Configuration
@Conditional(OnLinuxCondition.class)
public class LinuxConfiguration {
@Bean
public LinuxService linuxService() {
return new LinuxService();
}
}配置属性绑定
@ConfigurationProperties
@ConfigurationProperties(prefix = "myapp")
public class MyAppProperties {
private String name;
private int timeout = 30;
private Server server = new Server();
// getters and setters
public static class Server {
private String host = "localhost";
private int port = 8080;
// getters and setters
}
}# application.yml
myapp:
name: MyApplication
timeout: 60
server:
host: 192.168.1.100
port: 9090@EnableConfigurationProperties
@Configuration
@EnableConfigurationProperties(MyAppProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyAppProperties properties) {
return new MyService(properties);
}
}自定义 Starter
1. 创建自动配置模块
// my-spring-boot-autoconfigure
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties.getMessage());
}
}2. 创建 spring.factories
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration3. 创建 Starter 模块
<!-- my-spring-boot-starter/pom.xml -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>my-core</artifactId>
</dependency>
</dependencies>调试自动配置
1. 启用调试日志
# application.yml
debug: true
# 或
logging:
level:
org.springframework.boot.autoconfigure: DEBUG2. 查看自动配置报告
启动时会打印:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
DataSourceAutoConfiguration matched:
- @ConditionalOnClass found required classes 'javax.sql.DataSource'
Negative matches:
-----------------
RedisAutoConfiguration:
Did not match:
- @ConditionalOnClass did not find required class 'org.springframework.data.redis.core.RedisOperations'3. 使用 Actuator
# 查看所有自动配置
curl http://localhost:8080/actuator/conditions小结
Spring Boot 自动配置的核心是 @EnableAutoConfiguration 注解,它通过 spring.factories 加载所有自动配置类,然后使用条件注解过滤,最终只有满足条件的配置类才会生效。
面试题预览
常见面试题
- Spring Boot 自动配置的原理是什么?
- @ConditionalOnClass 和 @ConditionalOnBean 有什么区别?
- 如何自定义一个 Spring Boot Starter?
