springboot原始碼解析-管中窺豹系列之排序(五)

豐極發表於2021-01-13

一、前言

  • Springboot原始碼解析是一件大工程,逐行逐句的去研究程式碼,會很枯燥,也不容易堅持下去。
  • 我們不追求大而全,而是試著每次去研究一個小知識點,最終聚沙成塔,這就是我們的springboot原始碼管中窺豹系列。

 簡介

二、排序

  • 前幾節我們講原始碼的時候,會遇到一些排序的問題,我們都避而不談

比如獲取initializer時的排序:


private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = getClassLoader();
    Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);

    // 排序
    AnnotationAwareOrderComparator.sort(instances);

    return instances;
}

比如對runner排序:

private void callRunners(ApplicationContext context, ApplicationArguments args) {
    List<Object> 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<E> 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<Object> {

    ...

}

compare方法在OrderComparator裡面:

@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);
}
  • 先判斷有沒有實現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對它進行了重寫
@Override
@Nullable
protected Integer findOrder(Object obj) {
    Integer order = super.findOrder(obj);
    if (order != null) {
        return order;
    }
    return findOrderFromAnnotation(obj);
}

@Nullable
private 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),我們進去看看
@Nullable
static 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;
}

@Nullable
private static Integer findOrder(MergedAnnotations annotations) {
    MergedAnnotation<Order> 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,值越大優先順序越低

 豐極

歡迎關注微信公眾號:豐極,更多技術學習分享。

相關文章