Springboot启动时执行指定代码

4,385 阅读2分钟

我们在平时的springboot项目中会遇到在服务启动时期望其加载某些静态文件,或者服务启动时访问某些其他服务。这时候就需要在springboot中配置启动执行。

springboot为我们提供了两种开机启动的接口

  1. CommandLineRunner
  2. ApplicationRunner
  3. 同时我们也可以采用spring提供的监听事件ApplicationListener来实现 几种种方式都可以实现“开机启动”。

CommandLineRunner实现

import org.springframework.boot.CommandLineRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(1)
public class MyCommandLineRunner implements CommandLineRunner {
    @Override
    public void run(String... args) throws Exception {
        System.out.println("this is MyCommandLineRunner");
    }
}

ApplicationRunner实现

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Component
@Order(2)
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("this is MyApplicationRunner");
    }
}

ApplicationListener实现

import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

@Component
public class MyApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
    @Override
    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
        System.out.println("this is MyApplicationListener");
    }
}

运行结果

2018-09-24 18:21:25.017  INFO 7896 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
this is MyApplicationListener
Disconnected from the target VM, address: '127.0.0.1:12936', transport: 'socket'
2018-09-24 18:21:25.040  INFO 7896 --- [           main] c.e.s.SpringBootExamplesApplication      : Started SpringBootExamplesApplication in 2.89 seconds (JVM running for 5.734)
this is MyCommandLineRunner
this is MyApplicationRunner

其中ApplicationStartListener的onApplicationEvent方法在容器启动时已经被成功调用了。而此时初始化的容器为root容器。

此处使用Spring boot来进行操作,没有出现二次调用的问题。在使用传统的application.xml和project-servlet.xml配置中会出现二次调用的问题。主要原因是初始化root容器之后,会初始化project-servlet.xml对应的子容器。我们需要的是只执行一遍即可。那么上面打印父容器的代码用来进行判断排除子容器即可。在业务处理之前添加如下判断:

if(contextRefreshedEvent.getApplicationContext().getParent() != null){
   return;
}

这样其他容器的初始化就会直接返回,而父容器(Parent为null的容器)启动时将会执行相应的业务操作。

而CommandLineRunner与ApplicationRunner在Spring Beans初始化之后执行,执行顺序可以实现order接口或者注解@order来标记,@order(1),其中数字代表执行顺序,1是第一个,2是第二个,以此类推。