前言
最近在看框架的时刻,发现了这个接口,在此举行总结,希望能够给人人辅助,同时提升自己。
order接口的大要先容
Spring框架中有这个一个接口,名字叫Ordered,遐想我们在数据库中应用的Ordered,很容易想到它的寄义就是用来排序。那么问题来了,Spring中为什么要界说这样一个排序接口呢。我们知道spring框架使用了大量的计谋设计模式。计谋设计模式意味着我们的同一个接口,会有大量的差别实现。那么这么多实现,先执行哪个,后执行哪个呢。这就产生了一个排序和优先级的问题,于是Ordered接口登场,用来解决这一问题。
ordered接口的正式先容
首先我们通过spring的源码看一下Ordered接口,源码如下:
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
从上述代码中,我们可以看到ordered接口的实现是异常简朴的。有一个最高的优先级和一个最低的优先级,还提供了一个获得当前实现类的order数值的方式。
spring的order中。越小的值,优先级越高,越大的值优先级越低。
ordered接口的应用
先容完ordered接口之后,我们来看一下现实的应用场景。
有一个典型的场景,我们知道spring的事务管理是通过aop切面来实现的。当我们自己写aop实现的时刻,与事务的切面同时切到了一段代码。那么spring应该先执行谁呢。举一个详细的例子,我们写了一个切换数据源的aspect切面。若是说事务的执行在数据源切换的前面,那么切换数据源就失败了。我们一定希望先执行切换数据源,再执行事务。
于是ordered的应用场景就来了。
假设我们写一个下面的切面。
@Component
@Aspect
public class ChangeDataBase implements Ordered {
//阻挡所有的service操作
@Pointcut("execution( * com.color.*.service.*.*(..))")
public void point() {
}
@Before("point()")
public void onlyReadPre() {
DataSourceContextHolder.setDataSourceType(DataSourceType.MYSQL);
System.out.println("数据库切换MYSQL");
}
@After("point()")
public void onlyReadPast() {
DataSourceContextHolder.setDataSourceType(DataSourceType.ORACLE);
System.out.println("数据库切换回ORACLE");
}
@Override
public int getOrder() {
return 1;
}
}
在上述代码中,我们界说了一个切点,用于阻挡所有的service的方式。然后再方式执行前,我们将数据库切换到mysql,方式执行之后,数据库切换成oracle。
最后重写了ordered接口的getOrder方式。这里我们设置order的级别为1。
这个时刻,我们在设置事务切面的时刻。在xml中设置order。
<tx:annotation-driven transaction-manager="transactionManager" order="2"/>
若是是使用注入bean的方式的话,直接实现接口和上方一样使用即可。
这个时刻,我们就会发现。切换数据源的方式会永远在事务之前执行,这就实现了我们的目的。
order注解的使用
读到现在的读者在想,还要实现接口感受好麻烦啊,有没有什么更利便的方式呢。当然有,我们先容一下@Order注解。
照样先看一下order注解的源码。
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
int value() default 2147483647;
}
默认的优先级是最小的。
我们在使用的时刻,只要在类上面打上order注解即可。
我们模拟两个类,打上order注解,然后再spring容器启动的时刻,对类举行空参组织函数加载,通过空参组织函数内里的打印情形,我们就可以看到类初始化和执行的顺序。
确立我们的第一个order类。
@Component
//使用order属性,设置该类在spring容器中的加载顺序
@Order(1)
public class Order1 {
private final int ORDERED = 1;
public Order1(){
System.out.println(this);
}
@Override
public String toString() {
return "Order1 is loaded @ORDERED=" + ORDERED + "]";
}
}
确立我们的第二个order类。
@Component
//使用order属性,设置该类在spring容器中的加载顺序
@Order(2)
public class Order2 {
private final int ORDERED = 2;
public Order2(){
System.out.println(this);
}
@Override
public String toString() {
return "Order2 is loaded @ORDERED=" + ORDERED + "]";
}
}
启动spring容器之后,我们看到控制台执行如下效果。
Order1 is loaded @ORDERED=1]
Order2 is loaded @ORDERED=2]
orderComparator的先容
那么我们若是想知道一个类的order的值,或者想对照两个类的order值谁大谁小,这个时刻要若何操作呢,Spring知心的给我们提供了一个类。OrderComparator,通过这个类,我们获得实例后,使用它所提供的getOrder或者compare方式即可实现上述的需求。
我们照例照样先来看一下源码。
public class OrderComparator implements Comparator<Object> {
public static final OrderComparator INSTANCE = new OrderComparator();
public OrderComparator() {
}
public Comparator<Object> withSourceProvider(OrderComparator.OrderSourceProvider sourceProvider) {
return (o1, o2) -> {
return this.doCompare(o1, o2, sourceProvider);
};
}
public int compare(@Nullable Object o1, @Nullable Object o2) {
return this.doCompare(o1, o2, (OrderComparator.OrderSourceProvider)null);
}
private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderComparator.OrderSourceProvider sourceProvider) {
boolean p1 = o1 instanceof PriorityOrdered;
boolean p2 = o2 instanceof PriorityOrdered;
if (p1 && !p2) {
return -1;
} else if (p2 && !p1) {
return 1;
} else {
int i1 = this.getOrder(o1, sourceProvider);
int i2 = this.getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
}
private int getOrder(@Nullable Object obj, @Nullable OrderComparator.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);
Object[] var6 = sources;
int var7 = sources.length;
for(int var8 = 0; var8 < var7; ++var8) {
Object source = var6[var8];
order = this.findOrder(source);
if (order != null) {
break;
}
}
} else {
order = this.findOrder(orderSource);
}
}
}
return order != null ? order.intValue() : this.getOrder(obj);
}
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = this.findOrder(obj);
if (order != null) {
return order.intValue();
}
}
return 2147483647;
}
@Nullable
protected Integer findOrder(Object obj) {
return obj instanceof Ordered ? ((Ordered)obj).getOrder() : null;
}
@Nullable
public Integer getPriority(Object obj) {
return null;
}
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
public static void sortIfNecessary(Object value) {
if (value instanceof Object[]) {
sort((Object[])((Object[])value));
} else if (value instanceof List) {
sort((List)value);
}
}
@FunctionalInterface
public interface OrderSourceProvider {
@Nullable
Object getOrderSource(Object var1);
}
}
我们先来重点看一下doCompare方式。判断逻辑如下:
若工具o1是Ordered接口类型,o2是PriorityOrdered接口类型,那么o2的优先级高于o1
若工具o1是PriorityOrdered接口类型,o2是Ordered接口类型,那么o1的优先级高于o2
其他情形,若两者都是Ordered接口类型或两者都是PriorityOrdered接口类型,挪用Ordered接口的getOrder方式获得order值,order值越大,优先级越小
那么一句话来说就是这样的。
OrderComparator对照器举行排序的时刻,若2个工具中有一个工具实现了PriorityOrdered接口,那么这个工具的优先级更高。
若2个工具都是PriorityOrdered或Ordered接口的实现类,那么对照Ordered接口的getOrder方式获得order值,值越低,优先级越高。
再来看一下getOrder方式。
传入一个工具后,通过provider取得原始工具。若是不为空,继续举行判断。
若是是数组工具,对工具举行遍历,获得order后,跳出。若是不是数组则直接获得工具的order。
最后若是order若是不是空,直接返回order的int值,为空的时刻,通过findOrder查看,返回的是order的最大值,也就是最低优先级。
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = this.findOrder(obj);
if (order != null) {
return order.intValue();
}
}
return 2147483647;
}
总结
至此 ordered相关的器械就先容到此为止,文中难免有不足,希望人人提出指正,谢谢。
,阳光在线www.xjllhp.com(原诚信在线)现已开放阳光在线手机版下载。阳光在线游戏公平、公开、公正,用实力赢取信誉。
网友评论
最新评论
欧博官网欢迎进入欧博官网(Allbet Game):www.aLLbetgame.us,欧博官网是欧博集团的官方网站。欧博官网开放Allbet注册、Allbe代理、Allbet电脑客户端、Allbet手机版下载等业务。棒棒棒