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

简介: 【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


image.png

image.png

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

image.png

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

image.png

并且可以看到在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

image.png

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


image.png

image.png

往下面走到了

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


image.png

image.png

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

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


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

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

image.png

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

相关文章
|
5天前
|
Java 数据库 开发者
详细介绍SpringBoot启动流程及配置类解析原理
通过对 Spring Boot 启动流程及配置类解析原理的深入分析,我们可以看到 Spring Boot 在启动时的灵活性和可扩展性。理解这些机制不仅有助于开发者更好地使用 Spring Boot 进行应用开发,还能够在面对问题时,迅速定位和解决问题。希望本文能为您在 Spring Boot 开发过程中提供有效的指导和帮助。
41 12
|
9月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的新闻类网站的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的新闻类网站的详细设计和实现(源码+lw+部署文档+讲解等)
|
4月前
|
Java API Spring
springBoot:注解&封装类&异常类&登录实现类 (八)
本文介绍了Spring Boot项目中的一些关键代码片段,包括使用`@PathVariable`绑定路径参数、创建封装类Result和异常处理类GlobalException、定义常量接口Constants、自定义异常ServiceException以及实现用户登录功能。通过这些代码,展示了如何构建RESTful API,处理请求参数,统一返回结果格式,以及全局异常处理等核心功能。
|
4月前
|
JSON 缓存 前端开发
SpringBoot的 ResponseEntity类讲解(具体讲解返回给前端的一些事情)
本文讲解了SpringBoot中的`ResponseEntity`类,展示了如何使用它来自定义HTTP响应,包括状态码、响应头和响应体,以及如何将图片从MinIO读取并返回给前端。
298 3
|
4月前
|
Java Spring 容器
Springboot3.2.1搞定了类Service和bean注解同名同类型问题修复
这篇文章讨论了在Spring Boot 3.2.1版本中,同名同类型的bean和@Service注解类之间冲突的问题得到了解决,之前版本中同名bean会相互覆盖,但不会在启动时报错,而在配置文件中设置`spring.main.allow-bean-definition-overriding=true`可以解决这个问题。
170 0
Springboot3.2.1搞定了类Service和bean注解同名同类型问题修复
|
7月前
|
Java Spring
idea新建spring boot 项目右键无package及java类的选项
idea新建spring boot 项目右键无package及java类的选项
289 5
|
7月前
|
Java 数据库连接 mybatis
SpringBoot配置Mybatis注意事项,mappers层下的name命名空间,要落实到Dao的video类,resultType要落到bean,配置好mybatis的对应依赖。
SpringBoot配置Mybatis注意事项,mappers层下的name命名空间,要落实到Dao的video类,resultType要落到bean,配置好mybatis的对应依赖。
|
8月前
|
Java 应用服务中间件 Maven
Springboot入门基础知识详解 parent starter 引导类 辅助功能
Springboot入门基础知识详解 parent starter 引导类 辅助功能
69 2
|
8月前
|
Java
springboot Test 测试类中如何排除一个bean类
springboot Test 测试类中如何排除一个bean类
200 0
|
9月前
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的网络类课程思政学习系统的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的网络类课程思政学习系统的详细设计和实现(源码+lw+部署文档+讲解等)