ApplicationRunner & CommandLineRunner & @PostConstruct & static

Posted 我老菜

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ApplicationRunner & CommandLineRunner & @PostConstruct & static相关的知识,希望对你有一定的参考价值。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

系统启动后加载初始化数据


前言

不是很建议使用这些类
建议:
1:页面按钮(后端读表放入缓存,还可以实现reload/unload等)初始化数据
2:懒加载机制,后端用到时,再去读表+放入缓存
3:如果是某些配置,如:请求url,配置参数,那么一定要写到配置文件里,不要这样启动后再去加载

一、四种实现方式

被调用服务 InitService

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class InitService 

    public void init() 
        log.info("InitService");
    

ApplicationRunner

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

import java.util.concurrent.Executors;

@Slf4j
@Component
public class ApplicationRunnerExtend implements ApplicationRunner 

    private final InitService initService;

    public ApplicationRunnerExtend(InitService initService) 
        this.initService = initService;
    

    @Override
    public void run(ApplicationArguments args) throws Exception 
        log.info("-----------ApplicationRunnerExtend-----------");
        Executors.newSingleThreadExecutor().execute(() -> 
            log.info("开启线程执行");
            initService.init();
        );
    

CommandLineRunner

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

@Slf4j
@Component
public class CommandLineRunnerExtend implements CommandLineRunner 

    private final InitService initService;

    public CommandLineRunnerExtend(InitService initService) 
        this.initService = initService;
    

    @Override
    public void run(String... args) throws Exception 
        log.info("-----------CommandLineRunnerExtend-----------");
        initService.init();
    

@PostConstruct

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

import javax.annotation.PostConstruct;

@Slf4j
@Component
public class PostConstructExtend 
    private final InitService initService;

    public PostConstructExtend(InitService initService) 
        this.initService = initService;
    

    @PostConstruct
    public void init() 
        log.info("-----------PostConstructExtend-----------");
        initService.init();
    

static

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

@Slf4j
@Component
public class StaticExtend 

    static 
        InitService initService = new InitService();
        log.info("-----------StaticExtend-----------");
        initService.init();
    

二、执行结果

[           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
[           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 891 ms
[           main] c.e.demo.runner.PostConstructExtend      : -----------PostConstructExtend-----------
[           main] com.example.demo.runner.InitService      : InitService
[           main] com.example.demo.runner.StaticExtend     : -----------StaticExtend-----------
[           main] com.example.demo.runner.InitService      : InitService
[           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
[           main] com.example.demo.TaoDemoApplication      : Started TaoDemoApplication in 21.677 seconds (JVM running for 27.449)
[           main] c.e.demo.runner.ApplicationRunnerExtend  : -----------ApplicationRunnerExtend-----------
[           main] c.e.demo.runner.CommandLineRunnerExtend  : -----------CommandLineRunnerExtend-----------
[           main] com.example.demo.runner.InitService      : InitService
[pool-2-thread-1] c.e.demo.runner.ApplicationRunnerExtend  : 开启线程执行
[pool-2-thread-1] com.example.demo.runner.InitService      : InitService

三、注意异常

InitService中新增方法(会抛异常)

    public void initTwo()
        log.info("InitService");
        String str = null;
        str.contains("123");
    

ApplicationRunner 和 CommandLineRunner虽然是在spring启动成功后再执行的,但如果是执行initTwo,则会因为异常导致启动失败。

建议:
1:异步执行initTwo(),不造成spring启动失败

    public void run(ApplicationArguments args) throws Exception 
        log.info("-----------ApplicationRunnerExtend-----------");
        Executors.newSingleThreadExecutor().execute(() -> 
            log.info("开启线程执行");
            initService.initTwo();
        );
    

2:使用try/catch捕获异常

    @Override
    public void run(String... args) throws Exception 
        log.info("-----------CommandLineRunnerExtend-----------");
        try 
            initService.initTwo();
        catch (Exception e)
            log.error("异常了!!!");
        
    

总结

@PostConstructstatic 不建议用来初始化数据。
他们是在spring启动完成之前执行的,除非必要,不要用这两个去加载初始化数据。

2023年加油加油!

以上是关于ApplicationRunner & CommandLineRunner & @PostConstruct & static的主要内容,如果未能解决你的问题,请参考以下文章

ApplicationRunner & CommandLineRunner & @PostConstruct & static

ApplicationRunner接口

102. Spring Boot之CommandLineRunner和ApplicationRunner

SpringBoot的ApplicationRunner

SpringBoot之ApplicationRunner接口和@Order注解

CommandLineRunner或者ApplicationRunner接口