SpringBoot外化配置源码解析:外化配置简介、参数处理( 二 )

public class SimpleCommandL inePropertySource extends CommandL inePropertySource {public SimpleCommandL inePropertySource(String... args) {super(new SimpleCommand ineArgsParser() . parse(args));// 重裁的构造方法public SimpleCommandL inePropertySource(String name, String[] args) {super(name, new SimpleCommandL ineArgsParser() . parse(args));}}除了构造方法之外 , SimpleCommandLinePropertySource 还提供 了不同类型参数信息的获取和检查是否存在的功能 , 代码如下 。
public class SimpleCommandL inePropertySource extends Commandl inePropertySource {/获取选项参数数组@0verridepublic String[] getPropertyNames()return StringUtils. toStringArray(this . source . getOpt ionNames());/获取是否包含指定 name 的参数@Overrideprotected boolean containsOption(String name) {return this. source . containsOption(name );/获取指定 name 的选项参数列表@Override@Nullableprotected List getOptionValues(String name) {return this . source . getOpt ionValues(name);//获取非选项参数列表protected List getNonOptionArgs() {return this. source . getNonOptionArgs();}}ApplicationArguments 或者步说是 SimpleCommandLinePropertySource 对参数类型是有所区分的 , 即选项参数和非选项参数 。
选项参数必须以“一”为前缀 , 参数值可为空 , 该参数我们可以通过 SpringBoot 属性处理后使用 , 比如在执行 jar jar 命令时 , 添加选项参数“--app.name=spring boot learn" , 在代码中可通过@Value 属性或其他方式获取到该参数的值 。 该参数可以通过逗号分隔多个参数值 , 或多次使用同一个参数来包含多个参数的值 。
非选项参数并不要求以“--”前缀开始 , 可自行定义 。 非选项参数可以是除了传递的 VM 参数之外的其他参数 。 比如我们可以直接在 jar -jar 命令中定义参数为“non-option”的参数值 。
以上所说的选项参数和非选项参数的解析是在 SimpleCommandLinePropertySource 构造方法中调用的 SimpleCommandLineArgsParser 中完成的 , 代码如下 。
class SimpleCommandL ineArgsParser//解析 args 参数 , 返回一个 完整的 CommandL ineArgs 对象public CommandLineArgs parse(String... args) {CommandL ineArgs commandLineArgs = new CommandL ineArgs();//遍历参数for (String arg : args) {//解析选项参数 , 以"--"开头if (arg. startsWith("--"))String optionText = arg. substring(2, arg.length());String optionName;String optionValue = http://kandian.youth.cn/index/null;//判断是--foo=bar 参数格式 ,还是 foo 参数格式 ,并分别处理获取值if (optionText . contains("=")) {optionName = optionText . substring(0, optionText . index0f('='));optionValue = http://kandian.youth.cn/index/optionText . substring(optionText . indexOf('=' )+1,optionText. length());} elseoptionName = optionText;if (optionName. isEmpty()|| (optionValue != null commandL ineArgs . addOpt ionArg( optionName, optionValue);} else {//处理非选项参数commandL ineArgs . addNon0pt ionArg(arg);return commandLineArgs;}}通过 SimpleCommandLineArgsParser 的代码可以看出 , Spring 对参数的解析是按照指定的 参 数 格 式 分 别 解 析 字 符 串 中 的 值 来 实 现 的。最 终,解 析 的 结 果 均 封 装 在CommandLineArgs 中 。 而 CommandLineArgs 类 只是命令行参数的简单表示形式 , 内部分为“选项参数和“非选项参数” 。
class CommandL ineArgsprivate final Map> optionArgs = new HashMap<>();private final List nonOptionArgs = new ArrayList<>();CommandLineArgs 的核心存储结构包括:存储选项参数的Map> optionArgs 和存储非选项参数的 ListnonOptionArgs 。 同时 , 针对这两个核心存储结构 , Spring Boot 也提供了读写操作的方法 。
SimpleCommandLineArgsParser 解 析 获 得 的 CommandLineArgs 对 象 , 最 终 会 被SimpleCommand-LinePropertySource 的 构 造 方 法 通 过 super 调 用 , 一 层 层 地 传 递 到PropertySource 类的构造方法 ,最终封装到对应的属性当中 。
public abstract class PropertySource {//参数类别名称protected final String name;//参数封装类protected final T source;以在 SimpleCommandLinePropertySource 中的使用为例 , 最终封装在 PropertySource 中的结构为: name 为“commandLineArgs" , source 为解析出 的 CommandLineArgs 对象 。
而DefaultApplicationArguments的内部类Source作为SimpleCommandLinePropertySource 的子类存储了以上解析的数据内容 。 同时 , args 参数的原始值存储在 DefaultApplicationArguments 的 String[ ] args 属性中 。
SpringBoot外化配置源码解析:外化配置简介、参数处理文章插图
使用实例
在实践中我们可能会遇到这样的疑问:如何访问应用程序变量?或者 , 如何访问通过SpringApplication.run(args) 传 入 的 参 数 ? 下 面 我 们 以 具 体 的 例 子 来 说 明 如 何 通 过ApplicationArguments 获得对应的参数 。