如果你有一些资源需要在 Spring Boot 启动成功后才去加载,如:预加载配置、加载定时任务、初始化工作等。这些可以通过 Spring Boot 给我们提供的CommandLineRunner 接口和 ApplicationRunner 接口实现。
CommandLineRunner接口是在容器启动成功后的最后一步回调(类似开机自启动)。接口的源码如下:
package org.springframework.boot; @FunctionalInterface public interface CommandLineRunner { void run(String... args) throws Exception; }
该接口只定义了一个 run() 方法,且该方法仅仅接收一个字符串数组。如果我们需要在 Spring Boot 启动成功后做些什么,如:初始化数据,需要实现该接口,实现 run 方法。例如:
package com.huangx.springboot.service; import org.springframework.boot.CommandLineRunner; import org.springframework.stereotype.Service; /** * SpringBoot启动完成后自动运行 */ @Service public class AfterServiceStartedOther implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("AfterServiceStartedOther"); for(String arg : args) { System.out.println(arg); } } }
在运行 Spring Boot 时,添加参数,如下图:
程序运行结果如下:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.1.RELEASE) …… 2020-07-20 23:04:31.759 INFO 16772 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 …… AfterServiceStartedOther name1 name2 name3
从上面实例可以知道,run 方法的参数实际是上就是我们运行程序传递的参数。
CommandLineRunner接口和ApplicationRunner 接口基本一样,区别在于两者接收的参数不一样。CommandLineRunner 的参数是最原始的参数,没有做任何处理;而ApplicationRunner的参数是ApplicationArguments,对原始参数做了进一步的封装。下面通过实例进行说明:
package com.huangx.springboot.service; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.stereotype.Service; import java.util.Arrays; /** * SpringBoot启动完成后自动运行 */ @Service public class AfterServiceStarted implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("AfterServiceStarted"); for(String name : args.getOptionNames()) { System.out.println(name + "=" + args.getOptionValues(name)); } } }
假如我们在这里配置了一些启动参数 --env=dev --level=debug,如下图:
然后运行程序,结果如下:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.1.RELEASE) …… 2020-07-20 23:14:16.307 INFO 21612 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 …… AfterServiceStarted level=[debug] env=[dev]
如果使用 CommandLineRunner 实现上面实例,则 CommandLineRunner 只获取 --env=dev --level=debug 字符串。而 ApplicationRunner 可以将 --env=dev --level=debug 解析为 Key-Value,使得我们可以直接通过 key 来获取 value。
注意:ApplicationRunner 解析的参数必须使用“--”开头(双横线),否则不会解析。
CommandLineRunner 和 ApplicationRunner 接口的工作方式类似,如果有多个启动回调接口实现类,我们还可以通过添加 @Order 注解指定顺序。
例如,我们将上面的 AfterServiceStarted 设置为第一个启动,AfterServiceStartedOther 设置为第二个启动。如下:
AfterServiceStarted.java
package com.huangx.springboot.service; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; import java.util.Arrays; /** * SpringBoot启动完成后自动运行 */ @Order(1) @Service public class AfterServiceStarted implements ApplicationRunner { @Override public void run(ApplicationArguments args) throws Exception { System.out.println("AfterServiceStarted"); for(String name : args.getOptionNames()) { System.out.println(name + "=" + args.getOptionValues(name)); } } }
AfterServiceStartedOther.java
package com.huangx.springboot.service; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Service; /** * SpringBoot启动完成后自动运行 */ @Order(2) @Service public class AfterServiceStartedOther implements CommandLineRunner { @Override public void run(String... args) throws Exception { System.out.println("AfterServiceStartedOther"); for(String arg : args) { System.out.println(arg); } } }
运行结果如下:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.0.1.RELEASE) …… 2020-07-20 23:23:58.084 INFO 19048 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 …… AfterServiceStarted level=[debug] env=[dev] AfterServiceStartedOther --env=dev --level=debug