SpringBoot 自动配置原理(二)

时间:2021-07-08 10:20:04   收藏:0   阅读:48

上一篇文章中解释了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

评论(0
© 2014 bubuko.com 版权所有 - 联系我们:wmxa8@hotmail.com
打开技术之扣,分享程序人生!