美文网首页
SpringBoot中的排序

SpringBoot中的排序

作者: 噼咔丘 | 来源:发表于2020-05-07 19:03 被阅读0次

    包含三个类

    AnnotationAwareOrderComparator

    OrderComparator

    Comparator

    类图如下:


    image-20200421180701888.png

    步骤1:排序调用OrderComparator的compare方法

    public int compare(@Nullable Object o1, @Nullable Object o2) {
       return doCompare(o1, o2, null);
    }
    

    步骤2:调用内部方法doCompare,先判断是否有一个实现PriorityOrdered接口,如果有一个实现,顺序关系可以确定直接返回。

    如果都没有实现或者都实现了PriorityOrdered接口,进一步调用getOder方法返回排序值,然后确定顺序关系。

    private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
        // 实现了PriorityOrdered接口,排序靠前
        // PriorityOrdered继承自Ordered接口,也可以实现getOrder方法,所以实现PriorityOrdered的类里面getOrder越小的越靠前
       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);
    }
    

    步骤3:内部方法getOrder,在OrderSourceProvider为null的情况下,直接调用了getOder重构方法

    private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
       Integer order = null;
        //OrderSourceProvider这里不做分析
       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));
    }
    

    步骤4:getOder里面调用了findOrder方法,findOrder返回null的时候直接返回最小排序值

    protected int getOrder(@Nullable Object obj) {
       if (obj != null) {
          Integer order = findOrder(obj);
          if (order != null) {
             return order;
          }
       }
       return Ordered.LOWEST_PRECEDENCE;
    }
    

    步骤5:AnnotationAwareOrderComparator重写findOrder方法

    //AnnotationAwareOrderComparator重写findOrder方法
    @Override
    @Nullable
    protected Integer findOrder(Object obj) {
        // 先调用父类方法,判断是否实现了Ordered接口,如果实现了调用getOrder方法,否则返回null
       Integer order = super.findOrder(obj);
       if (order != null) {
          return order;
       }
        // 如果没有实现Ordered接口,或者实现了Ordered接口但是getOrder返回null,则调用该方法
       return findOrderFromAnnotation(obj);
    }
    
    // 父类OrderComparator的findOrder方法
    @Nullable
    protected Integer findOrder(Object obj) {
        return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
    }
    

    步骤6:AnnotationAwareOrderComparator核心方法

    @Nullable
    private Integer findOrderFromAnnotation(Object obj) {
        // AnnotatedElement代表了在当前JVM中的一个“被注解元素”(可以是Class,Method,Field,Constructor,Package等
       AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
        // MergedAnnotations是Spring的工具类,from方法是从element中获取注解,SearchStrategy是注解扫描策略,TYPE_HIERARCHY包含superclass,接口
       MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
        // 根据注解解析order
       Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
        // 如果order为null,并且排序对象实现了DecoratingProxy,则从代理类中获取排序order
       if (order == null && obj instanceof DecoratingProxy) {
          return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
       }
       return order;
    }
    

    步骤7:OrderUtils方法

    @Nullable
    static Integer getOrderFromAnnotations(AnnotatedElement element, MergedAnnotations annotations) {
        // 如果注解元素不是一个类,每次都从注解中获取order
       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) {
        // 如果改元素上存在Order注解,则返回value值
       MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
       if (orderAnnotation.isPresent()) {
          return orderAnnotation.getInt(MergedAnnotation.VALUE);
       }
        // 如果不存在Order注解,但是存在javax.annotation.Priority注解,则返回该注解的value值
       MergedAnnotation<?> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION);
       if (priorityAnnotation.isPresent()) {
          return priorityAnnotation.getInt(MergedAnnotation.VALUE);
       }
        // 如果注解都不存在,则返回null
       return null;
    }
    

    总结:

    两个对象比较,排序规则调用判断顺序如下:

    1. 其中有一个实现了PriorityOrdered,则排序靠前,返回排序状态。如果都没有实现PriorityOrdered接口,或者都实现了PriorityOrdered接口,继续往下执行

    2. 分别获取两个对象的排序值,根据排序值确定排序状态

    3. 如果实现了PriorityOrdered或者Ordered接口,调用getOrder方法返回排序值。如果没有实现这两个接口或者getOrder方法返回null,继续往下执行

    4. 如果有Order注解,返回注解的value值作为排序值

    5. 如果有Priority注解,返回value值作为排序值

    6. 如果都没有,返回最小排序值

    相关文章

      网友评论

          本文标题:SpringBoot中的排序

          本文链接:https://www.haomeiwen.com/subject/qekzghtx.html