【Spring源码分析】5、Spring 组件的执行顺序排序,相关排序类源码分析

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)使用多种排序方式测试

到点了,下班

3、更多细节学习

技术分享区

在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Tellsea

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值