文章目录
1、Spring 执行顺序排序
Spring 是一个大量使用策略设计模式的框架,这意味着有很多相同接口的实现类,那么必定会有优先级的问题,spring 为了解决排序问题,提供了 Ordered 接口
(1)Ordered 接口分析
Ordered 接口源码,很简短,就定义了一个 Ordered 接口,然后两个常量,分别对应最高级(数值最小)和最低级(数值最大),也就是数值越小,等级越高,数值越大,等级越低,然后有一个 getOrder()方法返回排序值
package org.springframework.core;
public interface Ordered {
/**
* 最高级(数值最小)
*
* @see java.lang.Integer#MIN_VALUE
*/
int HIGHEST_PRECEDENCE = Integer.MIN_VALUE;
/**
* 最低级(数值最大)
*
* @see java.lang.Integer#MAX_VALUE
*/
int LOWEST_PRECEDENCE = Integer.MAX_VALUE;
/**
* 获取该对象的order值。
* <p>较高的值被解释为较低的优先级。作为结果,
* 值最低的对象具有最高优先级(有点
* 类似于Servlet {@ code-on-startup}值)。
* <p>相同的order值将导致受影响的对象任意排序位置
*
* @return 排序值
* @see #HIGHEST_PRECEDENCE
* @see #LOWEST_PRECEDENCE
*/
int getOrder();
}
(2)PriorityOrdered 接口分析
PriorityOrdered 接口源码没有方法,只是实现了 Ordered 接口,但是实现它的子类是执行顺序优先级最高的
package org.springframework.core;
/**
* 优先级最高
*
* @author Juergen Hoeller
* @author Sam Brannen
* @since 2.5
* @see org.springframework.beans.factory.config.PropertyOverrideConfigurer
* @see org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
*/
public interface PriorityOrdered extends Ordered {
}
(3)OrderComparator 类分析
OrderComparator 类是一个实现了 Comparator 的一个比较器,它提供了 2 个静态排序方法:sort(List<?> list)、sort(Object[] array),对数组和集合进行排序,核心方法为 doCompare()
package org.springframework.core;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* 排序规则:
* 1、PriorityOrdered优先级最高
* 2、具有相同顺序值的对象按任意顺序排序
* 3、无序对象都是隐式的,分配的值为最大值,在排序的末尾
*
* @author Juergen Hoeller
* @author Sam Brannen
* @see Ordered
* @see PriorityOrdered
* @see org.springframework.core.annotation.AnnotationAwareOrderComparator
* @see java.util.List#sort(java.util.Comparator)
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
* @since 07.04.2003
*/
public class OrderComparator implements Comparator<Object> {
/**
* {@code OrderComparator}的共享默认实例。
*/
public static final OrderComparator INSTANCE = new OrderComparator();
/**
* 与给定的源提供商建立一个适应的order比较器。
*
* @param sourceProvider order源提供程序
* @return 自适应比较器
* @since 4.1
*/
public Comparator<Object> withSourceProvider(OrderSourceProvider sourceProvider) {
return (o1, o2) -> doCompare(o1, o2, sourceProvider);
}
@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) {
// 如果有PriorityOrdered 接口的,则 PriorityOrdered 优先级比其他的都高
boolean p1 = (o1 instanceof PriorityOrdered);
boolean p2 = (o2 instanceof PriorityOrdered);
if (p1 && !p2) {
return -1;
} else if (p2 && !p1) {
return 1;
}
// 如果都是PriorityOrdered 通过order值排序,值小优先级高
// 如果都不是PriorityOrdered,即是其他的接口和注解,通过order值来排序,值越小优先级越高
int i1 = getOrder(o1, sourceProvider);
int i2 = getOrder(o2, sourceProvider);
return Integer.compare(i1, i2);
}
/**
* 确定给定对象的order值。
* 默认实现检查给定的{@link OrderSourceProvider}
* 使用{@link #findOrder}并返回到常规的{@link#getOrder(Object)}调用。
*
* @param obj 要检查的对象
* @return 排序值, 或 {@code Ordered.LOWEST_PRECEDENCE} 默认值
*/
private int getOrder(@Nullable Object obj, @Nullable 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);
for (Object source : sources) {
order = findOrder(source);
if (order != null) {
break;
}
}
} else {
order = findOrder(orderSource);
}
}
}
return (order != null ? order : getOrder(obj));
}
/**
* 确定给定对象的排序值.
* <p>默认实现检查{@link Ordered}接口
* 通过委派给{@link #findOrder}。可以在子类中重写。
*
* @param obj 要检查的对象
* @return 排序值, 或 {@code Ordered.LOWEST_PRECEDENCE} 默认值
*/
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}
/**
* 查找给定对象指示的排序值.
* <p>默认实现检查{@link Ordered}接口。
* 可以在子类中重写。
*
* @param obj 要检查的对象
* @return 排序值, 或 {@code Ordered.LOWEST_PRECEDENCE} 默认值
*/
@Nullable
protected Integer findOrder(Object obj) {
return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
}
/**
* 确定给定对象的优先级值(如果有)。
* <p>默认实现始终返回{@code null}。
* 子类可以重写它以给特定类型的值
* 除了'priority'的语义。
* 优先级表示它可以用来选择一个对象
* 另一个,除了在列表/数组中用于排序之外。
*
* @param obj 要检查的对象
* @return 优先级值,如果没有,则为{@code null}
* @since 4.1
*/
@Nullable
public Integer getPriority(Object obj) {
return null;
}
/**
* 使用默认OrderComparator对给定列表排序。
* <p>优化为跳过大小为0或1的列表的排序,
* 为了避免不必要的数组提取。
*
* @param list the List to sort
* @see java.util.List#sort(java.util.Comparator)
*/
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
/**
* 使用默认OrderComparator对给定数组进行排序。
* <p>优化以跳过对大小为0或1的列表的排序,
* 为了避免不必要的数组提取。
*
* @param array 要排序的数组
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
*/
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
/**
* 使用默认的OrderComparator对给定的数组或列表进行排序,
* 如果有必要. 给定其他任何值时,仅跳过排序.
* <p>优化以跳过对大小为0或0的列表的排序1,
* 为了避免不必要的数组提取.
*
* @param value 数组或要排序的列表
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
*/
public static void sortIfNecessary(Object value) {
if (value instanceof Object[]) {
sort((Object[]) value);
} else if (value instanceof List) {
sort((List<?>) value);
}
}
/**
* 策略接口,用于为给定对象提供order来源。
*
* @since 4.1
*/
@FunctionalInterface
public interface OrderSourceProvider {
/**
* 返回指定对象的order来源,即
* 应检查order值以代替给定对象。
* <p>也可以是订order源对象的数组。
* <p>如果返回的对象不表示任何顺序,则比较器
* 将退回到检查原始对象。
*
* @param obj 查找order来源的对象
* @return 该对象的order来源,如果找不到,则为{@code null}
*/
@Nullable
Object getOrderSource(Object obj);
}
}
- OrderComparator 比较器进行排序的时候,若 2 个对象中有一个对象实现了 PriorityOrdered 接口,那么这个对象的优先级更高
- 若 2 个对象都是 PriorityOrdered 或 Ordered 接口的实现类,那么比较 Ordered 接口的 getOrder 方法得到 order 值,值越低,优先级越高
(4)AnnotationAwareOrderComparator 类分析
随便查了一下源码,OrderComparator 的使用频率高吗?但是发现 OrderComparator 几乎不怎么使用,发现 spring 源码中使用了大量的 AnnotationAwareOrderComparator 来进行排序,这里我们就继续分析 AnnotationAwareOrderComparator 的源码
package org.springframework.core.annotation;
import org.springframework.core.DecoratingProxy;
import org.springframework.core.OrderComparator;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.lang.Nullable;
import java.lang.reflect.AnnotatedElement;
import java.util.Arrays;
import java.util.List;
/**
* AnnotationAwareOrderComparator是支持spring的Ordered接口,以及@Order和java的@Priority的注解,
* 他的顺序值由Ordered提供,实例重写静态定义的注释值(如果有)。
*
* @author Juergen Hoeller
* @author Oliver Gierke
* @author Stephane Nicoll
* @see org.springframework.core.Ordered
* @see org.springframework.core.annotation.Order
* @see javax.annotation.Priority
* @since 2.0.1
*/
public class AnnotationAwareOrderComparator extends OrderComparator {
/**
* {@code AnnotationAwareOrderComparator}的共享默认实例。
*/
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
/**
* 此实现检查{@link Order@Order}或
* {@链接javax.annotation.Priority@优先权
* 元素,以及{@链接org.springframework.core.有序的}
* 检查超类。
*/
@Override
@Nullable
protected Integer findOrder(Object obj) {
Integer order = super.findOrder(obj);
if (order != null) {
return order;
}
return findOrderFromAnnotation(obj);
}
@Nullable
private Integer findOrderFromAnnotation(Object obj) {
AnnotatedElement element = (obj instanceof AnnotatedElement ? (AnnotatedElement) obj : obj.getClass());
MergedAnnotations annotations = MergedAnnotations.from(element, SearchStrategy.TYPE_HIERARCHY);
Integer order = OrderUtils.getOrderFromAnnotations(element, annotations);
if (order == null && obj instanceof DecoratingProxy) {
return findOrderFromAnnotation(((DecoratingProxy) obj).getDecoratedClass());
}
return order;
}
/**
* 此实现检索@{@链接javax.annotation.Priority}
* 值,允许在常规的@{@link Order}上附加语义
* 注释:通常,在
* 多个匹配项,但只返回一个对象。
*/
@Override
@Nullable
public Integer getPriority(Object obj) {
if (obj instanceof Class) {
return OrderUtils.getPriority((Class<?>) obj);
}
Integer priority = OrderUtils.getPriority(obj.getClass());
if (priority == null && obj instanceof DecoratingProxy) {
return getPriority(((DecoratingProxy) obj).getDecoratedClass());
}
return priority;
}
/**
* 使用默认的{@link AnnotationAwareOrderComparator}对给定列表进行排序。
* <p>优化为跳过大小为0或1的列表的排序,
* 为了避免不必要的数组提取。
*
* @param list 要排序的列表
* @see java.util.List#sort(java.util.Comparator)
*/
public static void sort(List<?> list) {
if (list.size() > 1) {
list.sort(INSTANCE);
}
}
/**
* 使用默认注释awareOrderComparator对给定数组进行排序。
* <p>优化为跳过大小为0或1的列表的排序,
* 为了避免不必要的数组提取。
*
* @param array 要排序的数组
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
*/
public static void sort(Object[] array) {
if (array.length > 1) {
Arrays.sort(array, INSTANCE);
}
}
/**
* 使用默认注释awareOrderComparator对给定的数组或列表进行排序,
* 如有必要。当给定任何其他值时,只需跳过排序。
* <p>优化为跳过大小为0或1的列表的排序,
* 为了避免不必要的数组提取。
*
* @param value 要排序的数组或列表
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
*/
public static void sortIfNecessary(Object value) {
if (value instanceof Object[]) {
sort((Object[]) value);
} else if (value instanceof List) {
sort((List<?>) value);
}
}
}
看完源码之后,是不是发现和 OrderComparator 的源码极其相似,2 个静态排序方法:sort(List<?> list)、sort(Object[] array),然后判断@Order,@Priority 等排序方法的优先级
(5)@Order 注解分析
@Order 注解没有什么内容,可以作用于类和方法,具体的源码如下,就只有一个 value 值(排序值),默认值为优先级最低
package org.springframework.core.annotation;
import org.springframework.core.Ordered;
import java.lang.annotation.*;
/**
* 组件的排序顺序注解,可选注解
*
* @author Rod Johnson
* @author Juergen Hoeller
* @see org.springframework.core.Ordered
* @see AnnotationAwareOrderComparator
* @see OrderUtils
* @see javax.annotation.Priority
* @since 2.0
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
/**
* 排序值:默认最低
*
* @see Ordered#getOrder()
*/
int value() default Ordered.LOWEST_PRECEDENCE;
}
(6)Spring 执行顺序小结
类名/接口名/注解名 | 说明 |
---|---|
PriorityOrdered 接口 | 实现了 Ordered 接口,优先级最高 |
Ordered 接口 | 优先级比普通类高 |
OrderComparator 类 | 对需要排序的数组或集合排序 |
AnnotationAwareOrderComparator 类 | 对需要排序的数组或集合排序 |
@Order 注解 | 通过制定 value 值(排序值),确定顺序 |
2、Spring 执行顺序排序测试案例
准备测试工具,万变不离其中,一个扫描配置类,一个测试类,香瓜你的测试类写在扫描包的规则下即可
import org.springframework.context.annotation.ComponentScan;
/**
* 扫描配置类
*
* @author Tellsea
* @date 2020-8-18
*/
@ComponentScan("cn.tellsea.ordered")
public class OrderedConfig {
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 测试类
*
* @author Tellsea
* @date 2020-8-18
*/
public class OrderedTest {
public static void main(String[] args) {
// 创建IOC容器
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderedConfig.class);
}
}
(1)Ordered 测试类
创建测试类 OrderedOne,并实现 Ordered 接口,然后重新 getOrder 方法, 设置排序值为最低
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
/**
* @author Tellsea
* @date 2020-8-18
*/
@Configuration
public class OrderedOne implements Ordered {
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
创建测试类 OrderedOne,并实现 Ordered 接口,然后重新 getOrder 方法, 设置排序值为最高
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
/**
* @author Tellsea
* @date 2020-8-18
*/
@Configuration
public class OrderedTwo implements Ordered {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
测试类中, 通过 applicationContext 拿到两个 bean,默认情况下,他们的加载顺序是 OrderedOne > OrderedTwo,但是我们实现了 Ordered 并重写了 getOrder,将第一个的排序值设置为最低,第二个的排序值设置为最高,意思就是 OrderedOne < OrderedTwo 反过来
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.OrderComparator;
import java.util.ArrayList;
import java.util.List;
/**
* 测试类
*
* @author Tellsea
* @date 2020-8-18
*/
public class OrderedTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderedConfig.class);
List<Object> list = new ArrayList<>();
list.add(applicationContext.getBean(OrderedOne.class));
list.add(applicationContext.getBean(OrderedTwo.class));
System.out.println("OrderComparator.sort ... 之前");
for (Object obj : list) {
System.out.println(obj);
}
OrderComparator.sort(list);
System.out.println("OrderComparator.sort ... 之后");
for (Object obj : list) {
System.out.println(obj);
}
}
}
测试成功
OrderComparator.sort ... 之前
cn.tellsea.ordered.OrderedOne$$EnhancerBySpringCGLIB$$47a00dd9@2c767a52
cn.tellsea.ordered.OrderedTwo$$EnhancerBySpringCGLIB$$425a107f@619713e5
OrderComparator.sort ... 之后
cn.tellsea.ordered.OrderedTwo$$EnhancerBySpringCGLIB$$425a107f@619713e5
cn.tellsea.ordered.OrderedOne$$EnhancerBySpringCGLIB$$47a00dd9@2c767a52
(2)PriorityOrdered 测试类
创建测试类 PriorityOrderedOne,并实现 PriorityOrdered 接口,然后重新 getOrder 方法, 设置排序值为最低
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
/**
* @author Tellsea
* @date 2020-8-18
*/
@Configuration
public class PriorityOrderedOne implements PriorityOrdered {
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
}
创建测试类 PriorityOrderedTwo,并实现 PriorityOrdered 接口,然后重新 getOrder 方法, 设置排序值为最高
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
/**
* @author Tellsea
* @date 2020-8-18
*/
@Configuration
public class PriorityOrderedTwo implements PriorityOrdered {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
测试类中, 通过 applicationContext 拿到两个 bean,默认情况下,他们的加载顺序是 PriorityOrderedOne > PriorityOrderedTwo,但是我们实现了 PriorityOrdered 并重写了 getOrder,将第一个的排序值设置为最低,第二个的排序值设置为最高,意思就是 PriorityOrderedOne < PriorityOrderedTwo 反过来
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.OrderComparator;
import java.util.ArrayList;
import java.util.List;
/**
* 测试类
*
* @author Tellsea
* @date 2020-8-18
*/
public class PriorityOrderedTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderedConfig.class);
List<Object> list = new ArrayList<>();
list.add(applicationContext.getBean(PriorityOrderedOne.class));
list.add(applicationContext.getBean(PriorityOrderedTwo.class));
System.out.println("OrderComparator.sort ... 之前");
for (Object obj : list) {
System.out.println(obj);
}
OrderComparator.sort(list);
System.out.println("OrderComparator.sort ... 之后");
for (Object obj : list) {
System.out.println(obj);
}
}
}
测试成功
OrderComparator.sort ... 之前
cn.tellsea.ordered.PriorityOrderedOne$$EnhancerBySpringCGLIB$$ba67371d@2c767a52
cn.tellsea.ordered.PriorityOrderedTwo$$EnhancerBySpringCGLIB$$b52139c3@619713e5
OrderComparator.sort ... 之后
cn.tellsea.ordered.PriorityOrderedTwo$$EnhancerBySpringCGLIB$$b52139c3@619713e5
cn.tellsea.ordered.PriorityOrderedOne$$EnhancerBySpringCGLIB$$ba67371d@2c767a52
(3)@Order 接口测试类
定义两个 bean,并设置@Order 的 value 一个为最高,一个为最低,最低的不用设置值,默认就是最低值
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* @author Tellsea
* @date 2020-8-19
*/
@Order
@Configuration
public class OrderOne {
}
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* @author Tellsea
* @date 2020-8-19
*/
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
public class OrderTwo {
}
测试类排序分析
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.OrderComparator;
import java.util.ArrayList;
import java.util.List;
/**
* @author Tellsea
* @date 2020-8-19
*/
public class OrderTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(OrderedConfig.class);
List<Object> list = new ArrayList<>();
list.add(applicationContext.getBean(OrderOne.class));
list.add(applicationContext.getBean(OrderedTwo.class));
System.out.println("OrderComparator.sort ... 之前");
for (Object obj : list) {
System.out.println(obj);
}
OrderComparator.sort(list);
System.out.println("OrderComparator.sort ... 之后");
for (Object obj : list) {
System.out.println(obj);
}
}
}
OrderComparator.sort ... 之前
cn.tellsea.ordered.OrderOne$$EnhancerBySpringCGLIB$$4995dc95@20ce78ec
cn.tellsea.ordered.OrderedTwo$$EnhancerBySpringCGLIB$$184c23dc@393671df
OrderComparator.sort ... 之后
cn.tellsea.ordered.OrderedTwo$$EnhancerBySpringCGLIB$$184c23dc@393671df
cn.tellsea.ordered.OrderOne$$EnhancerBySpringCGLIB$$4995dc95@20ce78ec
(4)使用多种排序方式测试
到点了,下班