Spring Boot 教程

ApplicationArguments 类

ApplicationArguments 接口提供了对用于访问运行 SpringApplication 程序传递的参数。Spring Boot 提供了它的默认实现 DefaultApplicationArguments。例如:

public static void main(String[] args) {
    System.out.println(Arrays.toString(args));
    ConfigurableApplicationContext context = SpringApplication.run(
            ApplicationargumentsDemoApplication.class, args);

    Environment environment = context.getEnvironment();
    System.out.println("key1=" + environment.getProperty("key1"));
    System.out.println("key2=" + environment.getProperty("key2"));
}

其中,args 是运行程序时动态传递过来的。如下图:

运行成功后将输出如下信息:

2020-11-09 13:01:51.141  INFO 12612 --- [  restartedMain] .s.a.ApplicationargumentsDemoApplication : Started ApplicationargumentsDemoApplication in 4.313 seconds (JVM running for 10.254)
key1=val1
key2=val2

注意:上面 IDEA 的 “Run/Debug Configurations” 界面中的 “Program arguments” 输入框中输入的参数必须遵循 “--键=值” 的格式。

上面代码演示了使用 Environment 获取 run() 方法传递的 args 参数。下面将介绍通过注入 ApplicationArguments 对象来访问参数,如下:

package com.huangx.springboot.applicationarguments_demo2;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Arrays;

@RestController
@SpringBootApplication
public class ApplicationargumentsDemo2Application {

    @Autowired
    private ApplicationArguments arguments;

    public static void main(String[] args) {
        SpringApplication.run(ApplicationargumentsDemo2Application.class, args);
    }


    @RequestMapping("/")
    public String index() {
        return "key1=" + Arrays.toString(arguments.getOptionValues(
                "key1").toArray(new String[]{})) + "<br/>" +
                "key2=" + Arrays.toString(arguments.getOptionValues(
                "key2").toArray(new String[]{}));
    }

}

启动应用程序后,使用浏览器访问 http://localhost:8080 ,效果如下图:

接下来,将介绍实现自己的 ApplicationRunner 类来获取参数。代码如下:

package com.huangx.springboot.applicationarguments_demo2;

import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.Arrays;

@Component
public class MyApplicationRunner implements ApplicationRunner {
    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("========= MyApplicationRunner =========");
        for(String name : args.getOptionNames()) {
            System.out.println(name + "=" + Arrays.toString(
                    args.getOptionValues(name).toArray(new String[]{})));
        }
    }
}

启动 Spring Boot 程序,输出结果如下:

========= MyApplicationRunner =========
key1=[val1]
key2=[val2]

ApplicationArguments 的实现

我们先从 SpringApplication.run() 方法开始查看,源代码如下:

源代码中,是直接 new 了一个 DefaultApplicationArguments 默认实现类作为 ApplicationArguments 的对象。继续点进去,查看 DefaultApplicationArguments 类的源代码,如下:

package org.springframework.boot;

import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.springframework.core.env.SimpleCommandLinePropertySource;
import org.springframework.util.Assert;

/**
 * Default implementation of {@link ApplicationArguments}.
 *
 * @author Phillip Webb
 * @since 1.4.1
 */
public class DefaultApplicationArguments implements ApplicationArguments {
   private final Source source;
   private final String[] args;

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

   @Override
   public String[] getSourceArgs() {
      return this.args;
   }

   // 获取所有选项名集合
   @Override
   public Set<String> getOptionNames() {
      String[] names = this.source.getPropertyNames();
      return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(names)));
   }

   // 判断给定的选项是否存在
   @Override
   public boolean containsOption(String name) {
      return this.source.containsProperty(name);
   }
   
   // 获取指定key的选项值列表 
   @Override
   public List<String> getOptionValues(String name) {
      List<String> values = this.source.getOptionValues(name);
      return (values != null) ? Collections.unmodifiableList(values) : null;
   }
   
   // 返回在命令行上指定的非选项参数的列表。
   @Override
   public List<String> getNonOptionArgs() {
      return this.source.getNonOptionArgs();
   }

   private static class Source extends SimpleCommandLinePropertySource {
      Source(String[] args) {
         super(args);
      }

      @Override
      public List<String> getNonOptionArgs() {
         return super.getNonOptionArgs();
      }

      @Override
      public List<String> getOptionValues(String name) {
         return super.getOptionValues(name);
      }
   }
}

假如我们启动 Spring Boot 程序传递的参数为 “--key1=val1 --key2=val2 hello world”,则:

  • getOptionNames() 返回的 key1 和 key2

  • getOptionValues(String name) 如果你传递 key1 作为name,那么将返回仅包含 val1 的 List

  • getNonOptionArgs() 返回包含了 hello 和 world 字符串的 List

我们关注的重点应该是 Source 内部类,该类继承了 SimpleCommandLinePropertySource 类,而 SimpleCommandLinePropertySource 类继承了 CommandLinePropertySource 类。

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
公众号