0
点赞
收藏
分享

微信扫一扫

【SpringBoot 一】SpringApplication启动类的Args详解


Args 作用


传递参数的一种方式; 例如启动的时候 ​​java -jar --spring.profiles.active=prod​​ 或者更改自己的自定义配置信息 ;使用方式是 ​​--key=value​​ 它的配置优先于项目里面的配置;


我们现在大部分项目都是用SpringBoot进行开发的,一般启动类的格式是

​SpringApplication.run(SpringBootDemoPropertiesApplication.class, args);​

但是好像平常一直也没有用到args; 也没有穿过参数,那么这个args究竟有什么用呢?我们随着源码一探究竟!

启动一个带web的项目,并且在​​application.yml​​配置文件里面定义一个自定义属性​​developer. name=test​

以下是启动类, args设置一些参数

@SpringBootApplication
public class SpringBootDemoPropertiesApplication {

public static void main(String[] args) {
args = new String[]{"1","2","--name=shienchuang","--name=shizhenzhen","age=18","--developer.name=shirenchuang666"};
SpringApplication.run(SpringBootDemoPropertiesApplication.class, args);
}
}

Args使用场景一

进入run方法看到 args第一次出现在 ​​SpringApplication​​类中的

private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}

方法中​​getSpringFactoriesInstances( SpringApplicationRunListener.class, types, this, args)​​ 用于实例化 ​​SpringApplicationRunListener​​的实现类(配置在spring.factories中的实现类)

关于​​spring.factories​​的用法可以参考: 【SpringBoot 二】spring.factories加载时机分析

此项目中只在​​spring.factories​​找到了一个实现类​​org.springframework.boot.context.event.EventPublishingRunListener​

【SpringBoot 一】SpringApplication启动类的Args详解_数据源

在实例化 的过程中是有把 两个参数{SpringApplication 和 String[] args} 传递过去的

【SpringBoot 一】SpringApplication启动类的Args详解_spring boot_02

那么对应到的构造函数就是

【SpringBoot 一】SpringApplication启动类的Args详解_spring boot_03

并且可以看到在​​EventPublishingRunListener​​的方法中都有把Args传递下去;

Args使用场景二

上面的​​SpringApplicationRunListeners​​完事之后,接下来就到了

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

SimpleCommandLinePropertySource

主要看上面的 new Source(args)方法; 这个Source继承了类​​SimpleCommandLinePropertySource​

【SpringBoot 一】SpringApplication启动类的Args详解_源码_04

那么SimpleCommandLinePropertySource作用是什么?


SimpleCommandLinePropertySource也是一个数据源PropertySource ;但是它主要是存放命令行属性;例如启动参数Args;中的属性就会保存在这个对象中; 并且SimpleCommandLinePropertySource会被放入到Environment中; 所以也就可以通过{@link Environment#getProperty(String)}来获取命令行的值了


public SimpleCommandLinePropertySource(String... args) {
super(new SimpleCommandLineArgsParser().parse(args));
}

看构造函数 可以知道实例化之后的​​SimpleCommandLinePropertySource​​​ 是name为​​commandLineArgs​​ 的数据源; 属性值的解析规则如下

  • –key=value key=value的前面接上两个- 就会解析成kv格式
  • key可以相同 ,并且value可以多个; 她是一个List接口;一个key可以对应多个value
  • 不能有空格
  • 如果不是 --key=value的格式,那么都会被解析到一个 key为​​nonOptionArgs​​的list中

【SpringBoot 一】SpringApplication启动类的Args详解_源码_05

往下面走到了

protected void configurePropertySources(ConfigurableEnvironment environment,
String[] args) {
MutablePropertySources sources = environment.getPropertySources();
if (this.defaultProperties != null && !this.defaultProperties.isEmpty()) {
sources.addLast(
new MapPropertySource("defaultProperties", this.defaultProperties));
}
if (this.addCommandLineProperties && args.length > 0) {
String name = CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME;
if (sources.contains(name)) {
PropertySource<?> source = sources.get(name);
CompositePropertySource composite = new CompositePropertySource(name);
composite.addPropertySource(new SimpleCommandLinePropertySource(
"springApplicationCommandLineArgs", args));
composite.addPropertySource(source);
sources.replace(name, composite);
}
else {
sources.addFirst(new SimpleCommandLinePropertySource(args));
}
}
}

这个方法的作用就是把 我们的Args 放到到Spring的 ​​environment​​中;

​sources.addFirst(new SimpleCommandLinePropertySource(args));​

看到方法是 addFirst(); 这个说明什么?说明命令行的的数据源被放到了最前面;那么命令行数据源的属性就会被最优先采用;

【SpringBoot 一】SpringApplication启动类的Args详解_数据源_06

那么我们就可以通过​​Environment#getProperty(String)​​ 获取args中的值了;

那么我们可以利用这个args做什么用;?

可以用它来写入 配置; 并且是覆盖项目中的配置(因为他的优先级更高);

例如 ​​java -jar --spring.profiles.active=dev​

【SpringBoot 一】SpringApplication启动类的Args详解_命令行_07

这里就算yml配置的是prod;最终使用的是dev;

【SpringBoot 一】SpringApplication启动类的Args详解_数据源_08



举报

相关推荐

0 条评论