我们在用springboot开发项目的时候,我们在线上或预发部署的时候,经常需要把这个文件application.yml提出来,然后根据不同分组配置不同的配置项,比如配置日志参数等,比如我代码的appliction.yml(配置文件路径在–classpath:/)的有个日志配置项配置的级别是debug,然后如果我再线上分组也提出来个appliction.yml(路径是–file:./config/ 既优先级最高的路径)
logging:
level:
root: debug
针对上面的场景做个假设,提出来的application.yml是不是比我classpath下的application.ym优先加载,那么加载顺序是啥?如果提出来的文件没有上面日志这个配置的话。是否会把我classpath下的配置项给覆盖?该从哪里找答案,答案是从源码找答案, 我们项目用的是spring-boot-1.4.5版本。
1 入口在SpringApplication.run(AppStart.class, args);
2 spring在启动完成后会发布一个SpringApplicationEvent事件,既ApplicationEvent,具体就是 listeners.finished(context, (Throwable)null); SpringApplicationEvent event = this.getFinishedEvent(context, exception);context.publishEvent(event);
3 ConfigFileApplicationListener通过实现ApplicationListener接口中方法onApplicationEvent来监听事件
4 通过getSearchLocations来找配置文件路径的,具体方法如下
private Set<String> getSearchLocations() {
Set<String> locations = new LinkedHashSet();
String path;
if (this.environment.containsProperty("spring.config.location")) {
for(Iterator var2 = this.asResolvedSet(this.environment.getProperty("spring.config.location"), (String)null).iterator(); var2.hasNext(); locations.add(path)) {
path = (String)var2.next();
if (!path.contains("$")) {
path = StringUtils.cleanPath(path);
if (!ResourceUtils.isUrl(path)) {
path = "file:" + path;
}
}
}
}
locations.addAll(this.asResolvedSet(ConfigFileApplicationListener.this.searchLocations, "classpath:/,classpath:/config/,file:./,file:./config/"));
return locations;
}
通过代码可以看出查找优先级依次为–file:./config/、–file:./、 –classpath:/config/ 、–classpath:/ (注如果存在指定spring.config.location的路径,则该路径会比上面的4个优先级还要高)所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置内容。SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在—互补配置。如果application.yml,application-pre.yml,application-prod.yml,application-test.yml同时存在且激活,则激活的配置文件的配置项会覆盖总的配置文件的配置项(如env等于pre,则application-pre.yml配置项会覆盖application.yml的)
#主配置文件,配置了这个会优先读取里面的属性覆盖主配置文件的属性
spring:
#激活哪一个环境的配置文件
profiles:
active: @env@