在使用Spring Boot開發的工做中,咱們常常會須要遇到一種功能需求,好比在服務啓動時候,去加載一些配置,去請求一下其餘服務的接口。Spring Boot給咱們提供了三種經常使用的實現方法: 第一種是實現CommandLineRunner接口, 第二種是實現ApplicationRunner接口 第三種是使用註解:@PostConstruct
一、CommandLineRunner執行的時間節點是在Application完成初始化工做以後。 二、CommandLineRunner在有多個實現的時候,可使用@order註解指定執行前後順序。 三、源碼在:org.springframework.boot.SpringApplication#run(),能夠看看
咱們先看一下CommandLineRunner的源碼:java
package org.springframework.boot; @FunctionalInterface public interface CommandLineRunner { void run(String... args) throws Exception; }
SpringApplication源碼:git
public ConfigurableApplicationContext run(String... args) { StopWatch stopWatch = new StopWatch(); stopWatch.start(); DefaultBootstrapContext bootstrapContext = this.createBootstrapContext(); ConfigurableApplicationContext context = null; this.configureHeadlessProperty(); SpringApplicationRunListeners listeners = this.getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass); try { ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); ConfigurableEnvironment environment = this.prepareEnvironment(listeners, bootstrapContext, applicationArguments); this.configureIgnoreBeanInfo(environment); Banner printedBanner = this.printBanner(environment); context = this.createApplicationContext(); context.setApplicationStartup(this.applicationStartup); this.prepareContext(bootstrapContext, 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, listeners); throw new IllegalStateException(var10); } try { listeners.running(context); return context; } catch (Throwable var9) { this.handleRunFailure(context, var9, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
callRunners方法源碼:spring
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); } } }
咱們寫一個例子實現:bootstrap
import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.Arrays; @Component @Order(1) public class CommandLineRunnerTest implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("----CommandLineRunnerTest1 start---"+ Arrays.toString(args)); } }
ApplicationRunner跟CommandLineRunner是區別是在run方法裏接收的參數不一樣,CommandLineRuner接收的參數是String... args,而ApplicationRunner的run方法的參數是ApplicationArguments
看看ApplicationRunner的源碼:微信
package org.springframework.boot; @FunctionalInterface public interface ApplicationRunner { void run(ApplicationArguments args) throws Exception; }
咱們寫一個例子實現:app
import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import java.util.List; import java.util.Set; @Component @Order(1) public class ApplicationRunnerTest implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("---ApplicationRunnerTest start----"); List<String> nonOptionArgs = args.getNonOptionArgs(); System.out.println("[非選項參數]>>> " + nonOptionArgs); Set<String> optionNames = args.getOptionNames(); for(String optionName: optionNames) { System.out.println("[選項參數]>>> name:" + optionName + ";value:" + args.getOptionValues(optionName)); } } }
@PostConstruct是在javaEE5的時候引入的,它並非Spring提供的,可是Spring有對@PostConstruct的實現。而且是在對象加載完以後執行。
先看註解源碼less
@Documented @Retention (RUNTIME) @Target(METHOD) public @interface PostConstruct { }
咱們寫一個例子實現:ide
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class PostConstructTest { @PostConstruct public void start(){ System.out.println("---PostConstruct start---"); } }
運行代碼輸出結果 :this
https://gitee.com/Qinux/comma...spa
微信公衆號:一凡碼農 歡迎交流