【Spring Boot 源码学习】深入 ApplicationArguments 接口及其默认实现

《Spring Boot 源码学习系列》

在这里插入图片描述

深入 ApplicationArguments 接口及其默认实现

  • 一、引言
  • 二、主要内容
    • 2.1 ApplicationArguments
    • 2.2 DefaultApplicationArguments
      • 2.2.1 成员变量
      • 2.2.2 构造方法
      • 2.2.3 成员方法
    • 2.3 SimpleCommandLinePropertySource
    • 2.4 应用场景
      • 2.4.1 准备和配置应用环境
      • 2.4.2 准备和配置应用上下文
      • 2.4.3 刷新应用上下文之后【afterRefresh方法】
      • 2.4.4 调用运行器【callRunners方法】
  • 三、总结

一、引言

在 《SpringApplication 的 run 方法核心流程介绍》 博文中,我们知道了 ApplicationArgumentsSpring Boot 中用于获取 应用程序启动参数 的接口,其默认实现是 DefaultApplicationArguments

不过有关内容尚未详细介绍,本篇就带大家深入分析下 ApplicationArguments 接口及其默认实现。

在这里插入图片描述

二、主要内容

注意: 以下涉及 Spring Boot 源码 均来自版本 2.7.9,其他版本有所出入,可自行查看源码。

2.1 ApplicationArguments

首先来看 应用程序启动参数接口类 ApplicationArguments 的源码:

public interface ApplicationArguments {
	String[] getSourceArgs();
	Set<String> getOptionNames();
	boolean containsOption(String name);
	List<String> getOptionValues(String name);
	List<String> getNonOptionArgs();
}

ApplicationArguments 接口共包含 5 个方法,均用于运行 SpringApplication 的参数的访问:

  • getSourceArgs:该方法返回传递给应用程序的原始未处理参数。
  • getOptionNames:该方法返回所有选项参数的名称,如果没有则返回一个空集。例如,如果参数是 "--foo=bar --debug",则返回值应为 ["foo", "debug"]
  • containsOption:该方法返回从参数中解析出的选项参数集合中是否包含给定名称的选项。如果参数中包含给定名称的选项,则返回 true
  • getOptionValues:该方法返回与给定名称的参数选项关联的值集合。
    • 如果选项存在且没有参数(例如:"--foo"),则返回空集合([])。
    • 如果选项存在且有一个值(例如:"--foo=bar"),则返回包含一个元素的集合(["bar"])。
    • 如果选项存在且有多个值(例如:"--foo=bar --foo=baz"),则返回一个包含每个值的元素的集合(["bar", "baz"])。
    • 如果选项不存在,则返回 null
  • getNonOptionArgs:该方法返回解析出的非选项参数的集合,如果没有则返回一个空列表。

2.2 DefaultApplicationArguments

SpringApplicationrun 方法中,我们可以看到如下标红的内容:

在这里插入图片描述

DefaultApplicationArguments 就是 ApplicationArguments 接口的一个默认实现,还是来看看相关源码:
在这里插入图片描述

2.2.1 成员变量

DefaultApplicationArguments 的成员变量有两个:

  • Source source :私有的静态内部类,继承自 org.springframework.core.env.SimpleCommandLinePropertySourcespring-core 包中的一个类,旨在提供解析命令行参数的最简单方法】
  • String[] args:原始的命令行参数数组

在这里插入图片描述

这个 Source 类是对 SimpleCommandLinePropertySource 的一个简单封装,可以看到它这里只是简单地调用了父类的实现,没有添加任何新的功能或逻辑。当然就目前而言,这个类似乎是多余的,Huazie 猜测这也许是为了将来的扩展吧。

2.2.2 构造方法

public DefaultApplicationArguments(String... args) {
	Assert.notNull(args, "Args must not be null");
	this.source = new Source(args);
	this.args = args;
}

构造方法主要用来初始化上述两个成员变量,它接受一个可变长度的字符串数组作为参数,该参数就是运行 SpringApplication 的命令行参数。

2.2.3 成员方法

在这里插入图片描述

阅读上述源码,可以看到实现的 5 个方法中都跟成员变量 source 有关系。

getOptionNames 方法中,可以看到返回的 Set 集合是通过 Collections.unmodifiableSet 包装过的 Set 集合的不可修改视图。Collections.unmodifiableSet 允许模块向用户提供对内部集合的“只读”访问权限。对返回集合的查询操作将“穿透”到指定的集合,而尝试修改返回的集合(无论是直接修改还是通过其迭代器)都将导致UnsupportedOperationException 异常。如果指定的集合是可序列化的,那么返回的集合也将是可序列化的。

同理,在 getOptionValues 方法中的 Collections.unmodifiableList 方法返回的是 List 集合的不可修改视图。

2.3 SimpleCommandLinePropertySource

上述 2.2.3 中,我们可以看到最终成员方法的处理都是来自 SimpleCommandLinePropertySource 类中的实现方法。

我们来看看相关源码:

在这里插入图片描述

SimpleCommandLinePropertySource 继承自 CommandLinePropertySource<CommandLineArgs>

CommandLinePropertySource<T> 是一个抽象基类,用于实现由命令行参数支持的PropertySource。泛型类型 T 代表命令行选项的底层来源。

SimpleCommandLinePropertySource 中,TCommandLineArgs,它是命令行参数的简单表示,分为 “选项参数”“非选项参数”

在这里插入图片描述

继续看 SimpleCommandLinePropertySource 的构造方法,可以看到 命令行参数 CommandLineArgs 是 通过 SimpleCommandLineArgsParserparse(String... args) 来解析的。

new SimpleCommandLineArgsParser().parse(args);

在这里插入图片描述

2.4 应用场景

有关 ApplicationArguments 的应用场景,我们一步步跟着源码来看:

2.4.1 准备和配置应用环境

首先是 run 方法中,先创建一个 DefaultApplicationArguments 对象,并赋值给 applicationArguments 变量;

接着调用 prepareEnvironment 方法来准备和配置应用环境,并传入 applicationArguments 参数;

在这里插入图片描述

进入 prepareEnvironment 方法,可以看到如下:

在这里插入图片描述

这里是获取了原始的参数数组,并作为入参,传入 configureEnvironment 方法中;

在这里插入图片描述

进入 configurePropertySources 方法,它是用来配置应用程序的环境属性源,可以看到最终 args 参数都会被构建成 SimpleCommandLinePropertySource 的属性源。

在这里插入图片描述

至于 configureProfiles 方法,目前是空实现,留着未来扩展。

2.4.2 准备和配置应用上下文

调用 prepareContext 方法准备和配置应用上下文,并传入 applicationArguments 参数;

在这里插入图片描述

进入 prepareContext 方法,可以看到:

在这里插入图片描述

如上标红处,将 applicationArguments 注册为单例的 Bean 实例,其名称为 springApplicationArguments,后续其他地方需要时,就可以通过该名称从 Spring 容器中获取 applicationArguments

2.4.3 刷新应用上下文之后【afterRefresh方法】

afterRefresh 方法的实现默认为空,可由开发人员自行扩展。

2.4.4 调用运行器【callRunners方法】

callRunners 方法里,主要是调用 ApplicationRunnerCommandLineRunner 的运行方法。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、总结

本篇博文 Huazie 同大家一起深入分析了 ApplicationArguments 接口及其默认实现,相信这些可以进一步加深大家对于 Spring Boot 启动运行阶段中命令参数获取和使用的理解。接下来的博文将会继续聚焦 Spring Boot 启动运行阶段,敬请期待!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/611828.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

shiro-quickstart启动报错

说明&#xff1a;最近在学登录框架&#xff0c;记录一下学习刚shiro框架&#xff0c;启动快速入门样例的错误&#xff1b; 场景 把shiro代码download下来&#xff0c;打开samples&#xff08;样例&#xff09;包&#xff0c;打开快速入门&#xff0c;启动&#xff0c;报错&am…

楼宇自控远程I/O革新BACnet/IP模块在暖通空调系统

在现代智能建筑的浪潮中&#xff0c;BACnet/IP分布式远程I/O控制器正逐步成为暖通空调&#xff08;HAVC&#xff09;系统升级转型的得力助手。本文将以某大型商业综合体为例&#xff0c;揭示BACnet/IP I/O模块如何在复杂多变的环境中发挥其独特优势&#xff0c;实现HVAC系统的智…

Open CASCADE学习|三重正交标架法则

三重正交标架&#xff08;Trihedron&#xff09; 定义:三重正交标架是在三维空间中定义的一个坐标系&#xff0c;由三个互相垂直的向量构成。这些向量分别是&#xff1a; 切线向量&#xff08;Tangent Vector&#xff09; - 表示曲线在某一特定点处的切线方向。 主法线向量&…

网工内推 | 软件测试工程师,有软考中、高级认证优先

01 上海碧蔓智能科技有限公司 招聘岗位&#xff1a;软件测试工程师 职责描述&#xff1a; 1、负责软件产品的测试工作&#xff0c;对测试进度和测试质量负责&#xff1b; 2、参与业务需求、设计方案的讨论&#xff0c;负责编写测试方案、测试计划、测试用例&#xff0c;搭建测…

冲突:故事型游戏的燃料

在故事型游戏中&#xff0c;冲突是推动情节发展的关键因素。没有冲突&#xff0c;故事就会变得平淡无奇&#xff0c;缺乏吸引力。在这篇博客中&#xff0c;我将探讨冲突在故事型游戏中的重要性&#xff0c;以及如何利用冲突为游戏增色添彩。 首先&#xff0c;让我们来了解一下冲…

Spring Boot 整合 Druid

目录 &#x1f34e;前言 &#x1f34a;数据库连接池 &#x1f34a;为什么需要使用数据库连接池 &#x1f34a;常见的连接池分类 &#x1f34e;什么是Druid &#x1f34a;Druid的功能 &#x1f34a;基本配置参数如下&#xff1a; &#x1f34e;整合Druid &#x1f34a;导…

深入解析Java中Set接口

哈喽&#xff0c;各位小伙伴们&#xff0c;你们好呀&#xff0c;我是喵手。运营社区&#xff1a;C站/掘金/腾讯云&#xff1b;欢迎大家常来逛逛 今天我要给大家分享一些自己日常学习到的一些知识点&#xff0c;并以文字的形式跟大家一起交流&#xff0c;互相学习&#xff0c;一…

ai直播-智能化视频直播-全程自动学,高效互动问答!

ai直播-智能化视频直播-全程自动学&#xff0c;高效互动问答&#xff01; 普通人想要致富&#xff0c;光靠勤劳是不可能的&#xff0c;唯有抓住时代风口&#xff0c;才能铸造成功之路。 大家都知道&#xff0c;现在最赚钱的行业&#xff0c;直播和卖货&#xff0c;肯定是名列…

今日arXiv最热NLP大模型论文:NAACL24实锤语言学对大模型“负优化”,抽象语义表示+思维链有损表现

大语言模型正以势不可挡的姿态席卷自然语言处理领域。在这个语言模型大显神威的时代&#xff0c;很多任务都转变为了端到端的文本生成任务。那么&#xff0c;在此之前我们苦心孤诣研究了几十年的语义表示&#xff0c;例如 AMR(抽象意义表示)&#xff0c;在这个时代里还能派上用…

手撕spring框架(5)

手撕spring框架(5) 相关系列 手撕spring框架&#xff08;1&#xff09; 手撕spring框架&#xff08;2&#xff09; 手撕spring框架&#xff08;3&#xff09; 手撕spring框架&#xff08;4&#xff09; 这是本专题最后一节了&#xff0c;主要是讲述自定义一个注解&#xff0c;实…

代码随想录算法训练营第六十二天|503.下一个更大元素II、42.接雨水

代码随想录算法训练营第六十二天|503.下一个更大元素II、42.接雨水 503.下一个更大元素II 给定一个循环数组 nums &#xff08; nums[nums.length - 1] 的下一个元素是 nums[0] &#xff09;&#xff0c;返回 nums 中每个元素的 下一个更大元素 。 数字 x 的 下一个更大的元…

【kernel exploit】CVE-2024-1086 nftables UAF漏洞-Dirty Pagedirectory利用方法

影响版本&#xff1a;Linux v3.15 - v6.7.2。v5.15.149 / v6.1.76 / v6.6.15 / v6.7.3 已修复&#xff0c;包括CentOS、Debian、Ubuntu和KernelCTF等。 注意&#xff0c;本exp适用于v5.14.21~v6.3.13&#xff0c;成功率99.4%&#xff1b;对于v6.4及以上版本的内核&#xff0c;…

buuctf-misc题目练习三

荷兰宽带数据泄露 BIN 文件&#xff0c;也称为二进制文件&#xff0c;是一种压缩文件格式&#xff0c;可以 包含图像和视频等信息 , 并被许多应用程序用于各种目的。 RouterPassView是一个找回路由器密码的工具。 大多数现代路由器允许备份到一个文件路由器的配置&#xff0c…

双目相机标定流程(MATLAB)

一&#xff1a;经典标定方法 1.1OPENCV 1.2ROS ROS进行双目视觉标定可以得到左右两个相机的相机矩阵和畸变系数&#xff0c;如果是单目标定&#xff0c;用ROS会非常方便。 3.MATLAB标定&#xff08;双目标定&#xff09; MATLAB用来双目标定会非常方便&#xff0c;主要是为…

【算法入门赛】A.坐标变换(推荐学习)C++题解与代码

比赛链接&#xff1a;https://www.starrycoding.com/contest/8 题目描述 武汉市可以看做一个二维地图。 牢 e e e掌握了一项特异功能&#xff0c;他可以“瞬移”&#xff0c;每次瞬移需要分别设定 x x x和 y y y的偏移量 d x dx dx和 d y dy dy&#xff0c;瞬移完成后位置会…

电脑设置在哪里打开?Window与Mac双系统操作指南

随着科技的不断发展&#xff0c;电脑已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;对于许多初学者来说&#xff0c;如何找到并熟悉电脑的设置界面可能是一个挑战。特别是对于那些同时使用Windows和Mac双系统的用户来说&#xff0c;更是需要一篇详尽的指南来…

【计算机毕业设计】springboot国风彩妆网站

二十一世纪我们的社会进入了信息时代&#xff0c; 信息管理系统的建立&#xff0c;大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多&#xff0c;而在线管理系统刚好能满足这些需求&#xff0c;在线管理系统突破了传统管理方式的局限性。于是本文针对这一需求设…

ntfs文件系统的优势 NTFS文件系统的特性有哪些 ntfs和fat32有什么区别 苹果电脑怎么管理硬盘

对于数码科技宅在新购得磁盘之后&#xff0c;出于某种原因会在新的磁盘安装操作系统。在安装操作系统时&#xff0c;首先要对磁盘进行分区和格式化&#xff0c;而在此过程中&#xff0c;操作者们需要选择文件系统。文件系统也决定了之后操作的流程程度&#xff0c;一般文件系统…

MySQL存储引擎详解

存储引擎 MySQL体系结构 连接层&#xff1a;与客户端连接&#xff0c;权限校验、连接池服务层&#xff1a;SQL接口和解析、查询优化、缓存、函数引擎层&#xff1a;索引、存储引擎存储层&#xff1a;系统文件、日志&#xff08;Redo、Undo等&#xff09; 存储引擎介绍 不同的…

暴力数据结构之栈与队列(队列详解)

1.队列的定义 队列是一种特殊的线性表&#xff0c;它遵循先进先出&#xff08;FIFO&#xff09;的原则。在队列中&#xff0c;只允许在表的一端进行插入操作&#xff08;队尾&#xff09;&#xff0c;而在另一端进行删除操作&#xff08;队头&#xff09;。这种数据结构确保了最…