浅谈Spring @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 {/*** 默认是最低优先级,值越小优先级越高*/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注解的使用相关推荐
- 浅谈Spring框架注解的用法分析
1.@Component是Spring定义的一个通用注解,可以注解任何bean. 2.@Scope定义bean的作用域,其默认作用域是"singleton",除此之外还有proto ...
- 浅谈 Spring 框架注解的用法分析
1.@Component是Spring定义的一个通用注解,可以注解任何bean. 2.@Scope定义bean的作用域,其默认作用域是"singleton",除此之外还有proto ...
- 浅谈:Spring Boot原理分析,切换内置web服务器,SpringBoot监听项目(使用springboot-admin),将springboot的项目打成war包
浅谈:Spring Boot原理分析(更多细节解释在代码注释中) 通过@EnableAutoConfiguration注解加载Springboot内置的自动初始化类(加载什么类是配置在spring.f ...
- 浅谈 Spring IOC
浅谈 Spring IOC 什么是IOC 理解 IOC 和 DI Spring IOC 相关操作个人总结 什么是IOC Ioc-Inversion of Control,即"控制反转&quo ...
- 浅谈Spring定时任务
浅谈Spring定时任务 三种定时任务基于原理 多定时任务并发配置 动态定时任务 定时任务Demo 三种定时任务基于原理 SpringBoot配置定时任务主要有Spring Schedule.JDK自 ...
- 浅谈Spring IOC的理解
浅谈Spring IOC的理解 学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊 ...
- 浅谈 Spring IOC和AOP
浅谈 Spring IOC和AOP IOC 控制反转 以前创建对象的主动权和时机是由于自己把握的,现在将这种权利转移到Spring容器中,并且根据配置文件去创建对象管理对象 ioc的注入方式有三种:构 ...
- 由openSession、getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持
由openSession.getCurrentSession和HibernateDaoSupport浅谈Spring对事物的支持 Spring和Hibernate的集成的一个要点就是对事务的支持,op ...
- 浅谈Spring IOC和DI及Spring工厂类
浅谈Spring IOC和DI及Spring的工厂类 文章目录 浅谈Spring IOC和DI及Spring的工厂类 一. IOC 1.什么是IOC 2.为什么使用IOC 传统开发模式的弊端 3. 使 ...
- 浅谈Spring注解
Spring目前的趋势是使用注解结合Java代码而不是配置来定义行为.属性.功能.规则和扩展点,因此梳理注解也是梳理Spring功能点的很好的方式,全面的梳理可以补足我们知识点的漏洞. 查找所有注解 ...
最新文章
- IOS开发笔记8-C语言基础复习
- 01_基于应用拆分的技术架构
- [LOJ#2270][BZOJ4912][SDOI2017]天才黑客
- CGCTF-Web-md5 collision
- mysql 查找配置文件 my.ini 位置方法
- CBT的完整形式是什么?
- 2019年网络规划设计师下午真题及答案解析
- Android 进程间通信——AIDL
- ftk学习记(多窗口篇)
- ssis 派生列_SSIS脚本组件与派生列
- 学校年检计算机台账,学校年检整改报告.docx
- linux不能上网问题
- 初学Laravel框架与ThinkPHP框架的不同
- java并发包原理及使用场景
- unityar自动识别人脸_Unity2019.2 Beta版:支持AR面部追踪和3D物体识别
- 海康4200服务器进不去系统,ivms-4200客户端登入不了云服务器
- 网络协议学习--SOAP协议(二)
- web 系统原理之路由器和交换机的区别
- THREE将左键改为平移右键改为旋转
- html标签的记忆巧法,小学记忆单词的方法