欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

SpringBoot 核心功能 - ApplicationRunner && CommandLineRunner 的使用

最编程 2024-03-09 17:44:53
...

前言

如果想在SpringApplication启动后做一些操作,那么除了可以监听ApplicationReadyEvent事件外,还可以实现ApplicationRunner或CommandLineRunner接口.

ApplicationRunner

新建一个ApplicationRunner实现,代码如下:

package geek.springboot.application.runner;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.boot.ApplicationArguments;  
import org.springframework.boot.ApplicationRunner;  
import org.springframework.stereotype.Component;  
  
/**  
* 自定义{@link ApplicationRunner}实现  
*  
* @author Bruse  
*/
@Slf4j  
@Component  
public class CustomApplicationRunner implements ApplicationRunner {  
  
    /**  
    * 在SpringApplication启动完成后,该方法会被回调,可以在这里做一些操作  
    *  
    * @param args 启动Java Application时设置的程序参数  
    * @throws Exception 异常  
    */  
    @Override  
    public void run(ApplicationArguments args) throws Exception {  
        // 简单打印一下应用参数
        log.info("arguments is {}", Arrays.toString(args.getSourceArgs()));
    }  
  
}

这里ApplicationRunner的run()方法实现,仅仅打印一下应用参数,所以在启动Java Application前,先在配置一些应用参数【笔者这里用到的IDEA版本为2023.1.4】:

image.png

image.png

image.png

启动SpringApplication,输出如下:

image.png

可以看到CustomApplicationRunner的run()方法在SpringApplicaiton启动后被回调,并且输出我们配置的应用参数.

CommandLineRunner

新建一个CommandLineRunner实现,代码如下:

package geek.springboot.application.runner;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.boot.CommandLineRunner;  
import org.springframework.stereotype.Component;  
  
import java.util.Arrays;  
  
  
/**  
* 自定义{@link CommandLineRunner}实现  
*/  
@Slf4j  
@Component  
public class CustomCommandLineRunner implements CommandLineRunner {  
  
    /**  
    * 在SpringApplication启动完成后,该方法会被回调,可以在这里做一些操作  
    *  
    * @param args 启动Java Application时设置的程序参数  
    * @throws Exception 异常  
    */  
    @Override  
    public void run(String... args) throws Exception {  
        // 这里简单做一下参数打印
        log.info("args is {}", Arrays.toString(args));  
    }  
  
}

启动SpringApplication,控制台成功输出:

image.png

两者的区别

ApplicationRunner和CommandLineRunner两个接口唯一的区别在于,两者run()方法的参数不一样,虽然参数都是Java应用启动时设置的参数,但ApplicationRunner将参数包装成了ApplicationArguments,CommandLineRunner则没有多过包装,直接就是传递一个String[]给实现者进行参数读取.

image.png

image.png

优先级设置

如果必须按特定顺序调用ApplicationRunner或CommandLineRunner的run()方法的话,可以使用Order注解或实现Ordered接口.

对CustomApplicationRunner稍作调整,让其实现Ordered接口,改动后代码如下:

package geek.springboot.application.runner;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.boot.ApplicationArguments;  
import org.springframework.boot.ApplicationRunner;  
import org.springframework.core.Ordered;  
import org.springframework.stereotype.Component;  
  
import java.util.Arrays;  
  
/**  
* 自定义{@link ApplicationRunner}实现  
*  
* @author Bruse  
*/  
@Slf4j  
@Component  
public class CustomApplicationRunner implements ApplicationRunner, Ordered {  
  
    /**  
    * 在SpringApplication启动完成后,该方法会被回调,可以在这里做一些操作  
    *  
    * @param args 启动Java Application时设置的程序参数  
    * @throws Exception 异常  
    */  
    @Override  
    public void run(ApplicationArguments args) throws Exception {  
        log.info("arguments is {}", Arrays.toString(args.getSourceArgs()));  
    }  
  
    @Override  
    public int getOrder() {  
        // 返回优先级,数值越小,优先级越高  
        return 0;  
    }  
}

对CustomCommandLineRunner稍作调整,给其加上@Order注解,代码如下:

package geek.springboot.application.runner;  
  
import lombok.extern.slf4j.Slf4j;  
import org.springframework.boot.CommandLineRunner;  
import org.springframework.core.annotation.Order;  
import org.springframework.stereotype.Component;  
  
import java.util.Arrays;  
  
  
/**  
* 自定义{@link CommandLineRunner}实现  
*/  
@Slf4j  
@Order(-1) // 数值越小,优先级越高  
@Component  
public class CustomCommandLineRunner implements CommandLineRunner {  
  
    /**  
    * 在SpringApplication启动完成后,该方法会被回调,可以在这里做一些操作  
    *  
    * @param args 启动Java Application时设置的程序参数  
    * @throws Exception 异常  
    */  
    @Override  
    public void run(String... args) throws Exception {  
        log.info("args is {}", Arrays.toString(args));  
    }  
  
}

CustomCommandLineRunner定义的优先级比CustomApplicationRunner高,也就是CustomCommandLineRunner的run()永远优于CustomApplicationRunner的run(),控制台输出如下:

image.png

注意不要做耗时的任务

本质上启动SpringApplication的线程,和回调ApplicationRunner、CommandLineRunner的run()方法的线程是同一个,所以注意不要在run()中执行过于复杂耗时的任务.

源码分析

查看SpringApplication的run()方法,关键代码如下:

image.png

查看callRunners()方法,可以看到逻辑非常简单,就是获取所有ApplicationRunner和CommandLineRunner的实现,然后做一个优先级排序,最后回调run()方法.

image.png

image.png

而且从源码中还可以看出,ApplicationRunner和CommandLineRunner的run()回调,是在ApplicationReadyEvent事件广播之前,核心代码如下:

image.png

结尾

本文章源自《Learn SpringBoot》专栏,感兴趣的话还请关注点赞收藏.

上一篇文章:《SpringBoot核心特性——应用事件监听

推荐阅读