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