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 ;
public interface Ordered {
int HIGHEST_PRECEDENCE = -2147483648;
int LOWEST_PRECEDENCE = 2147483647;
int getOrder();
}
3.创建BlackPersion、YellowPersion类,这两个类都实现CommandLineRunner
实现CommandLineRunner接⼝的类会在Spring IOC容器加载完毕后执⾏,适合预加载类及其它资源;也可以使⽤ApplicationRunner,使⽤⽅法及效果是⼀样的
package der;
import org.springframework.boot.CommandLineRunner;
import 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 args) throws Exception {
System.out.println("----BlackPersion----");
spring framework}
}
package der;
import org.springframework.boot.CommandLineRunner;
import 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 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 args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
SpringApplicationRunListeners listeners = RunListeners(args);
listeners.starting();
Collection exceptionReporters;
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
Banner printedBanner = this.printBanner(environment);
context = ateApplicationContext();
exceptionReporters = SpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
this.afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).ApplicationLog(), 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.BeansOfType(ApplicationRunner.class).values());
runners.BeansOfType(CommandLineRunner.class).values());
//重点来了,按照定义的优先级顺序排序
AnnotationAwareOrderComparator.sort(runners);
Iterator var4 = (new LinkedHashSet(runners)).iterator();
//循环调⽤具体⽅法
while(var4.hasNext()) {
Object runner = ();
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.SourceArgs());
} catch (Exception var4) {
throw new IllegalStateException("Failed to execute CommandLineRunner", var4);
}
}
到这⾥优先级类的⽰例及其执⾏原理都分析完毕;不过还是要强调下@Order、Ordered不影响类的加载顺序⽽是影响Bean加载如IOC容器之后执⾏的顺序(优先级);
个⼈理解是加载代码的底层要⽀持优先级执⾏程序,否则即使配置上Ordered、@Order也是不起任何作⽤的。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。