Spring AutoConfigurationSorter源码详解

概述 前面我们简介了spring boot的自动配置机制,现在我们来探讨下spring boot是如何解决这么多繁荣复杂的自动配置类之间的依赖顺序的。

sort

在上一篇《Spring @AutoConfiguration源码详解》中,
EnableAutoConfigurationImportSelector中使用了自动配置类的排序
private
List<String> sort(List<String> configurations)
throws
IOException {
configurations =
new
AutoConfigurationSorter(getMetadataReaderFactory())
.getInPriorityOrder(configurations);

return
configurations;
}

MetadataReaderFactory 我们看到排序的函数用到了MetadataReaderFactory,它的作用生成对应类的MetadataReader 来获取标注的注解等元数据。
public interface
MetadataReaderFactory {
//通过类名获取MetadataReader

MetadataReader getMetadataReader(String className)
throws
IOException;
//通过resource获取MetadataReader,resource包含了.class file路径

MetadataReader getMetadataReader(Resource resource)
throws
IOException;
}

private
MetadataReaderFactory getMetadataReaderFactory() {

try
{
//默认从容器中获取元数据工厂

return
getBeanFactory().getBean(
SharedMetadataReaderFactoryContextInitializer.
BEAN_NAME
,
MetadataReaderFactory.
class
);
}

catch
(NoSuchBeanDefinitionException ex) {
//没有则创建缓存元数据工厂,可配置缓存大小,默认256

return new
CachingMetadataReaderFactory(
this
.
resourceLoader
);
}
}

AutoConfigurationSorter 在spring boot中提供了工具类AutoConfigurationSorter,来对自动配置类进行依赖处理。我们来看看源码:
class
AutoConfigurationSorter {
//…
public
List<String> getInPriorityOrder(Collection<String> classNames)

throws
IOException {
//自动配置类元数据缓存

final
AutoConfigurationClasses classes =
new
AutoConfigurationClasses(

this
.
metadataReaderFactory
, classNames);
List<String> orderedClassNames =
new
ArrayList<String>(classNames);

// 初始化按照字母排序

Collections.
sort
(orderedClassNames);

// 根据order排序

Collections.
sort
(orderedClassNames,
new
Comparator<String>() {

@Override

public int
compare(String o1, String o2) {

int
i1 =
classes
.get(o1).getOrder();

int
i2 =
classes
.get(o2).getOrder();

return
(i1 < i2) ? –
1
: (i1 > i2) ?
1
:
0
;
}
});

// 根据 @AutoConfigureBefore @AutoConfigureAfter 排序

orderedClassNames = sortByAnnotation(classes, orderedClassNames);

return
orderedClassNames;
}

} 我们看到三次排序逻辑如下: 1、按照类名字典排序 2、按照order排序 3、按照@AutoConfigureBefore @AutoConfigureAfter 依赖排序

前面两个排序比较简单,我们来看一下最有一个排序是怎么做的。

private
List<String> sortByAnnotation(AutoConfigurationClasses classes,
List<String> classNames) {
//待排序的有序列表(已经按照字典和order进行排序)
List<String> toSort =
new
ArrayList<String>(classNames);
//已经排序的有序列表
Set<String> sorted =
new
LinkedHashSet<String>();
//处理中的有序列表,类似中间缓存队列
Set<String> processing =
new
LinkedHashSet<String>();

while
(!toSort.isEmpty()) {
//执行排序
doSortByAfterAnnotation(classes, toSort, sorted, processing,
null
);
}

return new
ArrayList<String>(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);
//获取所有需要在current之前执行的自动配置,即标注了@
AutoConfigureAfter

for
(String after : classes.getClassesRequestedAfter(current)) {
//循环依赖判断断言
Assert.
state
(!processing.contains(after),

“AutoConfigure cycle detected between ”
+ current +
” and ”
+ after);
//未处理过,则处理当前自动配置类之前的依赖自动配置类

if
(!sorted.contains(after) && toSort.contains(after)) {
doSortByAfterAnnotation(classes, toSort, sorted, processing, after);
}
}
//移除处理中
processing.remove(current);
//添加到已处理
sorted.add(current);
}

排序后依次再交给bean处理器处理,就可以正确的初始化自动配置bean了。那么最终是谁来执行这个导入选择器的呢? 答案是ConfigurationClassPostProcessor里面的ConfigurationClassParser。

    原文作者:Spring Boot
    原文地址: https://blog.csdn.net/ws008/article/details/80008012
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞