总结
SpringBoot自定义导入本质都是配置类上添加的@Import的变种
常用方式
- resources/META-INF/spring.factories 在SpringBoot低版本支持,高版本不支持(比如说3.2.1)
- resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 所有版本都支持
spring.factories
使用spring.factories需要使用org.springframework.boot.autoconfigure.EnableAutoConfiguration作为key,value为需要自动注入到容器里的bean,如果有多个通过“,”分割 比如
org.springframework.boot.autoconfigure.EnableAutoConfiguration=com.alibaba.demo.domain.order.Order
org.springframework.boot.autoconfigure.AutoConfiguration.imports
使用org.springframework.boot.autoconfigure.AutoConfiguration.imports直接在文件内容里写明需要自动注入的bean即可,应该bean一行 比如:
com.alibaba.demo.domain.order.Order
源码解读
核心在于org.springframework.boot.autoconfigure.SpringBootApplication这个超级注解
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 {
}
在EnableAutoConfiguration标注了许多注解,其中最核心的注解就是@Import(AutoConfigurationImportSelector.class)。在执行ConfigurationClassParser的时候会解析@Import注解,
同时解析AutoConfigurationImportSelector执行对应的import方法来进行导入
AutoConfigurationImportSelector
public class AutoConfigurationImportSelector implements DeferredImportSelector, BeanClassLoaderAware,
ResourceLoaderAware, BeanFactoryAware, EnvironmentAware, Ordered {
}
可以看到AutoConfigurationImportSelector实现了DeferredImportSelector
public interface DeferredImportSelector extends ImportSelector {
}
查看DeferredImportSelector可以知道实现了ImportSelector这个最原始的spring提供自动注入bean的接口 回到AutoConfigurationImportSelector实现的selectImports方法
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
// 执行getAutoConfigurationEntry方法来实现装配需要自动注入的bean
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
在selectImports中核心时通过getAutoConfigurationEntry来实现自动装配的
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);
}
在getAutoConfigurationEntry中核心是通过getCandidateConfigurations来获取需要自动装配的bean的
getCandidateConfigurations
getCandidateConfigurations在不同的版本实现有点不一样。本质都是通过spi技术去获取需要自动装配的bean
较低版本
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = new ArrayList<>(
SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(), getBeanClassLoader())); // 解析spring.factories里需要装配的bean
ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()).forEach(configurations::add); // 解析org.springframework.boot.autoconfigure.AutoConfiguration.imports需要装配的bean
Assert.notEmpty(configurations,
"No auto configuration classes found in META-INF/spring.factories nor in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
在较低版本里会先去spring.factories获取,再去org.springframework.boot.autoconfigure.AutoConfiguration.imports获取
较高版本(以3.2.1为例)
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = ImportCandidates.load(AutoConfiguration.class, getBeanClassLoader()) // 解析org.springframework.boot.autoconfigure.AutoConfiguration.imports需要装配的bean
.getCandidates();
Assert.notEmpty(configurations,
"No auto configuration classes found in "
+ "META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
在较高版本里只会去org.springframework.boot.autoconfigure.AutoConfiguration.imports获取