引言
SpringBoot的配置文件最常见的就是 application.properties
和 application.yml
,一般都是放在 src/main/resources
目录下。
那么问题来了:
- 如果多个配置文件存在同名的配置key,最终生效的值会采用哪个文件的?
- 不同文件格式的配置存在同名的配置key,最终生效的值会采用哪个文件的?
- 打成jar后部署运行时,需要修改某些配置(eg:数据库信息)怎么办?难道要解压jar去改里面的配置文件?
这便是本文要探究的问题,关于配置的优先级以及加载机制。我们先用一些案例来观察实际效果,后面再深入源码进行印证。走起
遇事不决,先打日志!
如果你用的是 application.properties
,添加以下配置:
logging.level.org.springframework.boot.context.config.ConfigFileApplicationListener = trace
如果你用的是 application.yml
,添加以下配置:
logging.level.org.springframework.boot.context.config.ConfigFileApplicationListener: trace
重新启动服务,你会发现新大陆:
这日志给你安排的明明白白,从日志我们可以得到这么些信息:
- 配置的加载路径有四个地方,分别是
file:./config/
、file:./
、classpath:/config/
、classpath:/
- 配置文件格式有四种,分别是
properties
、xml
、yml
、yaml
我项目是用了application.yml,放在 src/main/resources中,也就是对应日志中的 classpath:/application.yml,可以看到它也确实被加载到了(图中倒数第二行)。
试验
从日志的打印顺序就可以直观的看出配置的加载顺序,但是没法知道它的优先级。这就得实践出真知了。上代码
相同文件格式,不同加载路径
- 在 src/main/resources/
application.yml
(对应classpath:/
路径)增加如下配置
key: classpath:/application.yml
- 在 src/main/resources/
config/application.yml
(对应classpath:/config/
路径)增加如下配置
key: classpath:/config/application.yml
- 编写打印配置的代码
@Bean
public ApplicationRunner test(Environment env){
return new ApplicationRunner() {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println(env.getProperty("key"));
}
};
}
- 运行服务,最终打印的结果是 classpath:/config/application.yml
说明:相同文件格式的情况下,classpath:/config/
优先级 高于 classpath:/
。
相同加载路径,不同文件格式
- 在上一节的代码做以下调整
- 删掉上一节创建的 src/main/resources/
config/application.yml
- 在 src/main/resources/
application.properties
增加如下配置
key=classpath:/application.properties
- 运行服务,最终打印的是 classpath:/application.properties
说明:相同加载路径的情况下,properties
优先级 高于 yml
。
不同加载路径,不同文件格式
- 在上一节的代码做以下调整
- 还原 src/main/resources/
config/application.yml
- 运行服务,最终打印的是 classpath:/config/application.yml
说明:虽然 properties > yml,但是 classpath:/config/ > classpath:/,最终classpath:/config/application.yml > classpath:/application.properties,侧面得出加载路径权重高于文件格式。
总结
根据上面的试验结果,以及日志中体现的加载顺序,我们可以得出以下结论:(上述试验仅测了其中几种情况,有兴趣的同学可以挨个试验)
加载路径的优先级
加载路径的优先级:file:./config/
> file:./
> classpath:/config/
> classpath:/
文件格式的优先级
文件格式的优先级:properties
> xml
> yml
> yaml
扩展:外部化配置
一般我们SpringBoot打成jar包,配置文件是内置在jar中的,需要修改某些配置项如果要去改jar包,那稍显麻烦。SpringBoot自然意识到这个问题,默认的加载路径 file:./config/
和 file:./
便是外部化配置的关键。也就是SpringBoot jar启动时会去当前目录下的 ./config/
和 ./
路径读取配置文件,若有配置文件,根据优先级会替换jar包中的同名配置。
end
下一篇,将带大家深入到源码,看看SpringBoot从代码层面是如何实现的。敬请期待…