关于java:springboot源码解析管中窥豹系列之排序五

41次阅读

共计 5426 个字符,预计需要花费 14 分钟才能阅读完成。

一、前言

  • 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,值越大优先级越低

欢送关注微信公众号:丰极,更多技术学习分享。

正文完
 0