Java实战指南|SpringBoot启动时初始化系统资源

这是我参与更文挑战的第3天,活动详情查看: 更文挑战

Hello, everybody! 今天小编已经在倔金更文第三天,之前也在CSDN啊简书这类博客网站更过一段时间的文章,但每次都坚持不下去,立了Flag要每天写点东西,可总是坚持不了两天,Flag立了倒,倒了立,一直得不到正反馈,最后自己都气馁了(ps:引用倔金?,说到我的心坎里啦,哈哈哈哈)这次希望自己可以坚持下去,加油⛽️

下面进入正题??????

开始了.gif

需求背景:

在Spring Boot项目启动的时候要进行一批数据初始化到JavaCache内存中以保证后续接口的可用性,如何解决项目启动时初始化资源,在我们实际工作中,这样的需求也是很常见的,在项目启动的时候需要做一些初始化的操作,如初始化线程池,初始化数据资源等。

解决方法

为了达到这个目的,SpringBoot提供了一种简单的实现方案就是添加一个model并实现CommandLineRunnerApplicationRunner接口,实现功能的代码放在实现的run方法中,spring boot会自动监测到它们,并使用@Component注解使其成为bean;

CommandLineRunner和ApplicationRunner:
  • CommandLineRunner和ApplicationRunner的区别
    • 不同之处在于CommandLineRunner接口的run()方法接收String数组作为参数,即是最原始的参数,没有做任何处理;而ApplicationRunner接口的run()方法接收ApplicationArguments对象作为参数,是对原始参数做了进一步的封装。
  • 当程序启动时,我们传给main()方法的参数可以被实现CommandLineRunner和ApplicationRunner接口的类的run()方法访问,即可接收启动服务时传过来的参数。我们可以创建多个实现CommandLineRunner和ApplicationRunner接口的类。为了使他们按一定顺序执行可以使用@Order注解或实现Ordered接口。

话不多说,上代码,先来看一下他们的简单使用:

上代码.gif

CommandLineRunner:

package com.wechat.wechatservice.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * 
 *
 * @author TZ
 * @version 1.0
 * @date 6/2/21 11:39 AM
 */
@Component
@Slf4j
public class CommandLineRunnerBean implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        String strArgs = Arrays.stream(args).collect(Collectors.joining("|"));
        log.info("Application started with arguments:" + strArgs);
    }
} 
复制代码
启动类Application.java
/**
 * @author tz
 * @create 2019-09-24 14:30
 */
@SpringBootApplication
public class WeChatApplication {

    private static final Logger logger = LoggerFactory.getLogger(WeChatApplication.class);

    public static void main(String[] args) {
        
        ConfigurableApplicationContext context = SpringApplication.run(WeChatApplication.class, args);
        HelloService service = context.getBean(HelloService.class);
        logger.info(service.getMessage());
    }
}
复制代码
import org.springframework.stereotype.Service;

@Service
public class HelloService {
    public String getMessage(){
        return "Hello World!";
    }
}
复制代码

现在可以启动我们项目看一下效果了,我们自己测试的时候通过在idea里配置启动参数启动即可,如下图:

图片.png
当然也可以使用java-jar jar包名 参数1 参数2 参数3来进行启动

我们来看一下启动输出结果:

2021-06-02 11:50:17.038  INFO 31223 --- [  restartedMain] c.w.wechatservice.WeChatApplication      : Started WeChatApplication in 5.858 seconds (JVM running for 6.818)
2021-06-02 11:50:17.040  INFO 31223 --- [  restartedMain] c.w.w.config.CommandLineRunnerBean       : Application started with arguments:data1|data2|data3
2021-06-02 11:50:17.042  INFO 31223 --- [  restartedMain] c.w.wechatservice.WeChatApplication      : Hello World!

复制代码

ApplicationRunner同理如下:

/**
 * 
 *
 * @author tz
 * @version 1.0
 * @date 6/2/21 1:42 PM
 */
@Component
@Slf4j
public class ApplicationRunnerBean implements ApplicationRunner {

    @Override
    public void run(ApplicationArguments args) throws Exception {
        String strArgs = Arrays.stream(args.getSourceArgs()).collect(Collectors.joining("|"));
        log.info("ApplicationRunnerBean ---> {}",strArgs);
    }
}
复制代码

Program arguments:作为main 方法的args参数传入
ApplicationArguments有如下方法:

boolean containsOption(String name) :返回从参数分析的选项参数集是否包含具有给定名称的选项。

List getNonOptionArgs() : 返回已分析的非选项参数集合。

Set getOptionNames() :返回所有选项参数的名称。例如,如果参数为“-foo=bar–debug”,则返回值[“foo”,“debug”]。

List getOptionValues(String name): 返回与具有给定名称的参数选项关联的值集合。返回与具有给定名称的参数选项关联的值集合。
如果选项存在且没有参数(例如:“–foo”),则返回空集合([])如果该选项存在且具有单个值(例如“–foo=bar”),则返回一个包含一个元素的集合([“bar”])
如果选项存在并且有多个值(例如“–foo=bar–foo=baz”),则返回一个集合,其中每个值都有元素([“bar”、“baz”])
如果选项不存在,则返回空值

String[] getSourceArgs():
返回传递给应用程序的未处理的原始参数

CommandLineRunner和ApplicationRunner的执行顺序:

在spring boot程序中,我们可以使用不止一个实现CommandLineRunner和ApplicationRunner的bean。为了有序执行这些bean的run()方法,可以使用@Order注解或Ordered接口按顺序执行各个实现的Bean。

@Component
@Order(1)
public class CommandLineRunnerBean1 implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 1");
    }
}

------------------------------------------------------------------------

@Component
@Order(2)
public class ApplicationRunnerBean1 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 1");
    }
}

------------------------------------------------------------------------
@Component
@Order(3)
public class CommandLineRunnerBean2 implements CommandLineRunner {
    @Override
    public void run(String... args) {
        System.out.println("CommandLineRunnerBean 2");
    }
}

------------------------------------------------------------------------
@Component
@Order(4)
public class ApplicationRunnerBean2 implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("ApplicationRunnerBean 2");
    }
}

------------------------------------------------------------------------
输出结果:
CommandLineRunnerBean 1
ApplicationRunnerBean 1
CommandLineRunnerBean 2
ApplicationRunnerBean 2
复制代码

ok!文章到此就结束了,分享一些工作中可能会用到的一些Java小技巧,希望可以对大家有帮助,让大家少走一些弯路,有不对的地方希望大家可以提出来的,共同成长;

细节之中只有天地,整洁成就卓越代码

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享