SpringBoot优雅获取应用参数
本文以springboot2.7.2 版本为例,讲解怎么优雅获取应用参数,并提供一个demo案例来解说,最后在通过源码去分析怎么获取应用参数。
demo案例
通过一个demo来获取应用参数
添加依赖pom
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.2</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
模拟传递参数
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* @author bearboy80
*/
@SpringBootApplication
public class SpringBootArgDemo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
Collections.addAll(list, args);
list.add("--debug=logfile.txt");
list.add("--server.port=8081");
SpringApplication.run(SpringBootArgDemo.class, list.toArray(new String[list.size()]));
}
}
/**
* 获取arg 参数并打印
*/
@Component
class ArgsBean {
public ArgsBean(ApplicationArguments args) {
for (String key : args.getOptionNames()) {
System.out.println(args.getOptionValues(key));
}
}
}
源码解析
关键类
- ApplicationArguments 从Springboot1.3 开始引入
- DefaultApplicationArguments ApplicationArguments实现类
关键实现点
- 创建DefaultApplicationArguments -org.springframework.boot.SpringApplication#run(java.lang.String…)
long startTime = System.nanoTime();
DefaultBootstrapContext bootstrapContext = createBootstrapContext();
ConfigurableApplicationContext context = null;
configureHeadlessProperty();
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting(bootstrapContext, this.mainApplicationClass);
try {
#创建ApplicationArguments
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
#将ApplicationArguments注入到spring context上下文中
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
.....................
- 注入到spring 容器中–prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner) 方法
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
总结
本文通过springboot提供的applicationArguments来优雅的获取应用启动传递的参数,通过应用启动传递的参数会被存到CommandLinePropertySource中,我们可以通过@value来获取参数值。
大家可以思考一个问题,假如application.yml 指定server.port=9090,应用启动指定端口为8100,springboot启动以哪个端口为准?具体答案大家可以参考spring boot 外部化配置优先级