窥探-spring boot启动运行ApplicationRunner与CommandLineRunner
如果需要在spring boot运行启动之后运行指定的代码,可以使用两个接口, ApplicationRunner, CommandLineRunner.实现这两个接口的类,需要实现run方法,运行指定的逻辑代码。
简单使用
创建一个项目工程,项目结构如图:
MyApplicationRunner.java是实现了ApplicationRunner和Ordered接口,Ordered接口是进行相关的启动排序的,后面我们运行的时候可以看到这个字段的作用。同时也可以使用@Order注解进行顺序的操作。
使用Order注解的方式:
CommondLineRunner的相关操作是一样的.
使用注解的方式:
启动类:
我们运行工程:
我们可以看到当项目启动成功之后,就会按照order的顺序去运行ApplicationRunner和CommondLineRunner。
窥探ApplicationRunner和CommondLineRunner的运行
我们值spring的运行入口为run方法,我们进入看看看看调用runner的方法在哪里?
以上是调用callRunner(context,applicationArguments)方法进行操作的
进入callRunner方法:
我们可以看出,调用的时候,是将ApplicationRunner和CommondLineRunner统一放在一个ArrayList中,之后通过调用order的比较排序,之后遍历list中的runner进行类型判断进行执行相关的操作。
Order排序
AnnotationAwareOrderComparator类中的sort方法:
通过排序INSTANCE,INSTANCE是AnnotationAwareOrderComparator对象,这个对象继承了OrderComparator,这个类实现了Comparator接口.
排序是排序当前的实例,我们看看findOrder方法,获取order的方法
通过上面可以看出一个是通过findOrder或者通过注解的方法获得。
通过注解方法获取:
普通的获取方法调用父类的findOrder
获取相关的order
/**
* 确定给定对象的order值。默认实现使用findOrder与给定的 OrderSourceProvider进行比较,并回退到常规的getOrder(Object)调用。obj对象 检查@返回order值,或Ordered.LOWEST_PRECEDENCE作为后备
*/
private int getOrder(@Nullable Object obj, @Nullable OrderSourceProvider sourceProvider) {
Integer order = null;
if (obj != null && sourceProvider != null) {
Object orderSource = sourceProvider.getOrderSource(obj);
if (orderSource != null) {
if (orderSource.getClass().isArray()) {
Object[] sources = ObjectUtils.toObjectArray(orderSource);
for (Object source : sources) {
order = findOrder(source);
if (order != null) {
break;
}
}
}
else {
order = findOrder(orderSource);
}
}
}
return (order != null ? order : getOrder(obj));
}
/**
确定给定对象的order值。默认实现通过委派给findOrder来检查Ordered接口。 可以在子类中覆盖。obj对象,以检查@返回order值,或将 Ordered.LOWEST_PRECEDENCE作为后备
*/
protected int getOrder(@Nullable Object obj) {
if (obj != null) {
Integer order = findOrder(obj);
if (order != null) {
return order;
}
}
return Ordered.LOWEST_PRECEDENCE;
}
加载相关的orderBean是通过getOrderSource进行的,这个实现在FactoryAwareOrderSourceProvider类中,获取相关的orderSource
总结
在我们想在springboot启动只有就运行指定的代码,可以使用指定类去实现ApplicationRunner或者CommondLineRunner,ApplicationRunner和CommondLineRunner获取的参数是不一样的,运行的参数:ApplicationRunner是运行的args,但是CommondLineRunner的参数是选项参数,及‘–‘开头的运行参数。
之后如果想将指定的运行的顺序进行排序,可以实现Ordered接口getOrder方法设置顺序或者在指定的类上使用@Order(顺序值)注解