美文网首页
spring之接口实现类排序

spring之接口实现类排序

作者: 堵金凯 | 来源:发表于2018-08-22 16:21 被阅读0次

    spring中接口的实现类排序

    应用场景是项目中有个接口,这个接口有多个实现类,对这个多个实现类进行排序

    举例一 实现Ordered接口:

    /**
     * Created by dujinkai on 2018/8/22.
     * 自定义接口
     */
    public interface OrderTest {
        void say();
    }
    
    /**
     * Created by dujinkai on 2018/8/22.
     * 实现类1 
     */
    public class MyOrder1 implements OrderTest ,Ordered {
        @Override
        public void say() {
            System.out.println("MyOrder1");
        }
    
        @Override
        public int getOrder() {
            return Ordered.LOWEST_PRECEDENCE;
        }
    }
    /**
     * Created by dujinkai on 2018/8/22.
     * 实现类2
     */
    public class MyOrder2 implements OrderTest, Ordered {
    
        @Override
        public void say() {
            System.out.println("MyOrder2");
        }
    
        @Override
        public int getOrder() {
            return Ordered.HIGHEST_PRECEDENCE;
        }
    }
    
    public class TestMain {
        public static void main(String[] args) {
            List<OrderTest> orderTestList = new ArrayList<>();
            orderTestList.add(new MyOrder1());
            orderTestList.add(new MyOrder2());
            orderTestList.sort(OrderComparator.INSTANCE);
            orderTestList.stream().forEach(OrderTest::say);
        }
    }
    
    结果:
    MyOrder2
    MyOrder1
    
    Process finished with exit code 0
    

    如上代码 OrderTest 是一个接口 其有2个实现类 MyOrder1和MyOrder2 分别实现ordered接口 实现 getOrder方法就行了

    原理分析 :

    首先看下OrderComparator类

    public class OrderComparator implements Comparator<Object> 
    

    OrderComparator 类实现了Comparator接口 所以我们可以使用List接口的sort 方法来进行排序

    
        @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;
            }
    
            // Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
            int i1 = getOrder(o1, sourceProvider);
            int i2 = getOrder(o2, sourceProvider);
            return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
        }
    
        protected int getOrder(@Nullable Object obj) {
            if (obj != null) {
                Integer order = findOrder(obj);
                if (order != null) {
                    return order;
                }
            }
            return Ordered.LOWEST_PRECEDENCE;
        }
        @Nullable                                                                             
        protected Integer findOrder(Object obj) {                                             
            return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);              
        }                                                                                     
    

    从doCompare 方法我们可以得出这个样的排序结论

    • 1 如果实现类如果实现了PriorityOrdered接口 则其排在实现了Ordered接口的类前面 不管order值是多少
    • 2 如果实现类都实现了PriorityOrdered 接口 那么还是看他们的order值是多少 值越小越靠前
    • 3 如果都实现了Ordered 接口 那么看他们的order值是多少 值越小越靠前

    举例二 使用@Order 注解:

    /**
     * Created by dujinkai on 2018/8/22.
     * 自定义接口
     */
    public interface OrderTest {
        void say();
    }
    /**
     * Created by dujinkai on 2018/8/22.
     * 实现类1
     */
    @Order(value = Ordered.LOWEST_PRECEDENCE)
    public class MyOrder1 implements OrderTest {
        @Override
        public void say() {
            System.out.println("MyOrder1");
        }
    
    }
    
    /**
     * Created by dujinkai on 2018/8/22.
     * 实现类2
     */
    @Order(value = Ordered.HIGHEST_PRECEDENCE)
    public class MyOrder2 implements OrderTest {
    
        @Override
        public void say() {
            System.out.println("MyOrder2");
        }
    
    }
    public class TestMain {
    
        public static void main(String[] args) {
            List<OrderTest> orderTestList = new ArrayList<>();
            orderTestList.add(new MyOrder1());
            orderTestList.add(new MyOrder2());
            orderTestList.sort(AnnotationAwareOrderComparator.INSTANCE);
            orderTestList.stream().forEach(OrderTest::say);
        }
    }
    
    结果:
    MyOrder2
    MyOrder1
    
    Process finished with exit code 0
    

    原理分析:
    这边和上面主要通的就是排序器的不同 实现Ordered接口排序使用的排序器是OrderComparator 而使用@Order注解使用的排序器是AnnotationAwareOrderComparator

    public class AnnotationAwareOrderComparator extends OrderComparator
    

    从AnnotationAwareOrderComparator 类的定义可以看出继承了OrderComparator,所以AnnotationAwareOrderComparator也有排序的能力

        @Override
        @Nullable
        protected Integer findOrder(Object obj) {
            // Check for regular Ordered interface
            Integer order = super.findOrder(obj);
            if (order != null) {
                return order;
            }
    
            // Check for @Order and @Priority on various kinds of elements
            if (obj instanceof Class) {
                return OrderUtils.getOrder((Class<?>) obj);
            }
            else if (obj instanceof Method) {
                Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);
                if (ann != null) {
                    return ann.value();
                }
            }
            else if (obj instanceof AnnotatedElement) {
                Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
                if (ann != null) {
                    return ann.value();
                }
            }
            else {
                order = OrderUtils.getOrder(obj.getClass());
                if (order == null && obj instanceof DecoratingProxy) {
                    order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
                }
            }
    
            return order;
        }
    

    这边AnnotationAwareOrderComparator主要做的一件事就是重写了父类的findOrder方法 该方法主要是用来查找order的值。
    OrderComparator中findOrder比较简单 直接通过回调实现类的getOrder方法获得order的值
    AnnotationAwareOrderComparator 这边首先调用父类的findOrder 如果拿到了就直接返回拿不到就继续找 主要看的是最后一个

            else {
                order = OrderUtils.getOrder(obj.getClass());
                if (order == null && obj instanceof DecoratingProxy) {
                    order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
                }
            }
    
    @Nullable
        public static Integer getOrder(Class<?> type) {
            Object cached = orderCache.get(type);
            if (cached != null) {
                return (cached instanceof Integer ? (Integer) cached : null);
            }
            Order order = AnnotationUtils.findAnnotation(type, Order.class);
            Integer result;
            if (order != null) {
                result = order.value();
            }
            else {
                result = getPriority(type);
            }
            orderCache.put(type, (result != null ? result : NOT_ANNOTATED));
            return result;
        }
    
    

    从这可以看出 OrderUtils.getOrder(obj.getClass());方法重实现类的注解上获取了order的值

    相关文章

      网友评论

          本文标题:spring之接口实现类排序

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