写点什么

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

  • 2022 年 8 月 28 日
    江西
  • 本文字数:2408 字

    阅读完需:约 8 分钟

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

作者石臻臻,CSDN 博客之星 Top5Kafka Contributornacos Contributor华为云 MVP,腾讯云 TVP,滴滴 Kafka 技术专家 KnowStreaming


KnowStreaming 是滴滴开源的Kafka运维管控平台, 有兴趣一起参与参与开发的同学,但是怕自己能力不够的同学,可以联系我,当你导师带你参与开源!

Args 作用


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

我们现在大部分项目都是用 SpringBoot 进行开发的,一般启动类的格式是SpringApplication.run(SpringBootDemoPropertiesApplication.class, args);但是好像平常一直也没有用到 args; 也没有穿过参数,那么这个 args 究竟有什么用呢?我们随着源码一探究竟!

启动一个带 web 的项目,并且在application.yml配置文件里面定义一个自定义属性developer. name=test以下是启动类, args 设置一些参数

@SpringBootApplicationpublic 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); }}

复制代码

1Args 使用场景一

进入 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


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

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


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

2Args 使用场景二

上面的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

那么 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 中


往下面走到了

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(); 这个说明什么?说明命令行的的数据源被放到了最前面;那么命令行数据源的属性就会被最优先采用;


那么我们就可以通过Environment#getProperty(String) 获取 args 中的值了;那么我们可以利用这个 args 做什么用;?

可以用它来写入 配置; 并且是覆盖项目中的配置(因为他的优先级更高);例如 java -jar --spring.profiles.active=dev

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

在这里插入图片描述

发布于: 刚刚阅读数: 3
用户头像

关注公众号: 石臻臻的杂货铺 获取最新文章 2019.09.06 加入

进高质量滴滴技术交流群,只交流技术不闲聊 加 szzdzhp001 进群 20w字《Kafka运维与实战宝典》PDF下载请关注公众号:石臻臻的杂货铺

评论

发布
暂无评论
【SpringBoot 一】SpringApplication启动类的Args详解_spring-boot_石臻臻的杂货铺_InfoQ写作社区