Spring Boot 3启动加载器详解(含源码解析)

server/2024/11/27 21:31:33/

一、引言

Spring Boot 3启动加载器是提升开发效率和应用程序启动速度的关键组件。本文将详细介绍Spring Boot 3的启动加载器,包括其实现方式、应用场景及工作原理等。

说明:本文分析使用的Spring Boot源码版本为3.3.5

二、启动加载器简介

启动加载器在Spring Boot中扮演着重要的角色,它允许开发者在应用程序启动时执行一些初始化任务。Spring Boot提供了两种主要的启动加载器接口:CommandLineRunner和ApplicationRunner。通过实现这两个接口,开发者可以定义在应用程序启动时需要执行的代码。

三、启动加载器实现方式及区别

实现方式

1、CommandLineRunner接口
CommandLineRunner接口允许开发者在Spring Boot应用程序启动时执行代码,并接收命令行参数。实现该接口需要覆盖run方法,并注册为Spring容器中的Bean。

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

下面是该接口的源码中的说明:
CommandLineRunner源码

核心内容是:

  • 用于指示当一个 Bean 被包含在 SpringApplication 中时应该运行的接口。
  • 同一个应用上下文中可以定义多个 CommandLineRunner Bean ,并且可以通过实现 Ordered 接口或使用 @Order 注解来对它们进行排序。
  • 如果需要访问 ApplicationArguments 而不是原始的字符串数组,可以考虑使用 ApplicationRunner。

2、ApplicationRunner接口
ApplicationRunner接口与CommandLineRunner类似,也是一个函数式接口,但它接收的参数是ApplicationArguments,而不是简单的字符串数组。ApplicationArguments提供了更丰富的参数处理功能,如获取源参数、选项名称等。

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

下面是该接口的源码中的说明:
ApplicationRunner源码

核心内容是:

  • 用于指示当一个 Bean 被包含在 SpringApplication 中时应该运行的接口。
  • 同一个应用上下文中可以定义多个 ApplicationRunner Bean,并且可以通过实现Ordered接口或使用@Order 注解来对它们进行排序。

3、 使用@Order注解
@Order注解可以用来指定多个启动加载器的执行顺序。数值越小,优先级越高。

@Component@Order(1)public class FirstCommandLineRunner implements CommandLineRunner {// ...}@Component@Order(2)public class FirstApplicationRunner implements ApplicationRunner {// ...}

两种实现方式的区别

CommandLineRunner和ApplicationRunner是两种启动加载器接口,它们的主要区别在于参数类型和灵活性。

CommandLineRunner

  • 参数类型:CommandLineRunner接口的run方法接收一个String[]类型的参数,这个参数包含了启动应用时传递的命令行参数。
  • 灵活性:由于CommandLineRunner直接接收字符串数组作为参数,因此它提供了对命令行参数的基本访问。然而,这种访问方式相对简单,没有提供对参数进行进一步解析或分类的功能。
  • 使用场景:当应用需要快速访问命令行参数,并且不需要对参数进行复杂解析时,CommandLineRunner是一个合适的选择。

ApplicationRunner

  • 参数类型:ApplicationRunner接口的run方法接收一个ApplicationArguments类型的参数。ApplicationArguments是一个更复杂的对象,它提供了对命令行参数的详细访问,包括原始参数、选项参数、非选项参数等。
  • 灵活性:ApplicationRunner通过ApplicationArguments对象提供了对命令行参数的丰富访问方式。这使得开发者可以更方便地解析和处理命令行参数,包括区分选项参数和非选项参数,以及获取参数的默认值等。
  • 使用场景:当应用需要处理复杂的命令行参数,或者需要对参数进行精细分类和解析时,ApplicationRunner是更合适的选择。

四、应用场景

启动加载器在Spring Boot应用程序中有广泛的应用场景,包括但不限于:

  • 初始化数据:在应用启动时加载或初始化必要的数据,如数据库表结构、缓存配置等。
  • 配置检查:验证应用程序的配置是否正确。
  • 第三方服务调用:在启动时调用第三方服务进行必要的初始化。
  • 日志记录:记录应用启动的时间、版本信息等日志信息。
  • 版本兼容性检查:检查依赖库或第三方服务的版本兼容性,确保应用能够正常运行。

五、工作原理

Spring Boot的启动加载器工作原理相对简单,但非常有效。在应用程序启动时,Spring Boot会查找所有实现了CommandLineRunner和ApplicationRunner接口的Bean,并按照优先级顺序(通过@Order注解或默认的排序规则)调用它们的run方法。

具体来说,Spring Boot应用启动时,org.springframework.boot.SpringApplication#run(java.lang.String…)方法会调用callRunners方法,该方法会获取所有实现了启动加载器接口的Bean,并进行排序。然后,它会遍历这些Bean,并调用它们的run方法。

启动加载器调用栈

源码如下:

public ConfigurableApplicationContext run(String... args) {// ...callRunners(context, applicationArguments);// ...
}private void callRunners(ConfigurableApplicationContext context, ApplicationArguments args) {ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();String[] beanNames = beanFactory.getBeanNamesForType(Runner.class);Map<Runner, String> instancesToBeanNames = new IdentityHashMap<>();for (String beanName : beanNames) {instancesToBeanNames.put(beanFactory.getBean(beanName, Runner.class), beanName);}Comparator<Object> comparator = getOrderComparator(beanFactory).withSourceProvider(new FactoryAwareOrderSourceProvider(beanFactory, instancesToBeanNames));instancesToBeanNames.keySet().stream().sorted(comparator).forEach((runner) -> callRunner(runner, args));}

callRunners 方法的主要功能是从给定的 ConfigurableApplicationContext 中获取所有实现了 Runner 接口的 Bean,并按照一定的顺序调用这些 Bean 的 run 方法。

  1. 获取 Bean 工厂:从 context 中获取 ConfigurableListableBeanFactory。
  2. 获取 Bean 名称:从 Bean 工厂中获取所有实现了 Runner 接口的 Bean 的名称。
  3. 创建映射:创建一个 Map,将每个 Runner 实例与其对应的 Bean 名称关联起来。
  4. 排序:使用 getOrderComparator 获取一个排序器,并设置一个源提供者,以便根据依赖关系对 Runner 实例进行排序。
  5. 调用 Runner:遍历排序后的 Runner 实例,并依次根据 Runner 实现的具体接口(ApplicationRunner 或 CommandLineRunner)调用相应的 run 方法。

六、总结

Spring Boot 3的启动加载器为开发者提供了一个灵活而强大的机制,用于在应用程序启动时执行必要的初始化任务。通过实现CommandLineRunner或ApplicationRunner接口,并结合@Order注解,开发者可以轻松地定义和管理启动加载器,从而提升应用程序的启动速度和开发效率。

在实际开发中,合理利用启动加载器可以大大简化初始化任务的编写和管理,使应用程序更加健壮和易于维护。这些启动加载器在初始化数据、安全检查、日志记录等场景中发挥着重要作用,有助于提升应用的稳定性和可靠性。


http://www.ppmy.cn/server/145437.html

相关文章

postman的简单使用

导语&#xff1a;开发过程中免不了要使用postman发起并查看一些请求情况&#xff0c;以下为常用的一些postman的简单使用。 一、postman快速导入一个网页请求 1.右键请求 -->复制 -->以cURL(bash)格式复制 2.打开postman -->点击import --> 选择Raw text -->…

Java 爬虫深度解析销量和商品详情数据获取

一、Java 爬虫概述 什么是 Java 爬虫 Java 爬虫是使用 Java 编程语言编写的程序&#xff0c;用于自动访问网页并提取其中的信息。它可以模拟浏览器的行为&#xff0c;发送 HTTP 请求&#xff0c;接收服务器的响应&#xff0c;并解析网页中的内容&#xff0c;如文本、图片、…

AI助力PPT创作:从手动到智能,打造高效演示

在今天这个信息化时代&#xff0c;演示文稿已经成为我们表达观点、传递信息的重要工具。不论是企业汇报、学术交流&#xff0c;还是个人创作&#xff0c;PPT&#xff08;PowerPoint&#xff09;都在日常生活中扮演着不可或缺的角色。创建一份高质量的PPT往往需要花费大量时间与…

Docker 启动和停止的精准掌舵:操控指南

Docker 启动和停止的精准掌舵&#xff1a;操控指南 Docker是一个开源的应用容器引擎&#xff0c;基于Go语言开发&#xff0c;能够让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中&#xff0c;然后发布到任何流行的Linux机器上&#xff0c;也可以实现虚拟化。Do…

WPF 加载页面的三种方式(瞬时加载,延迟加载,异步行为)

在WPF中&#xff0c;瞬时加载、延迟加载和异步行为分别适用于不同的场景&#xff0c;它们各自的实现方式和用途如下&#xff1a; 1. 瞬时加载 定义&#xff1a; 在赋值或初始化时&#xff0c;视图和数据会立即加载&#xff0c;所有的逻辑在主线程上完成。视图在 UI 上的渲染…

学习Prompt Turning

传统的微调因为代价很高&#xff0c;而且一旦权重很大&#xff0c;这种fine 微微的意思是调不动模型的&#xff0c;所以需要这种提示词调 mindnlp直接有 peft config peft_config PromptTuningConfig(task_type“SEQ_CLS”, num_virtual_tokens10) 方便我们进行prompt tunin…

0基础学前端系列 -- 前端的存储方式

前端存储方式全解析&#xff1a;选择最适合你的解决方案 在现代Web开发中&#xff0c;存储用户数据和状态信息是至关重要的。随着应用程序的复杂性增加&#xff0c;开发者需要选择合适的存储机制来管理用户信息。本文将深入探讨前端的存储方式&#xff0c;包括 Session、Cooki…

【linux】shell脚本

文章目录 1. jar包启动脚本1.1 方式一1.2 方式二 2. 进程关闭脚本3. 操作mysql4. impala建表语句提取5. 监控磁盘存量6. 清日志脚本7. 替换tomcat的启动端口8. 将一行数据按照空格依次读取 1. jar包启动脚本 1.1 方式一 #!/bin/sh RESOURCE_NAME/usr/local/applications/scre…