jdk 1.8 list 排序_springboot原始碼解析-管中窺豹系列之排序(五)
阿新 • • 發佈:2021-01-31
技術標籤:jdk 1.8 list 排序
一、前言
- Springboot原始碼解析是一件大工程,逐行逐句的去研究程式碼,會很枯燥,也不容易堅持下去。
- 我們不追求大而全,而是試著每次去研究一個小知識點,最終聚沙成塔,這就是我們的springboot原始碼管中窺豹系列。
二、排序
- 前幾節我們講原始碼的時候,會遇到一些排序的問題,我們都避而不談
比如獲取initializer時的排序:
private Collection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) { ClassLoader classLoader = getClassLoader(); Set names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); // 排序 AnnotationAwareOrderComparator.sort(instances); return instances;}
比如對runner排序:
private void callRunners(ApplicationContext context, ApplicationArguments args) { List runners = new ArrayList<>(); // (1) 找到ApplicationRunner的實現類,加到list裡面 runners.addAll(context.getBeansOfType(ApplicationRunner.class).values()); // (2) 找到CommandLineRunner的實現類,加到list裡面 runners.addAll(context.getBeansOfType(CommandLineRunner.class).values()); // (3) 排序 AnnotationAwareOrderComparator.sort(runners); // (4) 鉤子回撥 for (Object runner : new LinkedHashSet<>(runners)) { if (runner instanceof ApplicationRunner) { callRunner((ApplicationRunner) runner, args); } if (runner instanceof CommandLineRunner) { callRunner((CommandLineRunner) runner, args); } }}
我們來分析一下這個排序AnnotationAwareOrderComparator.sort(list)的原始碼。
三、原始碼解析
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();public static void sort(List> list) { if (list.size() > 1) { list.sort(INSTANCE); }}
- 已new的AnnotationAwareOrderComparator物件作為引數,排序
- list.sort(comparator)是jdk自帶的排序, 通用的
default void sort(Comparator super E> c) { Object[] a = this.toArray(); Arrays.sort(a, (Comparator) c); ListIterator i = this.listIterator(); for (Object e : a) { i.next(); i.set((E) e); }}
- 我們知道排序要麼實現Comparable介面,要麼new Comparator, spring用的第二種
- 我們重點看下這個comparator : AnnotationAwareOrderComparator
public class AnnotationAwareOrderComparator extends OrderComparator { ...}public class OrderComparator implements Comparator { ...}
compare方法在OrderComparator裡面:
@Overridepublic 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);}
- 先判斷有沒有實現PriorityOrdered介面,實現了的比沒實現的有高優先順序
- 再用getOrder()判斷
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()) { Object[] sources = ObjectUtils.toObjectArray(orderSource); for (Object source : sources) { order = findOrder(source); if (order != null) { break; } } } else { order = findOrder(orderSource); } } } return (order != null ? order : getOrder(obj));}
sourceProvider為空,我們可以直接看最後一行。
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;protected int getOrder(@Nullable Object obj) { if (obj != null) { Integer order = findOrder(obj); if (order != null) { return order; } } return Ordered.LOWEST_PRECEDENCE;}protected Integer findOrder(Object obj) { return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);}
- 判斷有沒有實現Ordered介面,如果有就取出來它的order值
- 如果沒有,就取Integer.MAX_VALUE
- 注意,order值越小,優先順序越高
- 注意,上面findOrder方法是protected, 我們最開始說的AnnotationAwareOrderComparator對它進行了重寫
@[email protected] Integer findOrder(Object obj) { Integer order = super.findOrder(obj); if (order != null) { return order; } return findOrderFromAnnotation(obj);}@Nullableprivate Integer findOrderFromAnnotation(Object obj) { AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass()); MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY); Integer order = OrderUtils.getOrderFromAnnotations(element, annotations); if (order == null && obj instanceof DecoratingProxy) { return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass()); } return order;}
- 先呼叫父類的findOrder方法
- 沒找到,再呼叫findOrderFromAnnotation方法
- 最重要的是這一行:OrderUtils.getOrderFromAnnotations(element, annotations),我們進去看看
@Nullablestatic Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) { if (!(element instanceof Class)) { return findOrder(annotations); } Object cached = orderCache.get(element); if (cached != null) { return (cached instanceof Integer ? (Integer) cached : null); } Integer result = findOrder(annotations); orderCache.put(element, result != null ? result : NOT_ANNOTATED); return result;}@Nullableprivate static Integer findOrder(MergedAnnotations annotations) { MergedAnnotation orderAnnotation = annotations.get(Order.class); if (orderAnnotation.isPresent()) { return orderAnnotation.getInt(MergedAnnotation.VALUE); } MergedAnnotation> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION); if (priorityAnnotation.isPresent()) { return priorityAnnotation.getInt(MergedAnnotation.VALUE); } return null;}private static final String JAVAX_PRIORITY_ANNOTATION = "javax.annotation.Priority";
- 兩個方法,第一個是簡單的快取,不用看,重點看第二個方法
- 先判斷有沒有org.springframework.core.annotation.Order註解
- 再判斷有沒有javax.annotation.Priority註解
- 有註解就去上面的值,沒有返回null
回到最開始的方法,進行int值的排序
Integer.compare(i1, i2);public static int compare(int x, int y) { return (x < y) ? -1 : ((x == y) ? 0 : 1);}
至此,我們的排序原始碼就分析完了,我們總結一下:
- (1)先判斷有沒有實現PriorityOrdered,實現PriorityOrdered比沒實現的有高優先順序
- (2)第一步如果比較不出來,判斷有沒有實現Ordered,如果實現了,取實現方法的int值比較
- (3)如果沒有實現Ordered,判斷有沒有org.springframework.core.annotation.Order註解, 有註解,取註解上的order值,進行比較
- (4)如果沒有Order註解,判斷有沒有javax.annotation.Priority註解,取註解上的值比較
- (5)如果上面都沒有,返回Integer.MAX_VALUE,值越大優先順序越低
歡迎關注微信公眾號:豐極,更多技術學習分享。