In our work with Spring Boot, we often encounter a functional requirement, such as loading some configuration to request the interface of another service when the service is started. Spring Boot provides three common implementations: the first is to implement the CommandLineRunner interface, the second is to implement the ApplicationRunner interface, and the third is to use the @postConstruct annotationCopy the code
1, CommandLineRunner
CommandLineRunner executes at a time node after the Application has been initialized. CommandLineRunner can use the @Order annotation to specify the order of execution when there are multiple implementations of CommandLineRunner. 3, the source code in: org. Springframework. Boot. SpringApplication# run (), you can seeCopy the code
Take a look at CommandLineRunner’s source code:
package org.springframework.boot;
@FunctionalInterface
public interface CommandLineRunner {
void run(String... args) throws Exception;
}
Copy the code
SpringApplication source code:
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); }}Copy the code
CallRunners method
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); }}}Copy the code
Let’s write an example implementation:
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)); }}Copy the code
2, ApplicationRunner
The difference between the ApplicationRunner and CommandLineRunner is that the run method receives a different parameter, CommandLineRunner receives a String... Args, and ApplicationRunner's run method takes ApplicationArgumentsCopy the code
Check out ApplicationRunner’s source code:
package org.springframework.boot;
@FunctionalInterface
public interface ApplicationRunner {
void run(ApplicationArguments args) throws Exception;
}
Copy the code
Let’s write an example implementation:
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("[optional argument]>>> "+ nonOptionArgs); Set<String> optionNames = args.getOptionNames(); For (String optionName: optionNames) {system.out.println ("[option parameter]>>> name:" + optionName + "; value:" + args.getOptionValues(optionName)); }}}Copy the code
3, @ PostConstruct
@postconstruct was introduced in javaEE5. It is not provided by Spring, but Spring has an implementation for @postconstruct. It is executed after the object is loaded.Copy the code
First look at the annotated source code
@Documented
@Retention (RUNTIME)
@Target(METHOD)
public @interface PostConstruct {
}
Copy the code
Let’s write an example implementation:
import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; @Component public class PostConstructTest { @PostConstruct public void start(){ System.out.println("---PostConstruct start---"); }}Copy the code
Run the code output:
5, the source code
Gitee.com/Qinux/comma…
Wechat official account: Yifanmong welcomes communicationCopy the code