1. Introduction

I don’t know if you’ve been asked to implement some logic as soon as the project starts. Such as cache preheating, or online broadcast and so on. Maybe not now but in the future. Think about your possible operation, write an interface line I can adjust once? NO! NO! NO! That kind of beginner’s stuff. Today, I’m telling you that this operation makes your code more elegant and higher.

2. CommandLineRunner interface

 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
  * @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;
 
 }Copy the code

The CommandLineRunner function is to execute multiple CommandLineRunner type Spring beans defined in the same application context in marked order when Spring Application is started. If you want to replace with array way receive the args parameter can substitute another interface for org. Springframework. Boot. ApplicationRunner.

Talk is cheap show your code.

2.1 Higher priorityCommandLineRunnerimplementation

package cn.felord.begin; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; Foo =bar --dev.name= Java,springboot * @author Felordcn * @since 2019/6/17 23:06 */ @Slf4j @Component public class HighOrderCommandLineRunner implements CommandLineRunner , Ordered { @Override public void run(String... args) throws Exception { log.info("i am highOrderRunner"); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; }}Copy the code

2.2 Low priorityCommandLineRunnerImplementation:

package cn.felord.begin; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.Ordered; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; / * * * low priority Through annotation {@ the link Order} is larger than the optimal way to specify the priority * 64 presentation at {@ link HighOrderCommandLineRunner} executed after * * @ author Felord * @ since  2019/6/17 23:07 */ @Slf4j @Order(Ordered.HIGHEST_PRECEDENCE + 64) @Component public class LowOrderCommandLineRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { log.info("i am lowOrderRunner"); }}Copy the code

2.3 withApplicationRunnerAchieve the lowest priority:

package cn.felord.begin; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; /** * Lowest priority implementation * @author Felordcn * @since 2019/6/18 22:13 */ @slf4j @Component Public class DefaultApplicationRunner implements ApplicationRunner, Ordered { @Override public void run(ApplicationArguments args) throws Exception { log.info("i am applicationRunner"); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE+65; }}Copy the code

After starting SpringBoot, the console prints the execution result:

The 2019-11-02 21:18:14. 10244-603 the INFO [main] C.F.B do v.begin. HighOrderCommandLineRunner: I am highOrderRunner 21:18:14 2019-11-02. 10244-604 the INFO [main] C.F.B do v.begin. LowOrderCommandLineRunner: I am lowOrderRunner 21:18:14 2019-11-02. 10244-604 the INFO [main] C.F.B do v.begin. DefaultApplicationRunner: i am applicationRunnerCopy the code

3. Advanced operations — Read the parameters for Boot injection via the Spring Boot command line

Achieve the desired result of our opening paragraph. So what’s the difference between these two interfaces? Spring Boot passes extra parameters to the main method by executing java-jar on the command line, The following rules

  • The key-value pair format is--K=VSeparate multiple entries with Spaces
  • The value is separated by multiple Spaces

    Open the main method configuration item in the IDEA development tool and perform the following configuration. Do the same for other IDE tools. The parameters are as follows:

    –foo=bar –dev.name= Java springboot

HighOrderCommandLineRunner print args parameter:

package cn.felord.begin; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.CommandLineRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; Foo =bar --dev.name= Java,springboot * @author dax * @since  2019/6/17 23:06 */ @Slf4j @Component public class HighOrderCommandLineRunner implements CommandLineRunner , Ordered { @Override public void run(String... args) throws Exception { for (String arg : args) { System.out.println("arg = " + arg); } log.info("i am highOrderRunner"); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; }}Copy the code

DefaultApplicationRunner ApplicationArguments

package cn.felord.begin; import lombok.extern.slf4j.Slf4j; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.Ordered; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; import java.util.List; /** * @author Felord * @since 2019/6/18 22:13 */ @Slf4j @Component public class DefaultApplicationRunner implements ApplicationRunner, Ordered { @Override public void run(ApplicationArguments args) throws Exception { log.info("i am applicationRunner"); args.getOptionNames().forEach(System.out::println); System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>"); String[] sourceArgs = args.getSourceArgs(); if (sourceArgs! =null){ for (String sourceArg : sourceArgs) { System.out.println("sourceArg = " + sourceArg); } } System.out.println("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"); List<String> foo = args.getOptionValues("foo"); if (! CollectionUtils.isEmpty(foo)){ foo.forEach(System.out::println); } System.out.println("++++++++++++"); List<String> nonOptionArgs = args.getNonOptionArgs(); System.out.println("nonOptionArgs.size() = " + nonOptionArgs.size()); nonOptionArgs.forEach(System.out::println); } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE+65; }}Copy the code

Restarting the Spring Boot console prints the result:

Arg = --foo=bar arg = --dev. Name = Java arg = Java arg = springboot 2019-11-02 21:18:14.603 INFO 10244 -- [main] c.f.begin.HighOrderCommandLineRunner : I am highOrderRunner 21:18:14 2019-11-02. 10244-604 the INFO [main] C.F.B do v.begin. LowOrderCommandLineRunner: I am lowOrderRunner 21:18:14 2019-11-02. 10244-604 the INFO [main] C.F.B do v.begin. DefaultApplicationRunner: I am applicationRunner dev. Name foo > > > > > > > > > > > > > > > > > > > > > > > > > > sourceArg = - foo = bar sourceArg = -- dev. Name = code farming little elder brother sourceArg = java sourceArg = springboot <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< bar ++++++++++++ nonOptionArgs.size() = 2 java springbootCopy the code

We found that we could use these two interfaces to read Spring Boot command-line arguments. In fact, we can also use the @Value annotation to read it, but I won’t go into that here, so you can try it out for yourself. At this point the difference between ApplicationRunner and CommandLineRunner is clear from the console.

4. ApplicationRunnerCommandLineRunnerThe difference between

From the above log we know that arg= prints for CommandLineRunner’s ARgs array, which simply parses the above parameters into the original array using a space rule. ApplicationRunner is more refined. As you can see from print, ApplicationArguments provides some useful parameter resolution methods:

  • args.getOptionNames()Is to get a key-value pair--K=VIn theK
  • args.getOptionValues("foo")To be sent through theKTo get the value of the key-value pairV
  • args.getSourceArgs()Is equivalent toCommandLineRunnerargsAn array of
  • args.getNonOptionArgs()Worst way to get a single dog

Note that you deal with null Pointers when parsing ApplicationArguments.

5. To summarize

Today we look at CommandLineRunner and ApplicationRunner. Solved the problem of how to execute some logic at Spring Boot startup and how to prioritize multiple Boot logic. At the same time, we further read the Spring Boot Boot parameters through these two methods. Then you understand the subtle differences between the two interfaces. I hope it helps.

Follow our public id: Felordcn for more information

Personal blog: https://felord.cn