Spring命令列引數封裝CommandLineArgs
阿新 • • 發佈:2018-12-03
本文程式碼基於 Springboot 2.1.0
概述
Spring對應用程式執行的命令列引數進行了抽象,這個抽象是類CommandLineArgs
。
CommandLineArgs
類將命令列引數分為兩類:
- option 引數
- 以
--
開頭 - 可以認為是
name/value
對引數 - 例子 :
--foo, --foo=bar
- 以
- 非 option 引數
- 不以
--
開頭 - 可以認為是隻提供了value的引數(具體怎麼理解這個值,看業務邏輯的需求)
- 不以
原始碼解析
其原始碼如下:
package org.springframework.core.env;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.springframework.lang.Nullable;
class CommandLineArgs {
private final Map<String, List<String>> optionArgs = new HashMap<>();
private final List<String> nonOptionArgs = new ArrayList<>();
/**
* Add an option argument for the given option name and add the given value to the
* list of values associated with this option (of which there may be zero or more).
* The given value may be {@code null}, indicating that the option was specified
* without an associated value (e.g. "--foo" vs. "--foo=bar").
* 新增option引數,例如 --foo, --foo=bar 這樣的引數
* 同名option引數可以有多個值,比如同時提供了 --id=1 --id=2 這樣的引數
*/
public void addOptionArg(String optionName, @Nullable String optionValue) {
if (!this.optionArgs.containsKey(optionName)) {
this.optionArgs.put(optionName, new ArrayList<>());
}
if (optionValue != null) {
this.optionArgs.get(optionName).add(optionValue);
}
}
/**
* Return the set of all option arguments present on the command line.
* 獲取所有option引數的名稱列表
*/
public Set<String> getOptionNames() {
return Collections.unmodifiableSet(this.optionArgs.keySet());
}
/**
* Return whether the option with the given name was present on the command line.
* 是否包含某個指定名稱的option引數
*/
public boolean containsOption(String optionName) {
return this.optionArgs.containsKey(optionName);
}
/**
* Return the list of values associated with the given option. null signifies
* that the option was not present; empty list signifies that no values were associated
* with this option.
* 獲取指定名稱的option引數的值,如果命令列中沒有這個option引數,返回null;
* 因為一個option引數可能會被指定多個值,所以返回的是一個列表
*/
@Nullable
public List<String> getOptionValues(String optionName) {
return this.optionArgs.get(optionName);
}
/**
* Add the given value to the list of non-option arguments.
* 增加一個非option引數,一個非option引數可以被認為是隻有value的一個引數,
*/
public void addNonOptionArg(String value) {
this.nonOptionArgs.add(value);
}
/**
* Return the list of non-option arguments specified on the command line.
* 返回所有非option引數
*/
public List<String> getNonOptionArgs() {
return Collections.unmodifiableList(this.nonOptionArgs);
}
}
通過例子說明用途
當我們使用springboot開發一個應用時,假如我們為應用程式提供了命令列引數--pageNo=2 --pageSize=20 --id=1 --id=2 Beijing
,通過這個命令列引數我們想告訴應用程式的是:找出Beijing地區,使用者id為1或者2的所有訂單記錄,返回結果集中的第二頁,每頁容量為10行資料。針對該例子,實際上springboot就將其封裝成了一個CommandLineArgs
物件:
// SpringApplication 類原始碼部分
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);//<=== 構造一個應用程式引數物件,輸入引數是命令列引數列表(String[]型別)
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
// DefaultApplicationArguments類程式碼片段
public DefaultApplicationArguments(String[] args) {
Assert.notNull(args, "Args must not be null");
// Source 是一個 DefaultApplicationArguments 靜態內部類,繼承自 SimpleCommandLinePropertySource
this.source = new Source(args); //<==== 繼續傳遞原始命令列引數列表
this.args = args;
}
// SimpleCommandLinePropertySource 程式碼片段
public SimpleCommandLinePropertySource(String... args) {
// 使用一個SimpleCommandLineArgsParser物件分析原始的命令列引數列表,返回結果型別為CommandLineArgs
super(new SimpleCommandLineArgsParser().parse(args));
}
實際上,SimpleCommandLineArgsParser
其實是Spring的一個命令列引數列表分析工具,它的目的就是將原始的命令列引數列表分析處理後儲存為一個CommandLineArgs
物件。就上面的例子而言,最終的CommandLineArgs
物件如下:
留意上面例子中關於多值option引數的處理