SpringBoot
中工厂类加载器加载的实现类通常有多个,这些类通常会排序后放入集合
AnnotationAwareOrderComparator
是常用的比较器
AnnotationAwareOrderComparator
父类:OrderComparator
接口:Comparator
相关方法
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
@Override
public int compare(@Nullable Object o1, @Nullable Object o2) {
return doCompare(o1, o2, null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
}
else if (p2 && !p1) {
return 1;
}
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
for (Object source : ObjectUtils.toObjectArray(orderSource)) {
order = findOrder(source);
if (order != null) {
break;
}
}
}
else {
order = findOrder(orderSource);
}
}
}
return (order != null ? order : getOrder(obj));
}
排序逻辑:
- 先看是否实现了接口
PriorityOrdered
,优先级最高排前面 - 如果都实现了
PriorityOrdered
或者,都没有实现PriorityOrdered
接口,就比较order值 - order值优先从
Ordered
接口的getOrder
方法获取 - 其次从注解
Order
的value值获取 - 或者从注解
javax.annotation.Priority
的value值获取 - 都没取到,就取默认值
Integer.MAX_VALUE
比如监听器的排序
ClearCachesApplicationListener Integer.MAX_VALUE
ParentContextCloserApplicationListener Integer.MAX_VALUE - 10
FileEncodingApplicationListener Integer.MAX_VALUE
AnsiOutputApplicationListener Integer.MIN_VALUE + 10 + 1
DelegatingApplicationListener 0
LoggingApplicationListener Integer.MAX_VALUE
EnvironmentPostProcessorApplicationListener Integer.MIN_VALUE + 10
BackgroundPreinitializer Integer.MIN_VALUE + 20 + 1
最终排序为:
DelegatingApplicationListener
EnvironmentPostProcessorApplicationListener
AnsiOutputApplicationListener
ParentContextCloserApplicationListener
BackgroundPreinitializer
ClearCachesApplicationListener
FileEncodingApplicationListener
LoggingApplicationListener
除了监听器,多个地方用到了排序
这里只是查找了SpringBoot
代码,Spring
中也有。