前两天面试碰到面试官问Springboot有哪几种加载配置的方式,这些方式的优先级如何排列,一下子把只想到Apollo、bootstrap.properties和命令行参数的我给问闷了,故在此文中整理部分配置加载方法,并设计了验证它们优先级的实验。
官方文档https://docs.spring.io/spring-boot/docs/current/reference/html/features.html#features.external-config
目录
测试代码(总)
命令行参数(Command line arguments)
ServletContext
application.properties
@PropertySources
实验结果
配置类:
@Component
@PropertySource("/demo/demo.properties")
@ConfigurationProperties("prioritytest")
public class ConfigProperties {
private String p1;
private String p2;
private String p3;
private String p4;
//省略getter setter
}
负责输出结果的Controller类:
@RestController
public class BookController {
@Autowired
ConfigProperties configProperties;
@GetMapping("/testprop")
public String testProp(){
String strBuild = configProperties.getP1() +
" " +
configProperties.getP2() +
" " +
configProperties.getP3() +
" " +
configProperties.getP4();
return strBuild;
}
}
描述:命令行参数
By default,
SpringApplication
converts any command line option arguments (that is, arguments starting with--
, such as--server.port=9000
) to aproperty
and adds them to the SpringEnvironment
.
SpringApplication会将命令行参数转换为property并存入Spring的Environment中。
If you do not want command line properties to be added to the
Environment
, you can disable them by usingSpringApplication.setAddCommandLineProperties(false)
.
可通过上述方式阻止Spring将命令行参数加入Environment。
关于Spring Environment,可以参考官方文档。
或参考这篇文章。
简单来理解的话,把其当作是JDK环境、Servlet环境及Spring环境的整合体。
测试代码:由于笔者的测试项目使用Maven来启动Springboot应用,所以首先参考相关文档确认了参数的写法,其次在IDEA-项目视窗右键-Run Maven- new goal中添加如图中所示的两个Goal,都能够正常使用。
描述:ServletContext的优先级介于命令行参数与application.properties之间,不少博客提到了通过xml文件在ServletContext中添加属性的办法,当然,也有不依赖xml文件的方法。
笔者暂时没有发现ServletContext有什么特别的应用场景...
测试代码:
参考
@Bean
public ServletContextInitializer servletContextInitializer() {
return new ServletContextInitializer() {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.setInitParameter("prioritytest.p2",
"p2_servlet_context");
servletContext.setInitParameter("prioritytest.p1",
"p1_servlet_context");
}
};
}
描述:比较灵活、常见的配置方法。本文仅仅简单地演示了其用法,实际上,application.properties的相关使用技巧包括:支持复合结构的yaml文件,jar包外部的application.properties文件、jar包内部的application.properties文件、以及application-{profile}.properties用法...等等。
测试代码:
在application.properties中写入
prioritytest.p1 = p1_resources_application_properties
prioritytest.p2 = p2_resources_application_properties
prioritytest.p3 = p3_resources_application_properties
描述:该注解允许某个配置类(@Configuration
classes)从指定文件中读取配置信息,其优先级低于上面提及的几种配置方法。
此外,官方文档就该注解将值填入属性的时机进行了解说:
Please note that such property sources are not added to the
Environment
until the application context is being refreshed. This is too late to configure certain properties such aslogging.*
andspring.main.*
which are read before refresh begins.
测试代码:
项目结构图:
代码:
prioritytest.p1 = p1_resources_propertysource
prioritytest.p2 = p2_resources_propertysource
prioritytest.p3 = p3_resources_propertysource
prioritytest.p4 = p4_resources_propertysource
符合文档中对于配置优先级的描述。