注解@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 {/*** 默认是最低优先级,值越小优先级越高*/int value() default Ordered.LOWEST_PRECEDENCE;}
  • 注解可以作用在类(接口、枚举)、方法、字段声明(包括枚举常量);
  • 注解有一个int类型的参数,可以不传,默认是最低优先级;
  • 通过常量类的值我们可以推测参数值越小优先级越高;

2.Ordered接口类

package org.springframework.core;public interface Ordered {int HIGHEST_PRECEDENCE = -2147483648;int LOWEST_PRECEDENCE = 2147483647;int getOrder();
}

3.创建BlackPersion、YellowPersion类,这两个类都实现CommandLineRunner

实现CommandLineRunner接口的类会在Spring IOC容器加载完毕后执行,适合预加载类及其它资源;也可以使用ApplicationRunner,使用方法及效果是一样的

package com.yaomy.common.order;import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** @Description: Description* @ProjectName: spring-parent* @Version: 1.0*/
@Component
@Order(1)
public class BlackPersion implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("----BlackPersion----");}
}
package com.yaomy.common.order;import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;/*** @Description: Description* @ProjectName: spring-parent* @Version: 1.0*/
@Component
@Order(0)
public class YellowPersion implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {System.out.println("----YellowPersion----");}
}

4.启动应用程序打印出结果

----YellowPersion----
----BlackPersion----

我们可以通过调整@Order的值来调整类执行顺序的优先级,即执行的先后;当然也可以将@Order注解更换为Ordered接口,效果是一样的

5.到这里可能会疑惑IOC容器是如何根据优先级值来先后执行程序的,那接下来看容器是如何加载component的

  • 看如下的启动main方法
@SpringBootApplication
public class CommonBootStrap {public static void main(String[] args) {SpringApplication.run(CommonBootStrap.class, args);}
}

这个不用过多的解释,进入run方法…

public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();this.configureHeadlessProperty();SpringApplicationRunListeners listeners = this.getRunListeners(args);listeners.starting();Collection exceptionReporters;try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);this.configureIgnoreBeanInfo(environment);Banner printedBanner = this.printBanner(environment);context = this.createApplicationContext();exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);this.refreshContext(context);this.afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);}listeners.started(context);//这里是重点,调用具体的执行方法this.callRunners(context, applicationArguments);} catch (Throwable var10) {this.handleRunFailure(context, var10, exceptionReporters, listeners);throw new IllegalStateException(var10);}try {listeners.running(context);return context;} catch (Throwable var9) {this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);throw new IllegalStateException(var9);}}private void callRunners(ApplicationContext context, ApplicationArguments args) {List<Object> runners = new ArrayList();runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());//重点来了,按照定义的优先级顺序排序AnnotationAwareOrderComparator.sort(runners);Iterator var4 = (new LinkedHashSet(runners)).iterator();//循环调用具体方法while(var4.hasNext()) {Object runner = var4.next();if (runner instanceof ApplicationRunner) {this.callRunner((ApplicationRunner)runner, args);}if (runner instanceof CommandLineRunner) {this.callRunner((CommandLineRunner)runner, args);}}}private void callRunner(ApplicationRunner runner, ApplicationArguments args) {try {//执行方法runner.run(args);} catch (Exception var4) {throw new IllegalStateException("Failed to execute ApplicationRunner", var4);}}private void callRunner(CommandLineRunner runner, ApplicationArguments args) {try {//执行方法runner.run(args.getSourceArgs());} catch (Exception var4) {throw new IllegalStateException("Failed to execute CommandLineRunner", var4);}}

到这里优先级类的示例及其执行原理都分析完毕;不过还是要强调下@Order、Ordered不影响类的加载顺序而是影响Bean加载如IOC容器之后执行的顺序(优先级);

个人理解是加载代码的底层要支持优先级执行程序,否则即使配置上Ordered、@Order也是不起任何作用的,
个人的力量总是很微小的,欢迎大家来讨论,一起努力成长!!

GitHub源码:https://github.com/mingyang66/spring-parent

浅谈Spring @Order注解的使用相关推荐

  1. 浅谈Spring框架注解的用法分析

    1.@Component是Spring定义的一个通用注解,可以注解任何bean. 2.@Scope定义bean的作用域,其默认作用域是"singleton",除此之外还有proto ...

  2. 浅谈 Spring 框架注解的用法分析

    1.@Component是Spring定义的一个通用注解,可以注解任何bean. 2.@Scope定义bean的作用域,其默认作用域是"singleton",除此之外还有proto ...

  3. 浅谈:Spring Boot原理分析,切换内置web服务器,SpringBoot监听项目(使用springboot-admin),将springboot的项目打成war包

    浅谈:Spring Boot原理分析(更多细节解释在代码注释中) 通过@EnableAutoConfiguration注解加载Springboot内置的自动初始化类(加载什么类是配置在spring.f ...

  4. 浅谈 Spring IOC

    浅谈 Spring IOC 什么是IOC 理解 IOC 和 DI Spring IOC 相关操作个人总结 什么是IOC Ioc-Inversion of Control,即"控制反转&quo ...

  5. 浅谈Spring定时任务

    浅谈Spring定时任务 三种定时任务基于原理 多定时任务并发配置 动态定时任务 定时任务Demo 三种定时任务基于原理 SpringBoot配置定时任务主要有Spring Schedule.JDK自 ...

  6. 浅谈Spring IOC的理解

    浅谈Spring IOC的理解 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊 ...

  7. 浅谈 Spring IOC和AOP

    浅谈 Spring IOC和AOP IOC 控制反转 以前创建对象的主动权和时机是由于自己把握的,现在将这种权利转移到Spring容器中,并且根据配置文件去创建对象管理对象 ioc的注入方式有三种:构 ...

  8. 由openSession、getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持

    由openSession.getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持 Spring和Hibernate的集成的一个要点就是对事务的支持,op ...

  9. 浅谈Spring IOC和DI及Spring工厂类

    浅谈Spring IOC和DI及Spring的工厂类 文章目录 浅谈Spring IOC和DI及Spring的工厂类 一. IOC 1.什么是IOC 2.为什么使用IOC 传统开发模式的弊端 3. 使 ...

  10. 浅谈Spring注解

    Spring目前的趋势是使用注解结合Java代码而不是配置来定义行为.属性.功能.规则和扩展点,因此梳理注解也是梳理Spring功能点的很好的方式,全面的梳理可以补足我们知识点的漏洞. 查找所有注解 ...

最新文章

  1. IOS开发笔记8-C语言基础复习
  2. 01_基于应用拆分的技术架构
  3. [LOJ#2270][BZOJ4912][SDOI2017]天才黑客
  4. CGCTF-Web-md5 collision
  5. mysql 查找配置文件 my.ini 位置方法
  6. CBT的完整形式是什么?
  7. 2019年网络规划设计师下午真题及答案解析
  8. Android 进程间通信——AIDL
  9. ftk学习记(多窗口篇)
  10. ssis 派生列_SSIS脚本组件与派生列
  11. 学校年检计算机台账,学校年检整改报告.docx
  12. linux不能上网问题
  13. 初学Laravel框架与ThinkPHP框架的不同
  14. java并发包原理及使用场景
  15. unityar自动识别人脸_Unity2019.2 Beta版:支持AR面部追踪和3D物体识别
  16. 海康4200服务器进不去系统,ivms-4200客户端登入不了云服务器
  17. 网络协议学习--SOAP协议(二)
  18. web 系统原理之路由器和交换机的区别
  19. THREE将左键改为平移右键改为旋转
  20. html标签的记忆巧法,小学记忆单词的方法

热门文章

  1. arduino 读取模拟电压_【Arduino官方教程】基础示例(六):读取模拟电压
  2. Customer类的设计
  3. 某同学:1年经验和1本软考证书,很迷茫~
  4. 吃PHP小孩智力好,毁掉孩子智商的4类食物  别再给孩子吃了!
  5. 笔记本电脑只能外放,插上耳机还是外放
  6. KY-RTI分布仿真技术:第一章 简介
  7. C语言---用筛选法求100以内的素数
  8. 程序员为什么要会用Google谷歌搜索引擎
  9. Ttest + 秩和检验
  10. QT 对话框不在任务栏显示