spring之接口实现类排序

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 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 
 
 

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 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之接口实现类排序)