Spring Boot 的自动配置是其核心特性之一,通过 条件化配置 和 约定优于配置 的设计思想,自动加载和注册所需的配置类。以下从源码角度详细解析自动配置过程中注册配置类的关键步骤:
一、自动配置的核心流程
- 启动类标注
@SpringBootApplication
:- 该注解组合了
@EnableAutoConfiguration
,触发自动配置逻辑。
- 该注解组合了
- 加载
spring.factories
文件:- 从所有依赖的
META-INF/spring.factories
文件中读取自动配置类。
- 从所有依赖的
- 条件化筛选配置类:
- 根据条件注解(如
@ConditionalOnClass
)决定是否加载配置类。
- 根据条件注解(如
- 注册配置类到容器:
- 将筛选后的配置类注册为 Spring Bean。
二、源码解析
以下从源码角度详细分析自动配置过程中注册配置类的关键步骤。
1. 启动类与注解解析
- 入口:主类标注
@SpringBootApplication
。@SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }
@SpringBootApplication
注解:@Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootConfiguration @EnableAutoConfiguration // 触发自动配置 @ComponentScan public @interface SpringBootApplication {}
2. 自动配置触发
@EnableAutoConfiguration
注解:- 通过
@Import
导入AutoConfigurationImportSelector
。
@Import(AutoConfigurationImportSelector.class) public @interface EnableAutoConfiguration {}
- 通过
3. 加载自动配置类
AutoConfigurationImportSelector
:- 核心方法
selectImports()
负责加载自动配置类。
public String[] selectImports(AnnotationMetadata metadata) { // 获取自动配置类列表 AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(metadata); return autoConfigurationEntry.getConfigurations().toArray(new String[0]); }
- 核心方法
getAutoConfigurationEntry()
:- 调用
getCandidateConfigurations()
从spring.factories
加载所有自动配置类。 - 过滤排除项(如
exclude
指定的类)。
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata metadata) { List<String> configurations = getCandidateConfigurations(metadata, attributes); configurations = removeDuplicates(configurations); configurations = filter(configurations, autoConfigurationMetadata); return new AutoConfigurationEntry(configurations, exclusions); }
- 调用
getCandidateConfigurations()
:- 使用
SpringFactoriesLoader.loadFactoryNames()
加载spring.factories
中的自动配置类。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) { return SpringFactoriesLoader.loadFactoryNames(EnableAutoConfiguration.class, getBeanClassLoader()); }
- 使用
4. 条件化筛选配置类
OnClassCondition
:- 检查类路径是否存在指定类。
public final class OnClassCondition extends SpringBootCondition { @Override public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) { // 检查类路径是否存在指定类 ClassLoader classLoader = context.getClassLoader(); String[] classes = getClasses(metadata); for (String className : classes) { if (!ClassUtils.isPresent(className, classLoader)) { return ConditionOutcome.noMatch("Required class not found: " + className); } } return ConditionOutcome.match(); } }
ConditionEvaluator
:- 评估条件注解,决定是否加载配置类。
public boolean shouldSkip(AnnotatedTypeMetadata metadata, ConfigurationPhase phase) { for (Condition condition : conditions) { ConditionOutcome outcome = condition.getMatchOutcome(context, metadata); if (!outcome.isMatch()) { return true; // 跳过配置类 } } return false; // 加载配置类 }
5. 注册配置类到容器
ConfigurationClassPostProcessor
:- 解析配置类中的
@Bean
方法,并注册到容器。
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { // 解析配置类 ConfigurationClassParser parser = new ConfigurationClassParser(metadataReaderFactory, problemReporter, environment, resourceLoader, registry); parser.parse(candidates); parser.validate(); // 注册配置类 Set<BeanDefinitionHolder> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); this.reader.loadBeanDefinitions(configClasses); }
- 解析配置类中的
三、源码示例:WebMvcAutoConfiguration
1. 自动配置类
@Configuration
@ConditionalOnWebApplication(type = Type.SERVLET)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class})
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)
@EnableConfigurationProperties(WebMvcProperties.class)
public class WebMvcAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
// 配置 HandlerAdapter
}
}
2. 条件注解作用
@ConditionalOnWebApplication
:确保是 Servlet Web 应用。@ConditionalOnClass
:类路径存在DispatcherServlet
。@ConditionalOnMissingBean
:用户未自定义DispatcherServlet
时生效。
四、总结
Spring Boot 自动配置通过以下机制实现:
@EnableAutoConfiguration
触发自动配置流程。spring.factories
注册所有自动配置类。- 条件注解动态筛选有效配置。
ConfigurationClassPostProcessor
解析并注册配置类。
核心源码类:
AutoConfigurationImportSelector
:加载自动配置类。ConditionEvaluator
:评估条件注解。ConfigurationClassPostProcessor
:解析配置类。
理解自动配置源码后,开发者可以:
- 快速定位配置问题。
- 自定义 Starter 扩展功能。
- 优化应用启动速度和配置逻辑。