在使用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
微信公众号:一凡码农 欢迎交流