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

news2024/11/26 12:43:48

《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 启动运行阶段,敬请期待!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于FPGA的音视频监视器,音视频接口采集器的应用

① 支持1路HDMI1路SDI 输入 ② 支持1路HDMI输出 ③ 支持1080P高清屏显示实时画面以 及叠加的分析结果 ④ 支持同时查看波形图&#xff08;亮度/RGB&#xff09;、 直方图、矢量图 ⑤ 支持峰值对焦、斑马纹、伪彩色、 单色、安全框遮幅标记 ⑥ 支持任意缩放画面&#xff0c;支…

【Java EE】数据库连接池详解

文章目录 &#x1f38d;数据库连接池&#x1f338;Hikari&#x1f338;Druid &#x1f340;MySQL开发企业规范⭕总结 &#x1f38d;数据库连接池 在上⾯Mybatis的讲解中,我们使⽤了数据库连接池技术,避免频繁的创建连接,销毁连接 下⾯我们来了解下数据库连接池 数据库连接池负…

如何利用代理IP进行SEO优化?

“SEO”这个词相信对于做在线业务的朋友来说一定不陌生。 在网络营销中&#xff0c;SEO是至关重要的一环&#xff0c;对于增加有机流量、提升品牌知名度、增加网站的信任度和权威性非常有效。而代理IP在SEO优化中有着不可或缺的作用&#xff0c;它可以帮助网站管理员和SEO专家…

[muduo网络库]——muduo库的Reactor模型(剖析muduo网络库核心部分、设计思想)

一、前言 在学习 C 服务端的过程中&#xff0c;必不可少的一项就是熟悉一个网络库&#xff0c;包括网络库的应用和其底层实现。我们熟知的网络库有 libevent、libev、muduo、Netty 等&#xff0c;其中 muduo 是由陈硕大佬个人开发的 TCP 网络库&#xff0c;最近跟着课程正在深…

回炉重造java----单列集合

体系结构: 集合主要分为两种&#xff0c;单列集合collection和双列集合Map&#xff0c;区别在于单列集合一次插入一条数据&#xff0c;而双列的一次插入类似于key-value的形式 单列集合collection 注:红色的表示是接口&#xff0c;蓝色的是实现类 ①操作功能: 增加: add()&am…

上亿用户面临风险!小米、WPS等知名安卓应用竟藏有“文件覆盖”漏洞

Google Play商店中的几款热门安卓应用程序容易受到与路径遍历相关的漏洞攻击&#xff0c;该漏洞的代号为“Dirty Stream”攻击&#xff0c;恶意应用程序可能会利用此漏洞覆盖易受攻击的应用程序主目录中的任意文件。 微软威胁情报团队的Dimitrios Valsamaras在周三发布的一份报…

【最新点云数据增强综述】深度学习点云数据增强技术的进展

深度学习(DL)已成为点云分析任务(如检测、分割和分类)的主流和有效方法之一。为了减少深度学习模型训练过程中的过拟合,提高模型性能,尤其是在训练数据的数量和/或多样性有限的情况下,增强往往至关重要。虽然各种点云数据增强方法已被广泛应用于不同的点云处理任务中,但…

9.为什么有时候会“烫烫烫”——之函数栈桢

目录 1. 什么是函数栈帧 2. 理解函数栈帧能解决什么问题呢&#xff1f; 3. 函数栈帧的创建和销毁解析 3.1 什么是栈&#xff1f; 3.2 认识相关寄存器和汇编指令 3.3 解析函数栈帧的创建和销毁 小知识&#xff1a;烫烫烫~ Q&A 1. 什么是函数栈帧 我们在写C语言代码…

2024 年 数维杯(A题)大学生数学建模挑战赛 | 多源机会信号建模| 数学建模完整代码+建模过程全解全析

2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注哦 https://mbd.pub/o/bread/ZpWakpdq https://mbd.pub/o/bread/ZpWakpdq 2024数维杯数学建模A题B题C题思路模型代码&#xff08;开赛后第一时间更新&#xff09;及时留意关注…

leetcode63.跳跃游戏2(动态规划)

问题描述&#xff1a; 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish”&#xff09;。 现在考虑网格中有障碍物…

vue项目中使用websocke即时通讯实现系统公告实时获取并提醒

一、使用场景 发布者设置需要发布的公告内容、公告接收用户和发布时间&#xff0c;到达发布时间时及时通知提醒已登录系统用户&#xff0c;使用websocke来实现前端与服务器保持长连接&#xff0c;以便实时过去公告信息。 WebSocket是一种在单个TCP连接上进行全双工通信的协议…

17.Blender RC大佬EEVEE皮肤节点预设导入

如何添加节点预设 在底下的左下角打开Geometry Node Editor 选中正方体&#xff0c;点击新建 当鼠标指针在两个模块之间&#xff0c;是十字的样子时 可以拖出一个新的板块 然后打开文件浏览器 找到节点预设然后拖入到底下的节点编辑界面就可以了或者是blend文件&#xf…

微信小程序流量主如何自定义广告组件后台控制广告显示方式附源码[收藏]

最近开发了一个微信小程序&#xff0c;开通了流量主&#xff0c;引用广告显示。本教程干货满满&#xff0c;附上代码&#xff0c;建议**【收藏点赞】** 微信小程序广告有以下几种&#xff1a;Banner广告、激励广告、插屏广告、视频广告、视频贴片广告、封面广告。 为了增加广告…

pycharm如何对for循环中第n次循序执行断点

目录 在 PyCharm 中&#xff0c;您可以设置条件断点来实现这个功能&#xff0c;这样只有在满足特定条件时断点才会被触发。以下是设置仅在 for 循环的第 n 次迭代时触发断点的步骤&#xff1a; 设置断点&#xff1a; 首先&#xff0c;找到您想要在 for 循环中设置断点的行。点击…

找最大数字-第12届蓝桥杯国赛Python真题解析

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第60讲。 找最大数字&#…

【C++】C/C++中新const用法:const成员

欢迎来到CILMY23的博客 本篇主题为&#xff1a; C/C中新const用法&#xff1a;const成员 个人主页&#xff1a;CILMY23-CSDN博客 系列专栏&#xff1a;Python | C | C语言 | 数据结构与算法 | 贪心算法 | Linux 感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞…

如何设置海外虚拟IP的地址?

经济全球化发展&#xff0c;需要使用到海外ip的场景越来越多&#xff0c;比如跨境电商、海外投放、市场调研等等。海外虚拟ip地址已经成为了个人和企业不可或缺的工具。那么作为用户&#xff0c;该如何设置海外虚拟IP的地址&#xff1f; 设置海外IP的方式有以下几种&#xff1a…

栈结构(c语言)

1.栈的概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。 压栈&am…

Day2:调节屏幕驱动

Day2调节屏幕驱动 原理图&#xff1a; 要想调节屏幕驱动

泛微OA中,设置明细表某一列隐藏

泛微OA中&#xff0c;设置明细表的某一列字段进行隐藏 最近在接到的需求中&#xff0c;要求在主表中选择的平台类型为亚马逊的时候&#xff0c;在新增明细表数据时需要做到实时的提醒&#xff0c;例如&#xff1a;选择亚马逊时&#xff0c;所填的渠道不能为空 这个时候&#x…