一、前言
一般来说,SpringBoot工程环境配置放在properties文件中,启动的时候将工程中的properties/yaml文件的配置项加载到内存中。但这种方式改配置项的时候,需要重新编译部署,考虑到这种因素,今天介绍将配置项存到数据库表中,在工程启动时把配置项加载到内存中。
SpringBoot提供了两个接口: CommandLineRunner 和 ApplicationRunner 。实现其中接口,就可以在工程启动时将数据库中的数据加载到内存。使用的场景有:加载配置项到内存中;启动时将字典或白名单数据加载到内存(或缓存到Redis中)。
二、加载方式
第一种:使用@PostConstruct注解(properties/yaml文件)。
第二种:使用@Order注解和CommandLineRunner接口。
第三种:使用@Order注解和ApplicationRunner接口。
注意事项
第二种和第三种,二者的官方javadoc一样,区别在于接收的参数不一样。CommandLineRunner的参数是最原始的参数,没有做任何处理。ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步的封装。
三、代码示例
3.1 使用@PostConstruct注解
-
package com.example.demo.config;
-
-
import com.example.demo.service.ICodeService;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.stereotype.Component;
-
-
import javax.annotation.PostConstruct;
-
import javax.annotation.PreDestroy;
-
import java.util.HashMap;
-
import java.util.List;
-
import java.util.Map;
-
-
@Component
-
public
class
InitData1 {
-
-
public
static Map<Integer, String> codeMap =
new
HashMap<Integer, String>();
-
-
@Autowired
-
private ICodeService codeService;
-
-
@PostConstruct
-
public
void
init
() {
-
System.out.println(
"示例1:加载codeMap中......");
-
// 查询数据库数据
-
List<String> codeList = codeService.listAll();
-
for (
int
i
=
0; i < codeList.size(); i++) {
-
codeMap.put(i, codeList.get(i));
-
}
-
}
-
-
@PreDestroy
-
public
void
destroy
() {
-
System.out.println(
"系统启动成功,codeMap加载完成!");
-
}
-
}
3.2 CommandLineRunner接口
-
package com.example.demo.config;
-
-
import com.example.demo.service.ICodeService;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.CommandLineRunner;
-
import org.springframework.core.annotation.Order;
-
import org.springframework.stereotype.Component;
-
-
import java.util.HashMap;
-
import java.util.List;
-
import java.util.Map;
-
-
@Component
-
@Order(1)
// 初始化加载优先级,数字越小优先级越高
-
public
class
InitData2
implements
CommandLineRunner {
-
-
public
static Map<Integer, String> codeMap =
new
HashMap<Integer, String>();
-
-
@Autowired
-
private ICodeService codeService;
-
-
@Override
-
public
void
run
(String... args)
throws Exception {
-
System.out.println(
"示例2:加载codeMap中......");
-
// 查询数据库数据
-
List<String> codeList = codeService.listAll();
-
for (
int
i
=
0; i < codeList.size(); i++) {
-
codeMap.put(i, codeList.get(i));
-
}
-
}
-
}
3.3 ApplicationRunner接口
-
package com.example.demo.config;
-
-
import com.example.demo.service.ICodeService;
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.boot.ApplicationArguments;
-
import org.springframework.boot.ApplicationRunner;
-
import org.springframework.core.annotation.Order;
-
import org.springframework.stereotype.Component;
-
-
import java.util.HashMap;
-
import java.util.List;
-
import java.util.Map;
-
-
@Component
-
@Order(1)
// 初始化加载优先级,数字越小优先级越高
-
public
class
InitData3
implements
ApplicationRunner {
-
-
public
static Map<Integer, String> codeMap =
new
HashMap<Integer, String>();
-
-
@Autowired
-
private ICodeService codeService;
-
-
@Override
-
public
void
run
(ApplicationArguments args)
throws Exception {
-
System.out.println(
"示例3:加载codeMap中......");
-
// 查询数据库数据
-
List<String> codeList = codeService.listAll();
-
for (
int
i
=
0; i < codeList.size(); i++) {
-
codeMap.put(i, codeList.get(i));
-
}
-
}
-
}
四、总结
1、CommandLineRunner和ApplicationRunner调用的时机是在容器初始化完成之后,立即调用。
2、CommandLineRunner和ApplicationRunner使用上没有区别,唯一区别是CommandLineRunner接受字符串数组参数,需要自行解析出健和值,ApplicationRunner的参数是ApplicationArguments,是对原始参数做了进一步的封装。
3、两个接口都可以使用 @Order 参数,支持工程启动后根据order 声明的权重值来觉得调用的顺序(数字越小,优先级越高)。
完结!
转载:https://blog.csdn.net/weixin_44299027/article/details/128973408