SpringBoot2.x基礎(chǔ)篇:使用CommandLineRunner或ApplicationRunner

知識改變命運(yùn),擼碼使我快樂烙丛,2020繼續(xù)游走在開源界

點(diǎn)贊再看,養(yǎng)成習(xí)慣

給我來個Star吧,點(diǎn)擊了解下基于SpringBoot的組件化接口服務(wù)落地解決方案

如果你想要使用SpringBoot構(gòu)建的項(xiàng)目在啟動后運(yùn)行一些特定的代碼紊搪,那么CommandLineRunnerApplicationRunner都是很好的選擇磨总。

推薦閱讀

使用方式

我們以CommandLineRunner創(chuàng)建了一個簡單的例子嗦明,如下所示:

/**
 * {@link CommandLineRunner}接口使用示例
 *
 * @author 恒宇少年
 */
@Component
public class CommandLineRunnerExample implements CommandLineRunner {
    /**
     * 實(shí)例化本類的日志采集器
     */
    static LoggingCollector logging = LoggingCollectorFactory.getCollector(CommandLineRunnerExample.class);

    @Override
    public void run(String... args) throws Exception {
        // 執(zhí)行特定的代碼
        logging.debug("main方法參數(shù)列表:{}", args);
    }
}

CommandLineRunner接口的定義很簡單,只提供了一個名為#run()的方法蚪燕,我們只需要實(shí)現(xiàn)該方法做一些自定義的業(yè)務(wù)邏輯即可娶牌,ApplicationRunner接口的使用方式也是一樣的。

兩者的區(qū)別馆纳?

從源碼上分析诗良,CommandLineRunnerApplicationRunner兩者之間只有#run()方法的參數(shù)不一樣而已。

CommandLineRunner:

@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;

}

ApplicationRunner:

@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#run()方法的參數(shù)是啟動SpringBoot應(yīng)用程序main方法的參數(shù)列表鲁驶,而ApplicationRunner#run()方法的參數(shù)則是ApplicationArguments對象鉴裹。

在之前的文章中也提到過ApplicatgionArguments對象,并使用它獲取外部的配置參數(shù)钥弯,查看:應(yīng)用程序在啟動時訪問啟動項(xiàng)參數(shù)径荔。

建議:如果你在項(xiàng)目啟動時需要獲取類似 "--xxx" 的啟動參數(shù)值建議使用ApplicationRunner

什么時候會被調(diào)用?

我們已經(jīng)了解CommandLineRunnerApplicationRunner兩個接口的使用以及區(qū)別脆霎,是不是很想知道SpringBoot在啟動時在什么時候調(diào)用它們的呢总处?

我們大家都知道SpringBoot應(yīng)用程序的啟動主要?dú)w功于SpringApplication這個類,我們在創(chuàng)建項(xiàng)目時在啟動類內(nèi)會調(diào)用SpringApplication#run()方法睛蛛,如下所示:

public static void main(String[] args) {
  SpringApplication.run(LoggingServiceApplication.class, args);
}

那我們來查看下SpringApplication#run()方法的源碼鹦马,根據(jù)查看方法之間的相互調(diào)用,最終我們會定位到org.springframework.boot.SpringApplication#run(java.lang.String...)這個方法忆肾,閱讀該方法時發(fā)現(xiàn)有關(guān)調(diào)用Runner的定義荸频,如下所示:

// 省略部分源碼
listeners.started(context);
callRunners(context, applicationArguments);
// 省略部分源碼

#callRunnners()方法的調(diào)用確實(shí)是在應(yīng)用程序啟動完成后,而且把ApplicationContextApplicationArguments對象都作為參數(shù)進(jìn)行了傳遞客冈,那么我們來看看這個方法究竟干了些什么事情旭从?

SpringApplication#callRunners:

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);
  for (Object runner : new LinkedHashSet<>(runners)) {
    if (runner instanceof ApplicationRunner) {
      callRunner((ApplicationRunner) runner, args);
    }
    if (runner instanceof CommandLineRunner) {
      callRunner((CommandLineRunner) runner, args);
    }
  }
}

我想大家看到這里就應(yīng)該明白了,這個方法就是在執(zhí)行CommandLineRunner以及ApplicationRunner實(shí)現(xiàn)類實(shí)例的#run()方法,首先會從ApplicationContext中獲取CommandLineRunner遇绞、ApplicationRunner接口實(shí)現(xiàn)類的實(shí)例键袱,然后根據(jù)不同類型的Runner實(shí)例去調(diào)用了callRunner方法。

SpringApplication#callRunner:


// 調(diào)用ApplicationRunner實(shí)現(xiàn)類實(shí)例#run()
private void callRunner(ApplicationRunner runner, ApplicationArguments args) {
  try {
    (runner).run(args);
  }
  catch (Exception ex) {
    throw new IllegalStateException("Failed to execute ApplicationRunner", ex);
  }
}
// 調(diào)用CommandLineRunner實(shí)現(xiàn)類實(shí)例#run()
private void callRunner(CommandLineRunner runner, ApplicationArguments args) {
  try {
    (runner).run(args.getSourceArgs());
  }
  catch (Exception ex) {
    throw new IllegalStateException("Failed to execute CommandLineRunner", ex);
  }
}

設(shè)置執(zhí)行順序

那如果我們創(chuàng)建了多個CommandLineRunner摹闽、ApplicationRunner實(shí)現(xiàn)類蹄咖,還想要實(shí)現(xiàn)類在執(zhí)行的時候有一定的先后順序,那你不妨試下org.springframework.core.annotation.Order這個注解或者實(shí)現(xiàn)org.springframework.core.Ordered接口付鹿。

CommandLineRunnerExample:

/**
 * {@link CommandLineRunner}接口使用示例
 *
 * @author 恒宇少年
 */
@Component
@Order(100)
public class CommandLineRunnerExample implements CommandLineRunner, Ordered {
    // 省略部分代碼
    @Override
    public int getOrder() {
        return 100;
    }
}

接口注解的方式選擇其中一種就可以了澜汤。

作者個人 博客
使用開源框架 ApiBoot 助你成為Api接口服務(wù)架構(gòu)師

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市舵匾,隨后出現(xiàn)的幾起案子俊抵,更是在濱河造成了極大的恐慌,老刑警劉巖坐梯,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徽诲,死亡現(xiàn)場離奇詭異,居然都是意外死亡吵血,警方通過查閱死者的電腦和手機(jī)谎替,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來蹋辅,“玉大人钱贯,你說我怎么就攤上這事≌炝恚” “怎么了秩命?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長褒傅。 經(jīng)常有香客問我弃锐,道長,這世上最難降的妖魔是什么殿托? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任拿愧,我火速辦了婚禮,結(jié)果婚禮上碌尔,老公的妹妹穿的比我還像新娘。我一直安慰自己券敌,他們只是感情好唾戚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著待诅,像睡著了一般叹坦。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上卑雁,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天募书,我揣著相機(jī)與錄音绪囱,去河邊找鬼。 笑死莹捡,一個胖子當(dāng)著我的面吹牛鬼吵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播篮赢,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼齿椅,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了启泣?” 一聲冷哼從身側(cè)響起涣脚,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寥茫,沒想到半個月后遣蚀,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡纱耻,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年芭梯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片膝迎。...
    茶點(diǎn)故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡粥帚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出限次,到底是詐尸還是另有隱情芒涡,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布卖漫,位于F島的核電站费尽,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏羊始。R本人自食惡果不足惜旱幼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望突委。 院中可真熱鬧柏卤,春花似錦、人聲如沸匀油。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽敌蚜。三九已至桥滨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背齐媒。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工蒲每, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人喻括。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓邀杏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親双妨。 傳聞我的和親對象是個殘疾皇子淮阐,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評論 2 353