Spring Boot 自动装配,是 Spring Boot 的核心特性之一。下面我来详细介绍一下Spring Boot 实现自动装配的原理。
一、什么是自动装配?
自动装配是 Spring Boot 基于约定大于配置的原则,根据项目的依赖和配置,自动配置 Spring 应用程序所需 Bean 的过程。
二、核心注解 @SpringBootApplication
java
@SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
@SpringBootApplication 是一个复合注解,包含三个核心注解:
1. @SpringBootConfiguration
java
@Configuration
public @interface SpringBootConfiguration {
// 继承 @Configuration,标识为配置类
}
2. @ComponentScan
java
@ComponentScan
// 自动扫描当前包及其子包的组件
3. @EnableAutoConfiguration (最关键)
java
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
// 启用自动配置
}
三、自动装配执行流程
核心类:AutoConfigurationImportSelector
java
public class AutoConfigurationImportSelector implements ... {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
// 1. 判断是否开启自动装配
if (!isEnabled(metadata)) {
return NO_IMPORTS;
}
// 2. 获取所有自动配置类
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(metadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata metadata) {
// 3. 获取所有候选配置类
List<String> configurations = getCandidateConfigurations(metadata, attributes);
// 4. 去重
configurations = removeDuplicates(configurations);
// 5. 根据 @Conditional 注解排除不需要的配置
Set<String> exclusions = getExclusions(metadata, attributes);
configurations.removeAll(exclusions);
// 6. 过滤(关键步骤)
configurations = getConfigurationClassFilter().filter(configurations);
// 7. 触发自动配置导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
}
四、配置加载机制
1. spring.factories 文件
Spring Boot 在 META-INF/spring.factories 中定义自动配置类:
java
properties
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration,\
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration,\
org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration,\
...
2. Spring Boot 2.7+ 的变化
Spring Boot 2.7 开始,推荐使用新的方式:
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
bash
properties
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
五、条件注解(Conditional)
自动装配的核心是 条件化配置:
| 注解 | 作用 |
|---|---|
@ConditionalOnClass |
类路径下存在指定类时生效 |
@ConditionalOnMissingClass |
类路径下不存在指定类时生效 |
@ConditionalOnBean |
容器中存在指定 Bean 时生效 |
@ConditionalOnMissingBean |
容器中不存在指定 Bean 时生效 |
@ConditionalOnProperty |
配置属性满足条件时生效 |
@ConditionalOnWebApplication |
是 Web 应用时生效 |
@ConditionalOnExpression |
SpEL 表达式为 true 时生效 |
示例:DataSourceAutoConfiguration
java
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory")
@EnableConfigurationProperties(DataSourceProperties.class)
@Import({ DataSourcePoolMetadataProvidersConfiguration.class,
DataSourceInitializationConfiguration.class })
public class DataSourceAutoConfiguration {
@Configuration
@Conditional(EmbeddedDatabaseCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import(EmbeddedDataSourceConfiguration.class)
protected static class EmbeddedDatabaseConfiguration {
}
@Configuration
@Conditional(PooledDataSourceCondition.class)
@ConditionalOnMissingBean({ DataSource.class, XADataSource.class })
@Import({ DataSourceConfiguration.Hikari.class,
DataSourceConfiguration.Tomcat.class,
DataSourceConfiguration.Dbcp2.class,
DataSourceConfiguration.Generic.class })
protected static class PooledDataSourceConfiguration {
}
}
六、自动装配执行顺序
java
启动类 → @SpringBootApplication → @EnableAutoConfiguration
↓
AutoConfigurationImportSelector.selectImports()
↓
加载 spring.factories / AutoConfiguration.imports
↓
过滤(按条件注解排除)
↓
按 @AutoConfigureOrder, @AutoConfigureAfter, @AutoConfigureBefore 排序
↓
注册配置类到容器
↓
配置类中的 @Bean 方法创建 Bean
七、自定义 Starter 实现自动装配
1. 创建自动配置类
java
@Configuration
@ConditionalOnClass(MyService.class)
@EnableConfigurationProperties(MyProperties.class)
@AutoConfigureAfter(DataSourceAutoConfiguration.class)
public class MyAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public MyService myService(MyProperties properties) {
return new MyService(properties);
}
}
2. 创建配置属性类
java
@ConfigurationProperties("my.service")
public class MyProperties {
private String prefix = "default";
private boolean enabled = true;
// getters/setters
}
3. 注册配置
在 META-INF/spring/ 目录创建文件:
java
properties
# META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
com.example.MyAutoConfiguration
4. spring.factories(兼容旧版本)
java
properties
# META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.MyAutoConfiguration
八、调试和排除
1. 查看生效的自动配置
java
yaml
# application.yml
debug: true
启动时会输出:
java
Positive matches: # 已启用的自动配置
Negative matches: # 未启用的自动配置
Exclusions: # 排除的配置
Unconditional classes: # 无条件配置
2. 排除特定自动配置
java
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
JacksonAutoConfiguration.class
})
或配置文件:
java
yaml
spring:
autoconfigure:
exclude:
- org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
九、核心原理总结
-
启动入口 :
@SpringBootApplication→@EnableAutoConfiguration -
配置加载 :通过
spring.factories或AutoConfiguration.imports加载配置类 -
条件过滤 :使用
@Conditional系列注解按条件启用/禁用配置 -
Bean 注册 :符合条件的配置类中的
@Bean方法向容器注册 Bean -
属性绑定 :通过
@ConfigurationProperties绑定外部配置
十、最佳实践
-
合理使用条件注解,确保配置只在需要的场景生效
-
明确配置顺序 ,使用
@AutoConfigureBefore/@AutoConfigureAfter -
提供合理的默认值,同时允许用户覆盖
-
在
spring-autoconfigure-metadata.properties中预定义条件,加快启动速度 -
模块化配置,将相关功能放在同一个自动配置类中
自动装配是 Spring Boot"约定大于配置"理念的具体实现,大大简化了 Spring 应用的配置工作。