Spring Boot自动配置的原理在于@SpringBootApplication注解下的@EnableAutoConfiguration,因此我们从这个配置类开始分析,主要分析过程都写在代码中了。

@EnableAutoConfiguration

  • 这个注解是Spring Boot自动配置的关键,其中Import了另一个DefferedImportSelector的实现类AutoConfigurationImportSelector
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
    // 。。。。。。。
}
  • 简单介绍以下DefferedImportSelector的原理
  • Spring的后置处理器在解析配置类时会解析到配置类上的@Import注解,当Import的注解为DefferedImportSelector的实现类时,会将其添加到ConfigurationClassParser的一个属性deferredImportSelectorHandler,而这个属性中又有一个列表保存了DeferredImportSelectorHolder的实例,这个实例是在解析的时候根据配置类以及他引入的DefferedImportSelector构建的
  • 在某一配置类引入的类全部被递归解析完成后,才会执行到this.deferredImportSelectorHandler.process()方法,执行之前添加的DefferedImportSelector
public void parse(Set<BeanDefinitionHolder> configCandidates) {
    for (BeanDefinitionHolder holder : configCandidates) {
        BeanDefinition bd = holder.getBeanDefinition();
        try {
            if (bd instanceof AnnotatedBeanDefinition) {
                parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
            }
            else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
            }
            else {
                parse(bd.getBeanClassName(), holder.getBeanName());
            }
        }
        catch (BeanDefinitionStoreException ex) {
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanDefinitionStoreException(
                "Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
        }
    }
	// 执行之前添加的DefferedImportSelector
    this.deferredImportSelectorHandler.process();
}
  • process方法中会创建一个DeferredImportSelectorGroupingHandler,然后根据是否返回了非空的DeferredImportSelector.Group类,如果返回的是null或者没有重写getImportGroup方法,则使用默认的DefaultDeferredImportSelectorGroup,然后把所有相同Group的DeferredImportSelector添加到一起。最后调用DeferredImportSelectorGroupingHandler的processGroupImports方法。
public void process() {
    List<DeferredImportSelectorHolder> 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<>();
    }
}
// DeferredImportSelectorGroupingHandler类的方法
public void register(DeferredImportSelectorHolder deferredImport) {
    Class<? extends Group> group = deferredImport.getImportSelector()
        .getImportGroup();
    DeferredImportSelectorGrouping grouping = this.groupings.computeIfAbsent(
        (group != null ? group : deferredImport),
        key -> new DeferredImportSelectorGrouping(createGroup(group)));
    grouping.add(deferredImport);
    this.configurationClasses.put(deferredImport.getConfigurationClass().getMetadata(),
                                  deferredImport.getConfigurationClass());
}
  • processGroupImports会遍历之前封装好的DeferredImportSelectorGrouping,然后调用它的getImports方法
public void processGroupImports() {
    for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
        grouping.getImports().forEach(entry -> {
            ConfigurationClass configurationClass = this.configurationClasses.get(
                entry.getMetadata());
            try {
                processImports(configurationClass, asSourceClass(configurationClass),
                               asSourceClasses(entry.getImportClassName()), false);
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configurationClass.getMetadata().getClassName() + "]", ex);
            }
        });
    }
}
  • getImports方法中会对相同Group的DeferredImportSelector执行process和selectImports方法,这里就会因为前面的AutoConfigurationImportSelector中实现的getImportGroup方法而跳转到Spring Boot自动配置的关键方法中,即AutoConfigurationGroup的process和selectImports方法;这里再讲一下,如果DeferredImportSelector的getImportGroup方法返回null,那么就会执行到DefaultDeferredImportSelectorGroup的process和selectImports方法,这里就会直接调用DeferredImportSelector的selectImports方法
public Iterable<Group.Entry> getImports() {
    for (DeferredImportSelectorHolder deferredImport : this.deferredImports) {
        this.group.process(deferredImport.getConfigurationClass().getMetadata(),
                           deferredImport.getImportSelector());
    }
    return this.group.selectImports();
}

查找自动配置类

下面我们进入本文的重点,自动配置。

  • 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()));
    // 调用了AutoConfigurationImportSelector的getAutoConfigurationEntry方法
    AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
        .getAutoConfigurationEntry(getAutoConfigurationMetadata(), annotationMetadata);
    this.autoConfigurationEntries.add(autoConfigurationEntry);
    for (String importClassName : autoConfigurationEntry.getConfigurations()) {
        this.entries.putIfAbsent(importClassName, annotationMetadata);
    }
}
  • getAutoConfigurationEntry
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
			AnnotationMetadata annotationMetadata) {
    // 判断配置文件的自动配置功能是否打开,即环境中是否设置了spring.boot.enableautoconfiguration,默认返回true,取反为false
    if (!isEnabled(annotationMetadata)) {
        return EMPTY_ENTRY;
    }
    // 获取到@EnableAutoConfiguration注解的属性
    AnnotationAttributes attributes = getAttributes(annotationMetadata);
    // 获取到META/spring.factories文件中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的全限定类名
    List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    // 剔除重复的
    configurations = removeDuplicates(configurations);
    // 查找到@EnableAutoConfiguration中exclude,excludeName中的全限定类名,或者配置文件中spring.autoconfigure.exclude添加的全限定类名
    // 以便剔除不需要自动配置的类
    Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    // 检查上一步剔除的类,如果该排除的类可以被加载并且之前从spring.factories中没有指定过该类名,那么就是一个无效的排除,然后打印一下
    checkExcludedClasses(configurations, exclusions);
    // 删除有效的剔除类名
    configurations.removeAll(exclusions);
    configurations = filter(configurations, autoConfigurationMetadata);
    fireAutoConfigurationImportEvents(configurations, exclusions);
    return new AutoConfigurationEntry(configurations, exclusions);
}
  • filter方法获取掉不需要的类,SpringBoot默认实现有以下3个,后面我们依次来看

org.springframework.boot.autoconfigure.condition.OnBeanCondition
org.springframework.boot.autoconfigure.condition.OnClassCondition
org.springframework.boot.autoconfigure.condition.OnWebApplicationCondition

private List<String> filter(List<String> configurations, AutoConfigurationMetadata autoConfigurationMetadata) {
    long startTime = System.nanoTime();
    String[] candidates = StringUtils.toStringArray(configurations);
    boolean[] skip = new boolean[candidates.length];
    boolean skipped = false;
    for (AutoConfigurationImportFilter filter : getAutoConfigurationImportFilters()) {
        invokeAwareMethods(filter);
        // 使用各个Filter对候选的自动配置类进行筛选
        boolean[] match = filter.match(candidates, autoConfigurationMetadata);
        for (int i = 0; i < match.length; i++) {
            // 如果不符合过滤器的条件,那么就标识该配置类为需要跳过,将候选的置为null,标志是否有任意一个需要跳过
            if (!match[i]) {
                skip[i] = true;
                candidates[i] = null;
                skipped = true;
            }
        }
    }
    // 如果全部都没有要跳过,直接返回所有的
    if (!skipped) {
        return configurations;
    }
    // 根据前面filter判断的结果,决定是否添加到结果中返回
    List<String> result = new ArrayList<>(candidates.length);
    for (int i = 0; i < candidates.length; i++) {
        if (!skip[i]) {
            result.add(candidates[i]);
        }
    }
    if (logger.isTraceEnabled()) {
        int numberFiltered = configurations.size() - result.size();
        logger.trace("Filtered " + numberFiltered + " auto configuration class in "
                     + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startTime) + " ms");
    }
    return new ArrayList<>(result);
}

上面提供到3个过滤器都是继承自FilteringSpringBootCondition,而match方法由FilteringSpringBootCondition,getOutcomes由实现类重写

public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
    ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
    ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
    boolean[] match = new boolean[outcomes.length];
    for (int i = 0; i < outcomes.length; i++) {
        match[i] = (outcomes[i] == null || outcomes[i].isMatch());
        if (!match[i] && outcomes[i] != null) {
            logOutcome(autoConfigurationClasses[i], outcomes[i]);
            if (report != null) {
                report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
            }
        }
    }
    return match;
}

OnClassCondition类分析

protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
			AutoConfigurationMetadata autoConfigurationMetadata) {
    // Split the work and perform half in a background thread. Using a single
    // additional thread seems to offer the best performance. More threads make
    // things worse
    // 二分法处理
    int split = autoConfigurationClasses.length / 2;
    // 创建一个线程用于处理前一半的数据,创建了一个ThreadedOutcomesResolver,构造器中传入StandardOutcomesResolver,
    // 然后在构造器中启动一个线程执行构造器中传入StandardOutcomesResolver.resolveOutcomes方法,并将返回值赋值给ThreadedOutcomesResolver的
    // outcomes属性
    OutcomesResolver firstHalfResolver = createOutcomesResolver(autoConfigurationClasses, 0, split,
                                                                autoConfigurationMetadata);
    OutcomesResolver secondHalfResolver = new StandardOutcomesResolver(autoConfigurationClasses, split,
                                                                       autoConfigurationClasses.length, autoConfigurationMetadata, getBeanClassLoader());
    // 步骤
    // 1. 获取META-INF/spring-autoconfigure-metadata.properties文件中的配置,key为:自动配置类名 + "." + "ConditionalOnClass"
    // 2. 如果上述属性获取到了,判断该属性值对应的类是否可以加载到,如果加载得到返回null,加载得到,返回一个属性为false的ConditionOutcome
    ConditionOutcome[] secondHalf = secondHalfResolver.resolveOutcomes();
    // 调用ThreadedOutcomesResolver的resolveOutcomes方法,调用当前方法中之前创建的thread.join方法,等待线程把StandardOutcomesResolver.resolveOutcomes
    // 执行完成,然后把赋值好的outcomes返回
    ConditionOutcome[] firstHalf = firstHalfResolver.resolveOutcomes();
    // 组合返回
    ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
    System.arraycopy(firstHalf, 0, outcomes, 0, firstHalf.length);
    System.arraycopy(secondHalf, 0, outcomes, split, secondHalf.length);
    return outcomes;
}

回到上面的代码中

public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {
    ConditionEvaluationReport report = ConditionEvaluationReport.find(this.beanFactory);
    ConditionOutcome[] outcomes = getOutcomes(autoConfigurationClasses, autoConfigurationMetadata);
    boolean[] match = new boolean[outcomes.length];
    for (int i = 0; i < outcomes.length; i++) {
        // outcome为null或者outcome的match为true,那么就说明需要自动配置
        match[i] = (outcomes[i] == null || outcomes[i].isMatch());
        if (!match[i] && outcomes[i] != null) {
            // 打印不能使用自动配置的类
            logOutcome(autoConfigurationClasses[i], outcomes[i]);
            if (report != null) {
                report.recordConditionEvaluation(autoConfigurationClasses[i], this, outcomes[i]);
            }
        }
    }
    return match;
}

OnWebApplicationCondition,直接看getOutcomes方法,同样获取META-INF/spring-autoconfigure-metadata.properties文件中的配置,key为:自动配置类名 + “.” + “ConditionalOnWebApplication”,根据该值决定是否自动注入

protected ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
			AutoConfigurationMetadata autoConfigurationMetadata) {
    ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
    for (int i = 0; i < outcomes.length; i++) {
        String autoConfigurationClass = autoConfigurationClasses[i];
        if (autoConfigurationClass != null) {
            outcomes[i] = getOutcome(
                autoConfigurationMetadata.get(autoConfigurationClass, "ConditionalOnWebApplication"));
        }
    }
    return outcomes;
}

有哪些值?
1. 未配置;
2. SERVLET:项目引入_org.springframework.web.context.support.GenericWebApplicationContext,返回null
3. REACTIVE:项目引入_org.springframework.web.reactive.HandlerResult,返回null
4. 其他:引入了上述两种之一即返回null

private ConditionOutcome getOutcome(String type) {
    if (type == null) {
        return null;
    }
    ConditionMessage.Builder message = ConditionMessage.forCondition(ConditionalOnWebApplication.class);
    if (ConditionalOnWebApplication.Type.SERVLET.name().equals(type)) {
        if (!ClassNameFilter.isPresent(SERVLET_WEB_APPLICATION_CLASS, getBeanClassLoader())) {
            return ConditionOutcome.noMatch(message.didNotFind("servlet web application classes").atAll());
        }
    }
    if (ConditionalOnWebApplication.Type.REACTIVE.name().equals(type)) {
        if (!ClassNameFilter.isPresent(REACTIVE_WEB_APPLICATION_CLASS, getBeanClassLoader())) {
            return ConditionOutcome.noMatch(message.didNotFind("reactive web application classes").atAll());
        }
    }
    if (!ClassNameFilter.isPresent(SERVLET_WEB_APPLICATION_CLASS, getBeanClassLoader())
        && !ClassUtils.isPresent(REACTIVE_WEB_APPLICATION_CLASS, getBeanClassLoader())) {
        return ConditionOutcome.noMatch(message.didNotFind("reactive or servlet web application classes").atAll());
    }
    return null;
}

OnBeanCondition,和前两种一样,获取META-INF/spring-autoconfigure-metadata.properties文件中的配置,key为:自动配置类名 + “.” + “ConditionalOnBean”,如果前一个没有过滤掉,在判断ConditionalOnSingleCandidate的类型

protected final ConditionOutcome[] getOutcomes(String[] autoConfigurationClasses,
			AutoConfigurationMetadata autoConfigurationMetadata) {
    ConditionOutcome[] outcomes = new ConditionOutcome[autoConfigurationClasses.length];
    for (int i = 0; i < outcomes.length; i++) {
        String autoConfigurationClass = autoConfigurationClasses[i];
        if (autoConfigurationClass != null) {
            Set<String> onBeanTypes = autoConfigurationMetadata.getSet(autoConfigurationClass, "ConditionalOnBean");
            outcomes[i] = getOutcome(onBeanTypes, ConditionalOnBean.class);
            if (outcomes[i] == null) {
                Set<String> onSingleCandidateTypes = autoConfigurationMetadata.getSet(autoConfigurationClass,
                                                                                      "ConditionalOnSingleCandidate");
                outcomes[i] = getOutcome(onSingleCandidateTypes, ConditionalOnSingleCandidate.class);
            }
        }
    }
    return outcomes;
}

过滤掉条件不满足的类

/**
requiredBeanTypes: 必须要有的bean的类型全限定名
该方法用于判断任意一个需要加载的类不存在,即返回false的ConditionOutcome
*/
private ConditionOutcome getOutcome(Set<String> requiredBeanTypes, Class<? extends Annotation> annotation) {
    List<String> missing = filter(requiredBeanTypes, ClassNameFilter.MISSING, getBeanClassLoader());
    if (!missing.isEmpty()) {
        ConditionMessage message = ConditionMessage.forCondition(annotation)
            .didNotFind("required type", "required types").items(Style.QUOTE, missing);
        return ConditionOutcome.noMatch(message);
    }
    return null;
}
  • 过滤完成后继续调用getAutoConfigurationEntry方法中的fireAutoConfigurationImportEvents方法,该方法查找spring.factories中的org.springframework.boot.autoconfigure.AutoConfigurationImportListener, 向该监听器发布一个AutoConfigurationImportEvent事件
private void fireAutoConfigurationImportEvents(List<String> configurations, Set<String> exclusions) {
    List<AutoConfigurationImportListener> listeners = getAutoConfigurationImportListeners();
    if (!listeners.isEmpty()) {
        AutoConfigurationImportEvent event = new AutoConfigurationImportEvent(this, configurations, exclusions);
        for (AutoConfigurationImportListener listener : listeners) {
            invokeAwareMethods(listener);
            listener.onAutoConfigurationImportEvent(event);
        }
    }
}

onAutoConfigurationImportEvent,向ConditionEvaluationReport中记录自动配置类和排除过的类

public void onAutoConfigurationImportEvent(AutoConfigurationImportEvent event) {
    if (this.beanFactory != null) {
        ConditionEvaluationReport report = ConditionEvaluationReport.get(this.beanFactory);
        report.recordEvaluationCandidates(event.getCandidateConfigurations());
        report.recordExclusions(event.getExclusions());
    }
}
  • 调用selectImports方法
public Iterable<Entry> selectImports() {
    if (this.autoConfigurationEntries.isEmpty()) {
        return Collections.emptyList();
    }
    // 获取到所有的排除
    Set<String> allExclusions = this.autoConfigurationEntries.stream()
        .map(AutoConfigurationEntry::getExclusions).flatMap(Collection::stream).collect(Collectors.toSet());
    // 所有的自动配置类
    Set<String> processedConfigurations = this.autoConfigurationEntries.stream()
        .map(AutoConfigurationEntry::getConfigurations).flatMap(Collection::stream)
        .collect(Collectors.toCollection(LinkedHashSet::new));
    // 再剔除一次
    processedConfigurations.removeAll(allExclusions);

    // 排序,并且封装成List<Entry>返回
    return sortAutoConfigurations(processedConfigurations, getAutoConfigurationMetadata()).stream()
        .map((importClassName) -> new Entry(this.entries.get(importClassName), importClassName))
        .collect(Collectors.toList());
}
  • 下面我们来看如何排序,创建一个AutoConfigurationSorter的类用于排序
private List<String> sortAutoConfigurations(Set<String> configurations,
				AutoConfigurationMetadata autoConfigurationMetadata) {
    return new AutoConfigurationSorter(getMetadataReaderFactory(), autoConfigurationMetadata)
        .getInPriorityOrder(configurations);
}
  • 然后调用getInPriorityOrder方法,在这个方法中新建一个AutoConfigurationClasses的类,在这个类的构造方法中调用addToClasses,将配置类和他们依赖的@AutoConfigureBefore和@AutoConfigureAfter的类放到属性classes中
private void addToClasses(MetadataReaderFactory metadataReaderFactory,
				AutoConfigurationMetadata autoConfigurationMetadata, Collection<String> classNames, boolean required) {
    // 遍历之前扫描出来spring.factories的所有自动配置类
    for (String className : classNames) {
        // 判断是否已经添加过
        if (!this.classes.containsKey(className)) {
            // 封装成AutoConfigurationClass对象
            AutoConfigurationClass autoConfigurationClass = new AutoConfigurationClass(className,
                                                                                       metadataReaderFactory, autoConfigurationMetadata);
            // 判断是否可用,判断条件如下
            // 1. 如果是spring-autoconfigure-metadata.properties中申明过的,直接返回true
            // 2. 如果条件1不满足,判断当前类的class文件或者内部类class文件是否能被加载到,能则返回true
            // 3. 上述条件不满足返回false
            boolean available = autoConfigurationClass.isAvailable();
            // 递归的根方法中一定会添加,即从spring.factories中找到并过滤后的类一定会被添加
            // 被AutoConfigureBefore和AutoConfireAfter引入的类如果不满足上面available的条件,则不添加
            if (required || available) {
                this.classes.put(className, autoConfigurationClass);
            }
            if (available) {
                // 首先autoConfigurationClass.getBefore()方法找到指定的类,查找原则如下:
                // 1.如果当前类名是在spring-autoconfigure-metadata.properties中配置了, 
                //   那么就找这个配置文件下key为 类名 + ".AutoConfigureBefore"对应类
                // 2.如果spring-autoconfigure-metadata.properties下未配置类名的key,就查找该类的注解上@AutoConfigureBefore对应的类
                
                // 然后递归查找
                addToClasses(metadataReaderFactory, autoConfigurationMetadata,
                             autoConfigurationClass.getBefore(), false);
                // after的同样的逻辑
                addToClasses(metadataReaderFactory, autoConfigurationMetadata,
                             autoConfigurationClass.getAfter(), false);
            }
        }
    }
}
  • 回到getInPriorityOrder中,
public List<String> getInPriorityOrder(Collection<String> classNames) {
    AutoConfigurationClasses classes = new AutoConfigurationClasses(this.metadataReaderFactory,
                                                                    this.autoConfigurationMetadata, classNames);
    List<String> orderedClassNames = new ArrayList<>(classNames);
    // Initially sort alphabetically
    // 先按名称顺序排序
    Collections.sort(orderedClassNames);
    // 按前面解析出来的AutoConfigurationClass的getOrder排序,getOrder的逻辑和判断before和after类似
    // 即查看spring-autoconfigure-metadata.properties或者@AutoConfigureOrder注解的Value值,越小越排前
    orderedClassNames.sort((o1, o2) -> {
        int i1 = classes.get(o1).getOrder();
        int i2 = classes.get(o2).getOrder();
        return Integer.compare(i1, i2);
    });
    // Then respect @AutoConfigureBefore @AutoConfigureAfter
    // 然后respect @AutoConfigureBefore @AutoConfigureAfter
    // 根据这个配置,再次排序
    orderedClassNames = sortByAnnotation(classes, orderedClassNames);
    return orderedClassNames;
}
  • sortByAnnotation
private List<String> sortByAnnotation(AutoConfigurationClasses classes, List<String> classNames) {
    // 待排序的
    List<String> toSort = new ArrayList<>(classNames);
    toSort.addAll(classes.getAllNames());
    // 排好序的
    Set<String> sorted = new LinkedHashSet<>();
    // 正在执行排序的
    Set<String> processing = new LinkedHashSet<>();
    // 每遍历一个,remove一个
    while (!toSort.isEmpty()) {
        doSortByAfterAnnotation(classes, toSort, sorted, processing, null);
    }
    // 求交集,最终只返回spring.factories中EnableAutoConfiguration的类
    // 为什么求交集,因为这里排序只是为了保证我们需要的顺序,而不是决定我们后续需要执行哪些配置类的解析,如果需要在它之前执行的配置类没有,
    // 并不影响我当前类的配置解析,而如果要判断是否解析,应该由@Conditional来决定
    sorted.retainAll(classNames);
    return new ArrayList<>(sorted);
}

private void doSortByAfterAnnotation(AutoConfigurationClasses classes, List<String> toSort, Set<String> sorted,
                                     Set<String> processing, String current) {
    if (current == null) {
        current = toSort.remove(0);
    }
    processing.add(current);
    // 判断当前需要排序的类是否有需要在某个类之后配置
    // 如果有
    for (String after : classes.getClassesRequestedAfter(current)) {
        // 断言正在执行排序的类是不是包含了需要先配置的类,如果包含了,那么说明这两个类都需要对方在前,那么会导致死循环,因此抛出异常
        Assert.state(!processing.contains(after),
                     "AutoConfigure cycle detected between " + current + " and " + after);
        // 如果已经排好序的类中有需要先排序的这个类,说明需要提前把这个类先往前排,因此递归调用,递归调用时current传入需要先排序的这个类
        // 因此在最开始的判断current == null时不会为true,因此不会从待排序的队列中剔除,然后继续执行这个for逻辑,如果有继续递归,如果没有
        // 将当前的类名,添加到sorted的列表中,后续在遍历的过程中,依然会在toSort的列表中遍历到该类名,但由于sorted是一个LinkedHashSet
        // 不允许重复,因此即使重复遍历,也不会产生重复的数据
        // 如果上述条件不满足说明,需要先排序的已经在前面排好了序,那么就不用管这个类了
        if (!sorted.contains(after) && toSort.contains(after)) {
            doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
        }
    }
    processing.remove(current);
    // 最终,所有需要先排序的都提前先进入sorted,因此完成了排序
    sorted.add(current);
}
  • 执行完上面的操作后,我们拿到了所有被引入的自动配置类,因此可以回到上面DeferredImportSelectorGroupingHandler的processGroupImports方法了,这个方法,把获取到自动配置类作为配置类进行解析,后续流程参考我另外一篇文章
public void processGroupImports() {
    for (DeferredImportSelectorGrouping grouping : this.groupings.values()) {
        grouping.getImports().forEach(entry -> {
            ConfigurationClass configurationClass = this.configurationClasses.get(
                entry.getMetadata());
            try {
                processImports(configurationClass, asSourceClass(configurationClass),
                               asSourceClasses(entry.getImportClassName()), false);
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException(
                    "Failed to process import candidates for configuration class [" +
                    configurationClass.getMetadata().getClassName() + "]", ex);
            }
        });
    }
}
  • 以上就是Spring Boot自动配置的原理流程啦