前言
一般来说,springboot工程环境配置放在properties文件中,启动的时候将工程中的properties/yaml文件的配置项加载到内存中。但这种方式改配置项的时候,需要重新编译部署,考虑到这种因素,今天介绍将配置项存到数据库表中,在工程启动时把配置项加载到内存中。
springboot提供了两个接口:CommandLineRunner和ApplicationRunner。实现其中接口,就可以在工程启动时将数据库中的数据加载到内存。实现任意接口可实现以下场景:加载配置项到内存中;启动时将字典或白名单数据加载到内存(或缓存到redis中)。
一、CommandLineRunner实现
1、CommandLineRunner接口
1) 接口详解
官方doc:
Interface used to indicate that a bean should run when it is contained within a SpringApplication.
Multiple CommandLineRunner beans can be defined within the same application context and can be orderedusing the Ordered interface or Order @Order annotation.
这里是引用接口被用作将其加入spring容器中时执行其run方法。多个CommandLineRunner可以被同时执行在同一个spring上下文中并且执行顺序是以order注解的参数顺序一致。
If you need access to ApplicationArguments instead of the raw String arrayconsider using ApplicationRunner.
如果你需要访问ApplicationArguments去替换掉字符串数组,可以考虑使用ApplicationRunner类。
2)代码演示
在我们新建好工程后,为了简单我们直接使用Application类实现CommandLineRunner接口(或者新建类实现并使用@Component注解),这个类的注解@SpringBootApplication会为我们自动配置。
package com.skh.springboot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpringbootApplication implements CommandLineRunner {
private static Logger logger = LoggerFactory.getLogger(SpringbootApplication.class);
public static void main(String[] args) {
SpringApplication.run(SpringbootApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
logger.info("服务已启动,执行command line runner。");
for (int i = 0; i < args.length; ++i) {
logger.info("args[{}]: {}", i, args[i]);
}
}
}
启动服务,控制台查看日志如下,发现run()方法被正常地执行了:
run()方法有个可变参数args,这个参数是用来接收命令行参数的,我们下面来加入参数来测试一下:
重启,查看控制台日志,发现传入的参数已经打印出来:
2、ApplicationRunner接口
1)接口详解
二者的官方javadoc一样,区别在于接收的参数不一样。CommandLineRunner的参数是最原始的参数,没有做任何处理。ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步的封装。
ApplicationArguments是对参数(main方法)做了进一步的处理,可以解析–name=value的,我们就可以通过name来获取value(而CommandLineRunner只是获取–name=value)。
可以接收–foo=bar这样的参数。
–getOptionNames()方法可以得到foo这样的key的集合。
–getOptionValues(String name)方法可以得到bar这样的集合的value。
2)代码演示
定义MyApplicationRunner类继承ApplicationRunner接口。
package com.skh.springboot;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;
@Component
public class MyApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("===MyApplicationRunner==="+ Arrays.asList(args.getSourceArgs()));
System.out.println("===getOptionNames========"+args.getOptionNames());
System.out.println("===getOptionValues======="+args.getOptionValues("param"));
System.out.println("==getOptionValues========"+args.getOptionValues("developer.name"));
}
}
然后加入启动参数
控制台查看日志打印
总结
1、CommandLineRunner和ApplicationRunner调用的时机是在容器初始化完成之后,立即调用。
2、CommandLineRunner和ApplicationRunner使用上没有区别,唯一区别是CommandLineRunner接受字符串数组参数,需要自行解析出健和值,ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步的封装。
3、两个接口都可以使用@Order参数,支持工程启动后根据order声明的权重值来觉得调用的顺序(数字越小,优先级越高)。