前言
一般專案中的初始化操作,初次遇見,妙不可言,如果你還有哪些方式可用于初始化操作,歡迎在評論中分享出來~
ApplicationRunner 和 CommandLineRunner
Spring Boot 應用,在啟動的時候,如果想做一些事情,比如預先加載并快取某些資料,讀取某些配置等等,總而言之,做一些初始化的操作時,那么 Spring Boot 就提供了兩個介面幫助我們實作,
這兩個介面是:
- ApplicationRunner 介面
- CommandLineRunner 介面
原始碼如下:
ApplicationRunner
package org.springframework.boot;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* Interface used to indicate that a bean should <em>run</em> when it is contained within
* a {@link SpringApplication}. Multiple {@link ApplicationRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
*
* @author Phillip Webb
* @since 1.3.0
* @see CommandLineRunner
*/
@FunctionalInterface
public interface ApplicationRunner {
/**
* Callback used to run the bean.
* @param args incoming application arguments
* @throws Exception on error
*/
void run(ApplicationArguments args) throws Exception;
}
CommandLineRunner
package org.springframework.boot;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
/**
* Interface used to indicate that a bean should <em>run</em> when it is contained within
* a {@link SpringApplication}. Multiple {@link CommandLineRunner} beans can be defined
* within the same application context and can be ordered using the {@link Ordered}
* interface or {@link Order @Order} annotation.
* <p>
* If you need access to {@link ApplicationArguments} instead of the raw String array
* consider using {@link ApplicationRunner}.
*
* @author Dave Syer
* @since 1.0.0
* @see ApplicationRunner
*/
@FunctionalInterface
public interface CommandLineRunner {
/**
* Callback used to run the bean.
* @param args incoming main method arguments
* @throws Exception on error
*/
void run(String... args) throws Exception;
}
可以看到,這兩個介面的注釋幾乎一模一樣,如出一轍,大致的意思就是,這兩個介面可以在 Spring 的環境下指定一個 Bean 運行(run)某些你想要做的事情,如果你有多個 Bean 進行指定,那么可以通過 Ordered 介面或者 @Order 注解指定執行順序,
說白了,就是可以搞多個實作類實作這兩個介面,通過 @Order 確定實作類的誰先運行,誰后運行,
@Order
再看看 @Order 注解的原始碼:
/**
* {@code @Order} defines the sort order for an annotated component.
*
* <p>The {@link #value} is optional and represents an order value as defined in the
* {@link Ordered} interface. Lower values have higher priority. The default value is
* {@code Ordered.LOWEST_PRECEDENCE}, indicating lowest priority (losing to any other
* specified order value).
* ..... 省略剩下的注釋
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
@Documented
public @interface Order {
/**
* The order value.
* <p>Default is {@link Ordered#LOWEST_PRECEDENCE}.
* @see Ordered#getOrder()
*/
int value() default Ordered.LOWEST_PRECEDENCE;
}
Ordered.LOWEST_PRECEDENCE 的默認值是 Integer.MAX_VALUE,
在頂部的注釋中,可以知道,@Order 注解是給使用了 @Component 注解的 Bean 定義排序順序(defines the sort order for an annotated component),然后 @Order 注解的 value 屬性值越低,那么代表這個 Bean 有著更高的優先級(Lower values have higher priority),
測驗
分別寫兩個實作類,實作這兩個介面,然后啟動 Spring Boot 專案,看看執行順序
ApplicationRunnerImpl:
@Slf4j
@Component
public class ApplicationRunnerImpl implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
log.info("我正在加載 ------------------> ApplicationRunnerImpl");
}
}
CommandLineRunnerImpl:
@Slf4j
@Component
public class CommandLineRunnerImpl implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("我正在加載 ------------------> CommandLineRunnerImpl");
}
}
控制臺輸出:
2023-03-26 15:46:38.344 INFO 25616 --- [ main] c.g.demo.init.ApplicationRunnerImpl : 我正在加載 ------------------> ApplicationRunnerImpl
2023-03-26 15:46:38.344 INFO 25616 --- [ main] c.g.demo.init.CommandLineRunnerImpl : 我正在加載 ------------------> CommandLineRunnerImpl
可以看到,是 ApplicationRunnerImpl 先運行的,CommandLineRunnerImpl 后運行的,
我們給 CommandLineRunnerImpl 加上 @Order 注解,給其 value 屬性設定 10:
@Slf4j
@Order(10)
@Component
public class CommandLineRunnerImpl implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
log.info("我正在加載 ------------------> CommandLineRunnerImpl");
}
}
控制臺輸出:
2023-03-26 15:50:43.524 INFO 16160 --- [ main] c.g.demo.init.CommandLineRunnerImpl : 我正在加載 ------------------> CommandLineRunnerImpl
2023-03-26 15:50:43.524 INFO 16160 --- [ main] c.g.demo.init.ApplicationRunnerImpl : 我正在加載 ------------------> ApplicationRunnerImpl
區別
回到這兩個介面,看似一模一樣,但肯定有小小區別的,最主要的區別就是介面的抽象方法的引數,
ApplicationRunner:
- void run(
ApplicationArguments args) throws Exception;
CommandLineRunner:
- void run(
String... args) throws Exception;
具體來說,ApplicationRunner 介面的 run 方法中的引數為 ApplicationArguments 物件,該物件封裝了應用程式啟動時傳遞的命令列引數和選項,
而 CommandLineRunner 介面的 run 方法中的引數為 String 陣列,該陣列直接包含了應用程式啟動時傳遞的命令列引數和選項,
測驗
列印下命令列引數:
@Slf4j
@Component
public class ApplicationRunnerImpl implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner: optionNames = " + args.getOptionNames() + ", sourceArgs = " + args.getSourceArgs());
}
}
@Slf4j
@Component
public class CommandLineRunnerImpl implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner: " + Arrays.toString(args));
}
}
用 Maven 打包專案為 Jar 包,啟動該 Jar 包:
// 使用 java -jar 啟動,加上兩個引數:name 和 description
java -jar demo-0.0.1-SNAPSHOT.jar --name=god23bin --description=like_me
輸出:
ApplicationRunner: optionNames = [name, description]sourceArgs = [Ljava.lang.String;@5c90e579
CommandLineRunner: [--name=god23bin, --description=like_me]
最后的最后
由本人水平所限,難免有錯誤以及不足之處, 螢屏前的靚仔靚女們 如有發現,懇請指出!
最后,謝謝你看到這里,謝謝你認真對待我的努力,希望這篇博客對你有所幫助!
你輕輕地點了個贊,那將在我的心里世界增添一顆明亮而耀眼的星!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/548467.html
標籤:其他
上一篇:L2-001-緊急救援*C++(使用Dijkstra演算法附帶全詳細注釋)
下一篇:order by是怎么作業的?
