• Spring Boot 2.x系列【10】功能篇之使用 ApplicationRunner 、CommandLineRunner


    有道无术,术尚可求,有术无道,止于术。

    本系列Spring Boot版本2.7.0

    概述

    在应用程序启动后,需要执行特定的代码,比如加载缓存数据、打印自定义启动信息等。

    Spring Boot 为我们提供了ApplicationRunnerCommandLineRunner两个接口来实现上面的需求。

    在应用程序启动类SpringApplicationrun方法中,可以看到在最后调用了一个callRunners方法:

    在这里插入图片描述

    callRunners方法中,会在上下文中查询ApplicationRunnerCommandLineRunner类型的Bean 对象,并调用他们的run 方法运行:

    	private void callRunners(ApplicationContext context, ApplicationArguments args) {
    		List<Object> runners = new ArrayList<>();
    		runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
    		runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
    		AnnotationAwareOrderComparator.sort(runners);
    		for (Object runner : new LinkedHashSet<>(runners)) {
    			if (runner instanceof ApplicationRunner) {
    				callRunner((ApplicationRunner) runner, args);
    			}
    			if (runner instanceof CommandLineRunner) {
    				callRunner((CommandLineRunner) runner, args);
    			}
    		}
    	}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    由此可见,我们只需要注册ApplicationRunnerCommandLineRunner类型的Bean ,就可以实现在应用启动最后阶段执行特定的代码。

    ApplicationRunner

    ApplicationRunner只定义了一个run方法用于在启动完成后进行方法调用,可以定义多个该类型的Bean ,并且可以通过实现Ordered接口或使用@Order注解进行排序。

    run方法接收一个ApplicationArguments ,也就是应用启动参数,参数具体用法可以参考SpringApplication启动参数使用详解

    @FunctionalInterface
    public interface ApplicationRunner {
    	// 用于运行 bean 的回调
    	void run(ApplicationArguments args) throws Exception;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    案例演示:在应用程序启动完成时,加载字典缓存、打印当前应用的访问地址。

    首先加载缓存,并使用@Order(1)进行排序:

    @Order(1)
    @Component
    public class DictCacheInitializerApplicationRunner implements ApplicationRunner {
    
        @Override
        public void run(ApplicationArguments args) {
            System.out.println("应用启动完成,开始初始化字典缓存....");
            System.out.println("加载中....");
            System.out.println("初始化完成....");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    再编写一个打印访问地址的运行器,设置排序为2:

    @Component
    @Order(2)
    public class AddressInitializerApplicationRunner implements ApplicationRunner {
    
        @Value("${server.port}")
        String port;
    
        @Override
        public void run(ApplicationArguments args) {
            System.out.println("应用访问地址:http://localhost:" + port);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    启动程序,可以看到在启动完成后执行了响应的代码,@Order数值越小越先执行:
    在这里插入图片描述

    CommandLineRunner

    CommandLineRunnerApplicationRunner作用用法一样,区别在于他们的参数不同,CommandLineRunner传入的参数是原始的参数集合,比如--name=zhangsan,所以一般很少用到,也就不赘述了。

    @FunctionalInterface
    public interface CommandLineRunner {
    
    	void run(String... args) throws Exception;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
  • 相关阅读:
    Andorid获取原生GPS定位信息
    随机数(新标准)
    C++与C的区别终于说清楚了!
    数据结构知识点补充
    LeetCode 122. 买卖股票的最佳时机 II
    傻白入门芯片设计,IP, MCM, SiP, SoC 和 Chiplet的区别(二)
    棒球省队建设实施办法·棒球1号位
    为什么需要Code Review?
    js继承的几种方式(原型链继承、构造函数继承、组合式继承、寄生组合式继承、ES6的Class类继承)
    PMP备考大全:经典题库(敏捷管理第6期)
  • 原文地址:https://blog.csdn.net/qq_43437874/article/details/125601382