前言
最近在看框架的时候, 发现了这个接口, 在此进行总结, 希望能够给大家帮助, 同时提升自己.
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 相关的东西就介绍到此为止, 文中难免有不足, 希望大家提出指正, 感谢.
来源: https://www.cnblogs.com/jichi/p/12884915.html