首先我们要知道 @EnableAutoConfiguration 是用于激活 Spring Boot 自动装配的特性。
但是平常项目开发中我们一般使用的是@SpringBootApplication,可以通过查看注解代码,知道springboot里面 包含了 @EnableAutoConfiguration 注解,所以当你使用@SpringBootApplication已经启动了自动装配的特性
理解@ EnableAutoConfiguration

依照@Enable 模块驱动设计模式,@EnableAutoConfiguration 必然“@Import ” ImportSelector、 或 ImportBeanDefinitionRegistrar 的实现类。
窥探 AutoConfigurationImportSelector
//重写selectImports 方法
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return NO_IMPORTS;
}
AutoConfigurationMetadata autoConfigurationMetadata = AutoConfigurationMetadataLoader
.loadMetadata(this.beanClassLoader);
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(autoConfigurationMetadata,
annotationMetadata);
return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());
}
/**
* Return the {@link AutoConfigurationEntry} based on the {@link AnnotationMetadata}
* of the importing {@link Configuration @Configuration} class.
* @param autoConfigurationMetadata the auto-configuration metadata
* @param annotationMetadata the annotation metadata of the configuration class
* @return the auto-configurations that should be imported
*/
protected AutoConfigurationEntry getAutoConfigurationEntry(AutoConfigurationMetadata autoConfigurationMetadata,
AnnotationMetadata annotationMetadata) {
if (!isEnabled(annotationMetadata)) {
return EMPTY_ENTRY;
}
AnnotationAttributes attributes = getAttributes(annotationMetadata);
//获取META-INF/spring.factories 资源中@EnableAutoConfiguration 所关联的自动装配Class集合
List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//通过使用set集合 达到去重的目的
configurations = removeDuplicates(configurations);
//读取当前配置类所标注的@EnableAutoConfiguration 属性 exclude 和 excludeName, 并与 spring.autoconfigure.exclude 配置属性合并为自动装配 Class 排除集合。
Set<String> exclusions = getExclusions(annotationMetadata, attributes);
//检查自动装配 Class 排除集合是否合法
checkExcludedClasses(configurations, exclusions);
//排除候选自动装配 Class 集合中的排除名单
configurations.removeAll(exclusions);
// 再次过滤候选自动装配 Class 集合中 Class 不存在的成员
configurations = filter(configurations, autoConfigurationMetadata);
//触发自动装配导入事件
fireAutoConfigurationImportEvents(configurations, exclusions);
return new AutoConfigurationEntry(configurations, exclusions);
}
获取候选对象


该方法实际执行的是 SpringFactoriesLoader#loadFactoryNames(Class,Classloader) 方法:
public final class SpringFactoriesLoader {
public static final String FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories";
...省略部分代码...
public static List<String> loadFactoryNames(Class<?> factoryClass, @Nullable ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
return (List)loadSpringFactories(classLoader).getOrDefault(factoryClassName, Collections.emptyList());
}
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = (MultiValueMap)cache.get(classLoader);
if (result != null) {
return result;
} else {
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
LinkedMultiValueMap result = new LinkedMultiValueMap();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
Iterator var6 = properties.entrySet().iterator();
while(var6.hasNext()) {
Entry<?, ?> entry = (Entry)var6.next();
String factoryClassName = ((String)entry.getKey()).trim();
String[] var9 = StringUtils.commaDelimitedListToStringArray((String)entry.getValue());
int var10 = var9.length;
for(int var11 = 0; var11 < var10; ++var11) {
String factoryName = var9[var11];
result.add(factoryClassName, factoryName.trim());
}
}
}
cache.put(classLoader, result);
return result;
} catch (IOException var13) {
throw new IllegalArgumentException("Unable to load factories from location [META-INF/spring.factories]", var13);
}
}
}
...省略部分代码...
}
SpringFactoriesLoader、 是 Spring Framework 工厂机制的加载器 , loadFactorγNames(Class,Classloader)方法加载原理如下:
( 1 ) 搜索指定 ClassLoader下所有的META-INF/spring.factories 资源内容(可能存在多
个〉。
(2)将一个或多个META-INF/spring.factories 资源内容作为 Properties 文件读取, 合并 为 一 个 Key 为 接口 的 全类名 , Value 是实现类全类名 列 表 的Map , 作为 loadSpringFactories(Classloader)方法的返回值。
(3〕 再从上一步返回的 Map 中查找并返回方法指定类名所映射的实现类全类名列表。
由于@EnableAutoConfiguration 配置可能存在自动装配组件类名重复定义的情况 , 当 getCandidateConfigurations(AnnotationMetadata,AnnotationAttributes ) 方法获取所有 的候选类集合名后,立即执行 removeDuplicates(List)方法,利用 Set 不可重复性达到去重的目 的:
获取自动装配 排除对象集合
当 getExclusions(AnnotationMetadata,AnnotationAttr吐butes )方法执行后, 程序将获得一个自动装配 Class 的排除名单:
检查自动装配 Class 排除集合是否合法
当排除类存在于当前 ClassLoader 且不在自动装配候选类名单 中 时 , handle InvalidExcludes(List )方法被执行, 触发排除类非法异常。
接着该排除集合 exclusions 从候选自动装配 Class 名 单 configurations 中 移 除: configurations.removeAll(exclusions)。计算后的 configurations 并非最终自动装配 Class 名单, 还需再次过滤。
过滤Class 集合中 Class 不存在的成员
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);
boolean[] match = filter.match(candidates, autoConfigurationMetadata);
for (int i = 0; i < match.length; i++) {
if (!match[i]) {
skip[i] = true;
candidates[i] = null;
skipped = true;
}
}
}
if (!skipped) {
return configurations;
}
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);
}
protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {
return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}
其中 AutoConfigurationimportFilter、 对象集合同样被 SpringFactoriesLoader加载, 故查找 AutoConfigurationimportFilter 在所有 META-INF/spring.factories 资源中的配置。 Spring Boot 框架默认仅有 一 处声明,即在 org.springframework.boot:spring-bootautoconfigure 中 :
该方法 实际作用是过滤 META-INF/spring.factories 资源中那些当前 ClassLoader 不存在的 Class 。
触发自动装配导入事件
fireAutoConfigurationImportEvents(configurations, exclusions)
Spring Boot 1.5 开始引入 AutoConfigurationlmportlistener、接口,它有别于传统的 Spring Application Listener 的实现。 ApplicationListener 与 Spring 应用上下文 Configurable ApplicationContext 紧密关联,监昕 Spring ApplicationEvent 。 而 AutoConfiguration Import Listener 则是自定义Java Event Listener 实现,仅监昕 AutoConfigurationlmpo时Event, 然而其实例同样被 SpringFactoriesLoader 加载,因此 Spring Boot 框架层面为开发人员提供了扩 展的途径。其中, Condition EvaluationRepo内AutoConfigurationlmpor吃Listener 就是内建 实现,用于记录自动装配的条件评估详情,配置在 META-INFI spr、ing.factories 资源中:
当然如果读者感兴趣可以自己去实现一个监听器
到这里基本已经结束了,当然还有一些其他的功能组件,例如:排序自动装配组件
Spring Boot 提供了两种自动装配组件的排序手段:
绝对自动装配顺序 @AutoConfigureOrder;
相对自动装配顺序 @AutoConfigureBefore 和@AutoConfigureAfter。
来进行自动装配组件的顺序,读者感兴趣可以自己去了解
总而言之:
AutoConfigurationimportSelector、 读取自动装配 Class 的流程为:
( 1 )通过 SpringFactoriesLoader#loadFactoryNames(Class,ClassLoader)方法读取所有 META-INF/spring.factories 资源中@EnableAutoConfiguration 所关联的自动装配 Class 集合。
( 2 )读取当前配置类所标注的@EnableAutoConfiguration 属性 exclude 和 excludeName, 并与 spring.autoconfigure.exclude 配置属性合并为自动装配 Class 排除集合。
( 3 )检查自动装配 Class 排除集合是否合法。
( 4 )排除候选自动装配 Class 集合中的排除名单。
( 5 )再次过滤候选自动装配 Class 集合中 Class 不存在的成员。
当自动装配 Class 读取完毕后, fireAutoConfigurationimportEvents(List, Set )方法被执行,触发了一个自动装配的导入事件
参考《springboot 编程思想(核心篇)》








还没有评论,来说两句吧...