Spring源码必备-@Order排序详解

SSM-Project-Day07 AOP【切面排序@Order(1)数字越小优先级越高】 一、添加pom依赖 <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.9.RELEASE</version> ... 阅读详情

大家都知道Spring中可以使用@Order和@Priority来决定SpringBean的启动顺序,但是你知道他是怎么实现的吗?

下面我们就来看看Spring是怎么设计实现的。

一、如何使用

我们先看看Spring是如何使用的,然后再深入内部去看。

public class SpringApplication {
	private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
		ClassLoader classLoader = getClassLoader();
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
        //排序
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}
}

//进行排序的类
public class AnnotationAwareOrderComparator extends OrderComparator {
	public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
	public static void sort(List<?> list) {
		if (list.size() > 1) {
			list.sort(INSTANCE);
		}
	}
}

以上代码是SpringBoot启动刚开始的时候的一段代码,我加了注释的那行就是进行排序的。

该类的结构关系如下:

 Spring中排序使用的就是AnnotationAwareOrderComparator类,可以看出上层接口是Comparator,java的比较器我们都很熟悉了,这里就不多说了。

我们自己再写个小例子看看:

public class Test {
    public static void main(String[] args){
        List<A> list = new ArrayList<>();
        list.add(new A2());
        list.add(new A3());
        list.add(new A1());
        AnnotationAwareOrderComparator.sort(list);
        for (A a : list){
            a.say();
        }
    }
}

interface A{
    void say();
}
@Order(1)
class A1 implements A{
    public void say(){
        System.out.println(1);
    }
}
@Order(2)
class A2 implements A{
    public void say(){
        System.out.println(2);
    }
}
@Priority(3)
class A3 implements A{
    public void say(){
        System.out.println(3);
    }
}

以上代码写的是按不同顺序放入list,排序后,按照@Order和@Priority标注的顺序就行了排序。 

二、相关抽象类解释

Java是面向对象的语言,我们千万不能忘记这一点。我们可以把任何概念或者事物抽象成一个对象,Spring也不例外,所以,我们了解他的某一块功能,要先去了解Spring为了实现这个功能抽象出了哪些类。

2.1 @Order和@Priority

@Target({TYPE,PARAMETER})
@Retention(RUNTIME)
@Documented
public @interface Priority {
    int value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
	int value() default Ordered.LOWEST_PRECEDENCE;

}

这两个注解的区别就是,@Order有一个默认值,他两的标注范围也不同。

从之前的自己写的小例子也可以看出,这两个注解是被排序功能识别的,并不需要相关对象注入到Spring容器中。

2.2  查找策略SearchStrategy

Spring排序是实现了java的比较器Comparator,所以必须获取注解上表示大小的值。有查找就有了策略,是只查找当前类还是需要查找父类。

	enum SearchStrategy {
		/**
		 * 只查找当前类,不考虑@Inherited、父类和实现的接口
		 */
		DIRECT,
		/**
		 * 查找当前类和@Inherited,不查找父类和实现的接口
		 */
		INHERITED_ANNOTATIONS,
		/**
		 * 查找当前类和父类,不查找实现的接口
		 */
		SUPERCLASS,
		/**
		 * 查找当前类、父类、实现的接口
		 */
		TYPE_HIERARCHY,
		/**
		 * 在TYPE_HIERARCHY基础上还查找外部类(如果当前类是内部类)
		 */
		TYPE_HIERARCHY_AND_ENCLOSING_CLASSES
	}

 小知识:@Inherited 子类会继承父类的注解。实现类不会继承接口的注解、子接口不会继承父接口的注解

2.3 RepeatableContainers

 小知识:

@Repeatable:正常情况下同一个注解只能标注一次,而@Repeatable可以实现标注多次

如果出现下面这种情况,就得使用该类来解决了:

@Repeatable(persons.class)
@Order
@interface person{
    String value();
}

@interface persons{
    person[] value();
}

@persons({@person("a"), @person("b")})
class A{
}
@person("a")
@person("b")
class B{
}

 如果有自定义注解比如@person,那么获取A类的Order值就很麻烦了。RepeatableContainers就是做这个事的。它负责最终找出@Order注解。

2.4 注解过滤器AnnotationFilter

 这个类很简单,只有一个实现类,该类用来排除不需要查找的注解。

@FunctionalInterface
public interface AnnotationFilter {
	AnnotationFilter PLAIN = packages("java.lang", "org.springframework.lang");
	static AnnotationFilter packages(String... packages) {
		return new PackagesAnnotationFilter(packages);
	}
}

final class PackagesAnnotationFilter implements AnnotationFilter {
	@Override
	public boolean matches(String annotationType) {
		for (String prefix : this.prefixes) {
			if (annotationType.startsWith(prefix)) {
				return true;
			}
		}
		return false;
	}
}

如上代码,Spring中排除了java.lang和org.springframework.lang下的注解。

三、整个过程

整个排序过程,最重要也是最不容易阅读的代码就是查找Order值的过程,入口方法如下:

public class OrderComparator implements Comparator<Object> {
	@Nullable
	protected Integer findOrder(Object obj) {
		return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
	}
}

public class AnnotationAwareOrderComparator extends OrderComparator {	
    @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;
	}
}

首先调用父类方法,是否是Ordered接口的实现类,如果是,则直接调用方法获取值,如果不是则调用子方法。

子方法第一步首先获取Class对象。

AnnotatedElement是Class的父类。

第二步,查找前的准备工作。

第三步,从所有注解中过滤出order值。

第四部,如果找到直接返回,找不到并且是代理类的话,用目标对象再次走一遍刚才的流程。

代码中最重要的有2个

  • 查找前的准备工作。
  • OrderUtils类负责从注解中查找出order值。

3.1 准备工作

从静态方法from进入,我们可以看到初始化了以下内容:

  1. 策略选择的是TYPE_HIERARCHY
  2. 容器选择的是StandardRepeatableContainers
  3. Filter选择排除的是"java.lang", "org.springframework.lang"

3.2 过滤

这部分的代码量最大,这里不详细展开,大家可以自己简单看看,看的方法还是和之前一样,按功能模块看,不要从头到尾一直往下读。

	@Nullable
	private static Integer findOrder(MergedAnnotations annotations) {
		MergedAnnotation<Order> orderAnnotation = annotations.get(Order.class);
		if (orderAnnotation.isPresent()) {
			return orderAnnotation.getInt(MergedAnnotation.VALUE);
		}
		MergedAnnotation<?> priorityAnnotation = annotations.get(JAVAX_PRIORITY_ANNOTATION);
		if (priorityAnnotation.isPresent()) {
			return priorityAnnotation.getInt(MergedAnnotation.VALUE);
		}
		return null;
	}

以上为外层方法,看着很容易,调用MergedAnnotations的get方法先查找Order注解的值,有就返回,没有则查找javax.annotation.Priority注解的值。

四、总结

如果大家一边翻看源码,一边看本文,应该对Spring如何实现Order很了解了。

一个简单的Order,涉及到的代码和抽象概念都很多,包括了过滤、策略、Repeatable容器查找等,如果你详细看的话还会发现别的抽象接口,比如Finder什么的,不过那是更细节的代码了。


欢迎讨论交流

Spring框架中的@Order注解详解及应用实例 Order注解位于包中,它可以用来指定Bean的加载顺序。如果没有指定@Order,Spring默认的顺序是。 阅读详情

相关推荐

Spring框架中的@Order注解详解与实例

Order默认情况下,如果没有指定value属性,其值将为,表示Bean将被加载在最后。通过本文,我们了解了@Order注解在Spring框架中的重要性以及如何使用它来控制Bean的加载顺序。希望这些示例能帮助你在实际开发中更好地利用这一特性。

m0_62153576的博客 622

@order 注解用法

@order注解是spring-core包下的一个注解,@Order的作用是定义Spring IOC容器中Bean的执行顺序的优先级(这里的顺序也可以理解为存放到容器中的先后顺序)。开发过程当中有时候经常会出现配置依赖关系,例如注入A对象使用了@ConditionalOnBean(B.class),意思是要求容器当中必须存在B.class的实例的时候,才会进行注入A。这时候我们就必须保证B对象在注入A对象前进行注入。

怪咖@的博客 4万+

微信小程序网关逆向分析:从协议、签名到会话管理的安全架构剖析

在现代Web与移动应用开发中,API网关作为客户端与后端服务之间的关键通信枢纽,承担着协议转换、流量调度、安全防护与性能优化等核心职责。其工作原理通常涉及统一的请求路由、身份认证、参数校验与响应聚合。从技术价值看,深入理解网关机制不仅能帮助开发者构建更健壮、可扩展的微服务架构,还能为安全评估、性能调优与故障排查提供基础。在移动生态如微信小程序中,网关设计尤为关键,它需要处理微信特有的登录态、数据加密与防重放攻击等安全需求。本文聚焦于微信小程序网关的逆向分析方法,通过结合网络抓包与代码反编译技术,深入解析其通

weixin_29323493的博客 442

Spring(18) @Order注解介绍、使用、底层原理

Spring(18) @Order注解介绍、使用、底层原理

ACGkaka的博客 9821

保姆级教程:在DolphinScheduler 3.x中配置Apache SeaTunnel任务(Flink/Spark双引擎)

本文提供了一份详细的教程,指导如何在DolphinScheduler 3.x中配置Apache SeaTunnel任务,支持Flink和Spark双引擎。从环境准备、脚本选择到配置文件编写和任务调度优化,涵盖了所有关键步骤和常见问题解决方案,帮助用户高效集成SeaTunnel到海豚调度系统中。

weixin_42524945的博客 194

esp32c6 开发实战:低功耗蓝牙(BLE)开发

蓝牙栈在此程序流程中已经启动并运行,但是应用程序的功能尚未定义。功能的定义是通过响应事件来实现的,当其他设备尝试读取或写入参数以及建立连接时就会触发事件回调函数处理。BT控制器在控制器端实现主机控制器接口(HCI),链路层(LL)和物理层(PHY)。BT控制器对用户应用程序不可见,并处理BLE堆栈的较低层。蓝牙堆栈(Bluedroid stack)定义了经典蓝牙(BT Classic)和低功耗蓝牙(BLE)的通用定义和API。的判断)等对于启动低功耗蓝牙来说不重要的代码,函数初始化和启用BT控制器。

月入鱼饵的博客 2740

深入解析Spring Boot中的Bean加载顺序控制

在Spring Boot应用的启动过程中,Bean的加载顺序往往决定了系统初始化的成败。当容器需要初始化数百个相互依赖的Bean时,错误的加载顺序可能导致依赖注入失败、循环依赖甚至应用启动崩溃。特别是在2025年的现代微服务架构中,随着自动配置机制的广泛应用,理解并控制Bean加载顺序已成为高级开发者的必备技能。启动日志分析。

zuiyuelong的博客 1323

【Unity】Gif图片播放插件(支持UI及模型纹理渲染两种模式)

unity本身不支持GIF格式文件直接渲染, 因此一般的做法是通过加载图片,通过代码控制其循环播放、停止等,模拟动画效果,本文简单介绍一下某个现有开源工具,感谢开源作者。

灵境引路人 4036

Feign拦截器RequestInterceptor优先级实战指南

本文深入解析了Feign拦截器中RequestInterceptor的优先级排序机制。通过剖析其核心工作原理,详细介绍了PriorityOrdered接口、Ordered接口和@Order注解三大控制手段,并结合实战场景(如链路追踪、安全认证、请求签名)提供了多拦截器的编排策略与调试方法,帮助开发者避免因执行顺序混乱导致的常见生产问题。

sam99的博客 419

黑猫带你学eMMC协议第22篇:emmc可靠写详解(Write Reliability)

1 前言 1.1 声明 本文依据eMMC JEDEC5.1、网络资料及个人工作经验整理而成,如有部分错误请留言。 本文部分内容可能源自网络,侵删。 本文结合eMMC JEDEC5.1协议手册查看效果更佳。 1.2 内容提要 1、什么是可靠性写属性(Write Reliability)? 2、可靠写和普通的写有什么区别? 3、设置可靠写的流程及流程框图。 4、可靠写需要遵循哪些规则? 1.3 参考链接 本文主要参考链接:http://www.up48.com/cn/support/8_37.html 2 什么

黑猫奥利奥的博客 3118

【软件系统架构】系列六:MBSE(基于模型的系统工程)

基于模型的系统工程(MBSE)是一种以模型为核心的系统工程方法论,通过结构化、可视化的模型取代传统文档,实现从需求到验证的全生命周期管理。MBSE采用SysML建模语言,包含需求、功能、架构和验证四大要素,支持自动追踪、仿真分析和代码生成。相比文档式工程,MBSE具有变更影响自动分析、跨团队协作和高可视化等优势,广泛应用于航空航天、汽车电子等领域。典型开发流程包括需求建模、行为建模、架构建模等阶段,配合MagicDraw、Cameo等工具链实现。MBSE正与数字孪生、AI技术融合,推动自动化建模和智能验证的

moton2017的博客 2782

深入分析Spring的@Order注解

一文让你理解Spring中的@Order注解的作用。

L的博客 4851

YOLOv11改进策略【Head/分割头】| 结合CVPR-2024 中的DynamicConv 动态卷积 改进分割头, 优化模型(独家改进)

在大规模视觉预训练中,通常模型的性能受到数据、参数和FLOP三个关键因素的影响。一般来说,模型的参数数量越多,FLOP也越高,但在移动设备等对计算资源有限制的场景下,需要低FLOP的模型同时又希望模型能从大规模预训练中受益。传统的方法很难在增加参数的同时保持低FLOP,因此需要一种新的设计来解决这个问题,模块应运而生。

Limiiiing的博客 2310

Java注解篇:@Order

@Order注解在Spring框架中用于定义组件的排序优先级,值越小优先级越高。它不控制Bean的加载或实例化顺序,而是影响执行或注入时的顺序。

x² 2737

AutoSAR系列讲解(实践篇)9.5-通信的数据映射

讲解了AppL中的数据与通信中的Signal的一个映射操作

雪云飞星的博客 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【java知识点】常用注解解析

【java知识点】常用注解解析

等待中的小码农 3142

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Spring注解--@Order--使用/实例

本文用示例介绍@Order(顺序)注解的用法。

IT利刃出鞘的博客 4995

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

springboot注解@Order的使用

使用order属性,设置该类在spring容器中的加载顺序 例如有三个类:Order1,Order2,Order3,其中Order1类如下: @Component //把类交给spring容器管理 @Order(1) //使用order属性,设置该类在spring容器中的加载顺序 public class Order1{ private final int ORDERED = 1; ...

zhizhuodewo6的博客 2万+

浅谈Spring @Order注解的使用

注解@Order的作用是定义Spring容器加载Bean的顺序,接下来我们通过分析源码和示例测试详细的学习。 1.@Order的注解源码解读 注解类: @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @i...

OceanSky的专栏 20万+

注解详解系列 - @Order:控制Bean加载顺序

在今天的注解详解系列中,我们将探讨@Order注解。@Order是Spring框架中的一个重要注解,用于控制Spring容器中Bean的加载顺序。通过@Order注解,可以指定多个Bean的优先级,从而决定它们的执行或加载顺序。@Order注解用于定义Spring容器中Bean的加载顺序。它可以应用于类级别或方法级别,通常与实现了Ordered接口的类一起使用。

算命de博客 1759

Spring | @Order 与 Ordered 控制加载顺序

阐述了 @Order 与 Ordered 的区别, 使用方式, 以及@Order源码 是在哪里进行控制顺序的

苏老师的博客 4049

Spring Boot 中优雅地使用责任链模式(@Order 实战)

摘要:当业务逻辑中的if-else判断过多时,责任链模式是最佳解决方案。本文介绍了如何利用Spring Boot的@Order注解实现责任链模式,将复杂的业务流程分解为多个独立处理单元。通过定义Handler接口、Context对象和Chain执行器,配合@Order控制执行顺序,可以有效消除冗长的if-else结构,使代码更清晰、可维护性更强。这种模式特别适合导出流程、审批流等场景,让复杂业务逻辑像流水线一样清晰可控。

Knight 1227

@Order注解使用

注解@Order或者接口Ordered的作用是定义Spring IOC容器中Bean的执行顺序的优先级,而不是定义Bean的加载顺序,Bean的加载顺序不受@Order或Ordered接口的影响 1.@Order的注解源码解读 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD}) @Documented public @interface Order {

吾心即悟的博客 2356

Spring 框架中 @Order 注解:使用教程、原理剖析与应用场景

它通过定义优先级来影响Bean在集合中的注入顺序、切面的执行顺序以及特定扩展点(如过滤器、监听器)的排序。它通过定义优先级来影响Bean在集合中的注入顺序、切面的执行顺序以及特定扩展点(如过滤器、监听器)的排序。,可以确保Spring应用的组件按预期协同工作,提升系统的可维护性和稳定性。,可以确保Spring应用的组件按预期协同工作,提升系统的可维护性和稳定性。是Spring框架中实现组件排序的核心工具,其核心价值在于。是Spring框架中实现组件排序的核心工具,其核心价值在于。等注解解决复杂的顺序问题。

qq_35800459的博客 1785

@Order 注解

@Order 注解 @Order注解主要用来控制配置类的加载顺序 示例代码: package com.runlion.tms.admin.constant; public class AService { } package com.runlion.tms.admin.constant; public class BService { } package com.runlion....

优质后端技术知识记录 1万+

spring boot @Order 注解的使用场景

在中,@Order注解用于定义或的优先级顺序。它可以应用于过滤器、切面(Aspect)、监听器或其他需要顺序执行的组件。@Order注解来源于,其值为整数,表示顺序的优先级,值越小优先级越高(即最小的值会最先执行)。@Order。

学亮编程手记 1543
上一篇: 读Spring源码必备-资源访问
下一篇: Spring源码阅读之PropertySource
七号公园的忧伤
七号公园的忧伤 新星创作者: Java技术领域 新星创作者: Java技术领域
博客等级 码龄6年 4857粉丝 79原创
评论 10
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

打赏作者

七号公园的忧伤

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

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

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

打赏作者

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

抵扣说明:

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

余额充值