简介:

业务需求需要在项目启动之后自动执行一些操作(数据初始化或者创建一些调度任务),但是有时候可能不太明确他们的执行顺序,本文就梳理一下几种方式的执行顺序。

方法

一:实现InitializingBean接口重写afterProperiesSet()方法

InitializingBean接口只包含afterProperiesSet()这一个方法,凡是继承InitializingBean接口的类,都会在初始化的时候调用这个方法;
使用方法分为三个步骤:1、被spring管理;2、实现InitializingBean接口;3、重写afterProperiesSet()方法。

@Component
@Slf4j
public class InitConfigInitializingBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        log.error("testinit: InitializingBean已启动! ");
    }
}

二:方法注解@PostConstruct

作用在于声明一个Bean对象初始化完成后执行的,方法比ApplicationRunner要快。有以下几个特点:
1、只有一个非静态方法能使用此注解。
2、被注解的方法不得有任何参数。
3、被注解方法不能抛出异常。
4、被注解方法只会被执行一次。

@Component
@Slf4j
public class InitConfigPostConstruct {

    @PostConstruct
    public void init() {
        log.error("testinit: postconstruct已启动! ");
    }
}

三:监听ApplicationListener上下文事件

实现ApplicationListener接口,并实现onApplicationEvent(ContextRefreshedEvent applicationEvent)方法

@Component
@Slf4j
public class InitConfigApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent applicationEvent) {
        log.error("testinit: InitConfigApplicationListener启动! ");
    }
}

四:实现ApplicationRunner接口重写run()方法

ApplicationRunner也可以实现同样的功能,该方法的参数是ApplicationArguments
且在不设置@Order的情况下application的优先级要大于command

@Component
public class InitConfigApplicationRunner implements ApplicationRunner {

    private static final Logger LOGGER = LoggerFactory.getLogger(InitConfigApplicationRunner.class);
    @Override
    public void run(ApplicationArguments args) throws Exception {
        LOGGER.error("testinit: InitConfigApplicationRunner已启动! ");
    }
}

五:实现CommandLineRunner接口重写run()方法

@Component
public class InitConfigCommandLineRunner implements CommandLineRunner {

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

    @Override
    public void run(String... args) throws Exception {
        logger.error("testinit: commandLineRunner已启动");
    }
}

六:结论

在默认情况下(不加order关键字的情况下),初始化的先后顺序如下面所示:
InitializingBean —> postconstruct —> ApplicationListener —> ApplicationRunner —> commandLineRunner
测试结果:
在这里插入图片描述
ApplicationRunner 与CommandLineRunner工作方式相同,唯一的区别在于两种方法入参方式不同,实现这两个接口就可以让应用程序代码在启动完成后,接收流量前被调用。如果实现了多次,则必须实现org.springframework.core.Ordered或者使用org.springframework.core.annotation.Order注解来定义他们之间的顺序。
推荐使用: ApplicationRunner 或者 CommandLineRunner方式

参考资料 & 致谢

[Java Framework] SpringBoot几种启动后自动初始化的几种方式

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐