SpringBoot 自动配置原理(二)
上一篇文章中解释了SpringBoot是如何确定basePackage的,这篇文章继续分析SpringBoot的自动装配是如何获得需要装配的类的。
DeferredImportSelector
DeferredImportSelector是ImportSelector的一个子接口,继承自ImportSelector接口,同样也有selectImports方法。但是当@Import注解导入一个实现了DeferredImportSelector接口的类时,@Import的行为就会发生变化。他不会去执行selectImports方法了,而是转而执行DeferredImportSelector接口中子接口Group的process方法,这个在源码的注释中有说明。
interface Group {
/**
* Process the {@link AnnotationMetadata} of the importing @{@link Configuration}
* class using the specified {@link DeferredImportSelector}.
*/
void process(AnnotationMetadata metadata, DeferredImportSelector selector);
AutoConfigurationImportSelector
这是注解@EnableAutoConfiguration上导入的一个类,这个类就实现了DeferredImportSelector接口,并且AutoConfigurationImportSelector的静态内部类AutoConfigurationGroup实现了DeferredImportSelector.Group接口,我们现在就来分析一下AutoConfigurationGroup的process方法都做了什么。
@Override
public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
() -> String.format("Only %s implementations are supported, got %s",
AutoConfigurationImportSelector.class.getSimpleName(),
deferredImportSelector.getClass().getName()));
//这里我们发现他将参数deferredImportSelector直接强转为AutoConfigurationImportSelector类型了,
//其实通过断点调试可以发现deferredImportSelector确实是AutoConfigurationImportSelector类型。
AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
.getAutoConfigurationEntry(annotationMetadata);
this.autoConfigurationEntries.add(autoConfigurationEntry);
for (String importClassName : autoConfigurationEntry.getConfigurations()) {
this.entries.putIfAbsent(importClassName, annotationMetadata);
}
}
我们可以看到这里最关键的方法就是getAutoConfigurationEntry,在这个方法中SpringBoot加载了自动配置项。我们再进入到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方法中我们可以发现,整体是围绕configurations和exclusions两个变量进行的,从名字不难看出这两个变量依次是SpringBoot要处理的自动配置类和排除在外的自动配置类。configurations是从getCandidateConfigurations方法中获得的,所以我们重点关注这个方法。
protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {
List<String> configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),
getBeanClassLoader());
Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring.factories. If you "
+ "are using a custom packaging, make sure that file is correct.");
return configurations;
}
在getCandidateConfigurations方法中,我们看到了老朋友META-INF/spring.factories
,和猜想的一样,需要自动配置的类都会写在spring.factories中。getSpringFactoriesLoaderFactoryClass()方法的返回值很简单,就是EnableAutoConfiguration.class。所以他会去加载META-INF/spring.factories
中名为org.springframework.boot.autoconfigure.EnableAutoConfiguration
的属性,然后获得一个自动配置类的全限定名列表。
总结
SpringBoot会读取META-INF/spring.factories
中名为org.springframework.boot.autoconfigure.EnableAutoConfiguration
的属性,作为进行自动配置的类的候选列表。
原文:https://www.cnblogs.com/supermaskv/p/14984268.html