1 缘起
在补充SpringCloud网关(Gateway)配置白名单相关知识过程中,
有两种实现方案:
(1)SpringBoot的启动配置文件application.yml进行配置;
(2)自动加载MySQL数据库中的白名单数据到内存(JVM)实现;
第一种方案,很简单,只需将白名单配置在启动文件中,SpringBoot启动时会自动加载,无需开发者操心,而,第二种方案,从MySQL自动加载数据到内存,则需要开发者自己实现,核心问题:SpringBoot启动时,自动运行配置的Bean,SpringBoot提供了两种实现方案,均是在启动SpringBoot时,通过回调的方式,运行Bean,更确切描述是:当依赖的Bean存在于SpringApplication中时,回调执行自定义的Bean,两种接口类:
(1)ApplicationRunner
(2)CommandLineRunner
Note:
执行结束后,SpringBoot完成启动,当然,这也带来一个问题,
如果自定义的Bean执行时间过长,SpringBoot应用在这个空窗期,是无法对外提供服务的。
2 Runner
SpringBoot提供了两个Runner接口类,自动回调执行Bean。
2.1 CommandLineRunner
由注释可知,CommandLineRuuner接口类用于执行某个已存在于SpringApplication的Bean,如果在同一个应用上下文中有多个需要CommandLineRunner执行的Bean,可通过Ordered接口或@Order注解配置执行顺序。
CommandLineRunner的回调方法run配置的参数为原生String,如果需要读取命令行中配置的参数,可以使用ApplicationRunner接口类。
2.2 ApplicationRunner
由注释可知,ApplicationRunner接口类用于执行某个已存在于SpringApplication的Bean,如果在同一个应用上下文中有多个需要CommandLineRunner执行的Bean,可通过Ordered接口或@Order注解配置执行顺序。
3 测试
SpringBoot启动时,从MySQL读取用户信息,读取结束,完成SpringBoot启动。
3.1 样例
package com.monkey.standalone.common.mybean;
import com.github.pagehelper.PageInfo;
import com.monkey.standalone.modules.user.service.IUserService;
import com.monkey.standalone.modules.user.vo.UserPageInputVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* 回调执行Bean.
*
* @author xindaqi
* @since 2022-11-19 21:59
*/
@Component
public class LoadDataBean implements ApplicationRunner, CommandLineRunner {
private static final Logger logger = LoggerFactory.getLogger(LoadDataBean.class);
@Resource
IUserService userService;
private UserPageInputVO userPageInputVO = new UserPageInputVO(1, 2);
@Override
public void run(ApplicationArguments args) throws Exception {
PageInfo<BaseUserVO> userPage = userService.queryUserByPage(userPageInputVO);
logger.info(">>>>>>>>Application runner, user info:{}", userPage);
}
@Override
public void run(String... args) throws Exception {
PageInfo<BaseUserVO> userPage = userService.queryUserByPage(userPageInputVO);
logger.info(">>>>>>>>Command line runner, user info: {}", userPage);
}
}
3.2 结果
启动SpringBoot过程中,执行ApplicationRuuner和CommandLineRunner回调方法run中的逻辑。
首先,执行的是ApplicationRunner的回调方法,结果如下图所示。
然后执行的是CommandLineRunner的回调方法,结果如下图所示。
最后,输出SpringBoot启动成功的日志,表明,当Runner接口的回调方法逻辑执行结束,
SpringBoot才会完成启动,上面提到的加载空窗期,SpringBoot应用无法对外提供服务,开发者需要以及实际情况调整加载的数据量。
4 小结
(1)SpringBoot启动过程中,通过回调方式执行Bean的两个接口类:ApplicationRunner和CommandLineRunner;
(2)ApplicationRunner回调方法可以获取输入的参数,CommandLineRunner中的回调方法使用原生字符串;
(3)ApplicationRunner和CommandLineRunner完成加载后才会完成SpringBoot启动,加载空窗期, SpringBoot应用无法对外提供服务。
Note:
感兴趣的可以学习其他的实现:@PostConstruct和InitializingBean,
参见文章:https://blog.csdn.net/Xin_101/article/details/120062024