Spring Boot的自动装配机制通过约定优于配置的原则,极大地简化了Spring应用的开发,同时保持了高度的灵活性和可定制性。
入口注解@SpringBootApplication
@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
自动装配的核心是@SpringBootApplication注解中的@EnableAutoConfiguration
@EnableAutoConfiguration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration
通过@Import(AutoConfigurationImportSelector.class)
导入自动配置类选择器
AutoConfigurationImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
}
protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
configurations = removeDuplicates(configurations);
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = getConfigurationClassFilter().filter(configurations);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation,
getBeanClassLoader());
List<String> configurations = importCandidates.getCandidates();
Assert.notEmpty(configurations,
"No auto configuration classes found in " + "META-INF/spring/"
+ this.autoConfigurationAnnotation.getName() + ".imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
AutoConfigurationImportSelector
类实现了DeferredImportSelector
接口,其核心方法selectImports
负责加载所有符合条件的自动配置类。
加载逻辑:
- 从类路径下扫描
META-INF/spring.factories
(旧版)或META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
(新版)文件,读取org.springframework.boot.autoconfigure.EnableAutoConfiguration
键对应的配置类全限定名。 - 结合条件注解(如
@ConditionalOnClass
)过滤配置类,仅加载满足条件的配置。
自动装配流程
- 启动阶段:Spring Boot扫描
@SpringBootApplication
主类,触发@EnableAutoConfiguration
。 - 加载配置类:通过
AutoConfigurationImportSelector
读取spring.factories
文件,获取候选配置类。 - 条件过滤:根据
@Conditional
系列注解筛选有效配置类。 - Bean注册:符合条件的配置类中的
@Bean
方法被调用,Bean注册到容器。
Spring Boot通过spring.factories
文件实现SPI机制,允许第三方Starter模块声明自动配置类。这种机制实现了“对扩展开放,对修改封闭”的原则。
小技巧
可以通过设置debug=true来查看哪些自动配置类生效,哪些没有生效