一、前言
本文仅介绍springboot项目中applicaiton.properties和application.yml在不同目录层级下的加载顺序,关于bootstrap和applicaiton加载的优先级深入分析,可参考上一篇文章:
二、加载顺序
在源码ConfigFileApplicationListener.java注释中,提到,加载顺序如下:
创建一个空的springboot项目,按下图所示,新建配置文件。
按照上图源码中分析,加载顺序按照下图中标注端口号,由小到大进行加载:
6001——> 6002——> 7001——> 7002——> 8001——> 8002——> 9001——> 9002
并且,当6001端口存在时,不再加载其余端口,也就是优先加载到端口,不会被后续配置文件中配置的端口覆盖(很明显,properties要优先yml进行加载)。
三、源码分析
springboot项目启动时,会按照约定的顺序加载内部的配置文件及初始化类
spring.factories会在springboot项目启动时,优先加载,在spring.factorie文件的前两行,首先配置了配置文件的加载顺序,如下图:
PropertiesPropertySourceLoader定义了加载扩展名为properties、xml的文件
YamlPropertySourceLoader中定义了加载扩展名为yml、yaml的文件
在指定了加载顺序后,开始初始化操作
首先会调用ConfigFileApplicationListener类中的下面方法扫描项目中的配置文件
private Set<String> getSearchLocations() {
Set<String> locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
locations.addAll(getSearchLocations(CONFIG_LOCATION_PROPERTY));
}
else {
locations.addAll(
asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
}
return locations;
}
通过debug调试,查看加载内容:
返回的locations的内容,和开篇源码中注释说明的顺序一致,这几个顺序又是从哪里指定的呢?
回到ConfigFileApplicationListener类的开头
public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered {
private static final String DEFAULT_PROPERTIES = "defaultProperties";
// Note the order is from least to most specific (last one wins)
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/*/,file:./config/";
...
}
DEFAULT_SEARCH_LOCATIONS定义了扫描的目录的先后顺序
四、效果演示
启动项目
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.7.RELEASE)
2022-07-26 15:43:55.313 INFO 18900 --- [ main] com.zhufeng.DemoApp : Starting DemoApp on MacBook-Pro-lichao.local with PID 18900 (/Users/lichao/soft/workplace-idea/gitee/zhufeng-boot/target/classes started by lichao in /Users/lichao/soft/workplace-idea/gitee/zhufeng-boot)
2022-07-26 15:43:55.314 INFO 18900 --- [ main] com.zhufeng.DemoApp : No active profile set, falling back to default profiles: default
2022-07-26 15:43:55.621 INFO 18900 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 6001 (http)
2022-07-26 15:43:55.624 INFO 18900 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-07-26 15:43:55.624 INFO 18900 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.41]
启动端口为 6001,删掉6001的配置文件,即项目根目录下config/application.properties
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.7.RELEASE)
2022-07-26 15:45:51.171 INFO 18932 --- [ main] com.zhufeng.DemoApp : Starting DemoApp on MacBook-Pro-lichao.local with PID 18932 (/Users/lichao/soft/workplace-idea/gitee/zhufeng-boot/target/classes started by lichao in /Users/lichao/soft/workplace-idea/gitee/zhufeng-boot)
2022-07-26 15:45:51.172 INFO 18932 --- [ main] com.zhufeng.DemoApp : No active profile set, falling back to default profiles: default
2022-07-26 15:45:51.478 INFO 18932 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 6002 (http)
2022-07-26 15:45:51.481 INFO 18932 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2022-07-26 15:45:51.481 INFO 18932 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.41]
启动端口变为6002,也就是项目根目录下config/application.yml中配置的端口,依次类推,可以验证后续配置文件的端口加载顺序