EnableAutoConfiguration

What

@EnableAutoConfiguration是Spring Boot自动装配的入口,用于加载配置文件META-INF/spring.factoriesorg.springframework.boot.autoconfigure.EnableAutoConfiguration指定的且未被exclude()excludeName()所排除的配置类,以实现Spring Boot 的自动装配功能。

How

了解了自动装配的功能,那么其是如何实现的呢?

首先,查看@EnableAutoConfiguration注解的源码,发现其类上声明了一个@Import注解标记,且这个票房指定了一个配置类AutoConfigurationImportSelector

package org.springframework.boot.autoconfigure;

@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
}

接着想看AutoConfigurationImportSelector的源码,发现其实现了ImportSelector接口。

classDiagram
    ImportSelector <|-- DeferredImportSelector
    DeferredImportSelector <|-- AutoConfigurationImportSelector
    
    class ImportSelector {
        + String[] selectImports(importingClassMetadata)
    }

这时,我们可以知道这个配置类会在容器加载或刷新时被解析并回调selectImports()方法。

那么现在就来看看AutoConfigurationImportSelector是如何实现selectImports()方法的吧:

	@Override
	public String[] selectImports(AnnotationMetadata annotationMetadata) {
		if (!isEnabled(annotationMetadata)) {
			return NO_IMPORTS;
		}
		AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);
		return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
	}

在上述方法中,getAutoConfigurationEntry()方法创建AutoConfigurationEntry,并将其configurations的值返回,AutoConfigurationEntry的定义如下:

protected static class AutoConfigurationEntry {

	private final List<String> configurations;

	private final Set<String> exclusions;

}

现在,再来看下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);
}