当前文章分析的核心是:解析启动类@Import时获取得到的 AutoConfigurationImportSelector。
DeferredImportSelector:A variation of {@link ImportSelector} that runs after all {@code @Configuration} beans have been processed. This type of selector can be particularly useful when the selected imports are {@code @Conditional}。
解决 Spring Boot 中不能被默认路径扫描的配置类的方式,有 2 种:
(1)在 Spring Boot 主类上使用 @Import 注解。
(2)使用 spring.factories 文件。
private class DeferredImportSelectorHandler {
@Nullable
private List deferredImportSelectors = new ArrayList<>();
public void handle(ConfigurationClass configClass, DeferredImportSelector importSelector) {
DeferredImportSelectorHolder holder = new DeferredImportSelectorHolder(configClass, importSelector);
if (this.deferredImportSelectors == null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
handler.register(holder);
handler.processGroupImports();
}
else {
this.deferredImportSelectors.add(holder);
}
}
public void process() {
List deferredImports = this.deferredImportSelectors;
this.deferredImportSelectors = null;
try {
if (deferredImports != null) {
DeferredImportSelectorGroupingHandler handler = new DeferredImportSelectorGroupingHandler();
deferredImports.sort(DEFERRED_IMPORT_COMPARATOR);
deferredImports.forEach(handler::register);
handler.processGroupImports();
}
}
finally {
this.deferredImportSelectors = new ArrayList<>();
}
}
}
deferredImportSelectors集合中元素: 是解析启动类的@Import获取到ImportSelector类型的AutoConfigurationImportSelector时通过DeferredImportSelectorHandler#handle方法得到的。
private class DeferredImportSelectorGroupingHandler {
private final Map
grouping.getImports():获取自动装配的类。 entry:遍历每个自动装配的类
private static class DeferredImportSelectorGrouping {
private final DeferredImportSelector.Group group;
private final List deferredImports = new ArrayList<>();
DeferredImportSelectorGrouping(Group group) {
this.group = group;
}
public void add(DeferredImportSelectorHolder deferredImport) {
this.deferredImports.add(deferredImport);
}
public Iterable getImports() {
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
this.group.process(deferredImport.getConfigurationClass().getMetadata(),
deferredImport.getImportSelector());
}
return this.group.selectImports();
}
public Predicate getCandidateFilter() {
Predicate mergedFilter = DEFAULT_EXCLUSION_FILTER;
for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
Predicate selectorFilter = deferredImport.getImportSelector().getExclusionFilter();
if (selectorFilter != null) {
mergedFilter = mergedFilter.or(selectorFilter);
}
}
return mergedFilter;
}
}
group.process:调用AutoConfigurationImportSelector的静态内部类AutoConfigurationGroup的方法AutoConfigurationGroup#process获取Spring.factories中涉及的类信息。
this.group.selectImports():对候选的自动装配类进行排序。首先按照全限定性名,其次再根据@AutoConfigureOrder、最后@AutoConfigureBefore @AutoConfigureAfter依次控制集合中候选类的顺序。
public class AutoConfigurationImportSelector implements DeferredImportSelector{
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,AnnotationMetadata annotationMetadata) {
AnnotationAttributes attributes = getAttributes(annotationMetadata);
// 通过spi机制加载spring.factories文件下的目标类
List configurations = getCandidateConfigurations(annotationMetadata, attributes);//#1
configurations = removeDuplicates(configurations);
Set exclusions = getExclusions(annotationMetadata, attributes);
checkExcludedClasses(configurations, exclusions);
configurations.removeAll(exclusions);
configurations = filter(configurations, autoConfigurationMetadata);
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
private List filter(List configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
long startTime = System.nanoTime();
String[] candidates = StringUtils.toStringArray(configurations);
boolean[] skip = new boolean[candidates.length];
boolean skipped = false;
// AutoConfigurationImportFilter
for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {//#2
invokeAwareMethods(filter);
boolean[] match = filter.match(candidates, autoConfigurationMetadata);//#3
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
skip[i] = true;
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
List result = new ArrayList<>(candidates.length);
for (int i = 0; i < candidates.length; i++) {
if (!skip[i]) {
result.add(candidates[i]);
}
}
return new ArrayList<>(result);
}
private static class AutoConfigurationGroup implements DeferredImportSelector.Group{
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
@Override
public Iterable selectImports() {
if (this.autoConfigurationEntries.isEmpty()) {
return Collections.emptyList();
}
Set allExclusions = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
Set processedConfigurations = this.autoConfigurationEntries.stream()
.map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
.collect(Collectors.toCollection(LinkedHashSet::new));
processedConfigurations.removeAll(allExclusions);
return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
.map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
.collect(Collectors.toList());
}
}
}
步骤1:通过spi机制加载spring.factories文件下的目标类。
步骤2:在spring.factories文件中获取 AutoConfigurationImportFilter类型的过滤类。如下所示:
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
org.springframework.boot.autoconfigure.condition.OnBeanCondition,\
org.springframework.boot.autoconfigure.condition.OnClassCondition,\
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition
步骤3:遍历所有候选类。利用AutoConfigurationImportFilter三种不同类型判断候选类是否满足当前条件。
承接孪生文章