浅谈Spring @Order注解的使用(转)
2024-09-05 09:18:27
注解@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 {
@Override
public 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 {
@Override
public 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容器之后执行的顺序(优先级);
- 原文地址:https://blog.csdn.net/yaomingyang/article/details/86649072
最新文章
- WCF学习之旅——第一个WCF示例(三)
- Adapter 代码中启动报错
- iOS 学习 - 12.NSMutableAttributedString 计算高度
- [转]删除SQL Server Management Studio中保存的帐户信息
- Linux中断(interrupt)子系统
- 用Cookie记住上次登录用户名
- Castle扩展Ibatis.Net
- UIButton 中高亮取消
- Python的可变类型与不可变类型
- [ Java面试题 ] 框架篇
- SAP主数据文件版本号命名规范
- 口试C#概念
- C++实现 电子邮件客户端程序(简易版)
- htmlElement.style 是只读属性
- 怎样使用EOS.JS的API
- python创建目录保存文件
- WP调用api
- [笔记] Ubuntu 18.04安装Docker CE及nvidia-docker2流程
- [转]解读Unity中的CG编写Shader系列4——unity中的圆角矩形shader
- GO语言(七)多核并行化的问题
热门文章
- 二叉树(Java实现)
- 【sublime Text】sublime Text3安装可以使xml格式化的插件
- Neo4j图数据库配置文件详解
- 修改hosts文件 解决coursera可以登录但无法播放视频的问题
- shell、bash、terminal和kernel之间的关系
- LeetCode 腾讯精选50题--最小栈
- [git] Updates were rejected because the tip of your current branch is behind its remote counterpart.
- vue入门:(底层渲染实现render函数、实例生命周期)
- 卡尔曼(Kalman)滤波及十种数据采集滤波的方法和编程实例
- Delphi 使用数据库浏览器