SpringBoot 配置加载优先级详解

本文是网上查了查相关资料,这里整理记录一下,方便总结归纳,主要针对 spring.profiles.activespring.config.location 以及 spring.config.additional-location 的作用机制及优先级问题进行实践对比。

1. 加载位置与顺序

SpringBoot启动会扫描以下位置的application.properties/yml文件作为spring boot的默认配置文件:

file:./config/
file:./
classpath:/config/
classpath:/

以上是按照优先级从高到低的顺序,所有位置的文件都会被加载,高优先级配置内容会覆盖低优先级配置的内容,并形成互补配置;当然,我们也可以通过spring.config.location来改变默认配置。

上面的:

  • file: 指当前项目根目录
  • classpath: 指当前项目的resources目录

给出一个图例:

SpringBoot 配置加载优先级详解_第1张图片

注意:maven打包是不能把src外面的两个application.properties文件打到jar包里的。

 

2、配置说明

2.1 spring.profiles.active

     除了 application.properties 文件之外,profile-specific 配置也可以通过以下命名方式来定义:application-{profile}.properties。在没有使用 active 指定 profiles 的情况下,Environment 会指定一组默认的 profiles(默认情况下是[default]),换句话说就是,如果没有显示的激活 profiles 配置文件,则默认加载的是 application-default.properties 配置文件。

     profile-specific 配置文件的属性与标准 application.properties 从相同的位置加载(一般是 classpath 下);profile-specific 指定的 properties 配置文件始终覆盖默认配置。

在案例工程中(guides-properties),resources 下面包括 application.properties 和 application-dev.properties 两份配置文件

application.properties 文件配置

spring.application.name=appNameInner
testKey=key-default

application-dev.properties 文件配置

testKey=key-dev

通过以下代码在启动时将配置值输出:

@Value("${testKey}")
private String testKey;

@PostConstruct
private void init(){
    System.out.println("-------------------------------");
    System.out.println(testKey);
    System.out.println("-------------------------------");
}

2.1.1 不指定 spring.profiles.active 时

通过 java -jar guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,console 输出如下:

2020-01-04 00:08:47.279  INFO 11050 --- [           main] com.glmapper.bridge.boot.BootStrap       : No active profile set, falling back to default profiles: default
-------------------------------
key-default
-------------------------------

结论是,如果不显示指定 profiles,则使用默认的。

2.1.2 指定 spring.profiles.active 时

通过 java -jar -Dspring.profiles.active=dev guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,console 输出如下:

2020-01-04 00:08:14.426  INFO 11040 --- [           main] com.glmapper.bridge.boot.BootStrap       : The following profiles are active: dev
-------------------------------
key-dev
-------------------------------

结论是,在显示指定 profiles 的情况下,会覆盖默认 application.properties 中的配置值。

2.2 spring.config.location

在 SpringBoot 2.x 中 spring.config.location 的语义发生了变更(此项配置会导致 classpath 中的 application.properties 不再生效)。原因如下:

private Set getSearchLocations() {
    // spring.config.location 直接使用此份文件,不会再处理其他配置文件
    if (this.environment.containsProperty(CONFIG_LOCATION_PROPERTY)) {
        return getSearchLocations(CONFIG_LOCATION_PROPERTY);
    }
    Set locations = getSearchLocations(CONFIG_ADDITIONAL_LOCATION_PROPERTY);
    locations.addAll(
            asResolvedSet(ConfigFileApplicationListener.this.searchLocations, DEFAULT_SEARCH_LOCATIONS));
    return locations;
}

在工程的根目录的 conf 目录下新建一个 application-conf.properties 配置文件,内容如下:

testKey=key-spring.config.location

通过 java -jar -Dspring.config.location=conf/application-conf.properties guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,发现启动报错,原因是因为 application-conf.properties 中没有 配置 spring.application.name,而 spring.application.name 是在 resources 目录下的 application.properties 中的,所以也间接说明前面提到的,会使 classpath 下的配置失效。新增 spring.application.name 之后,重新启动工程,

spring.application.name=guides-properties
testKey=key-spring.config.location

输出结果如下:

2020-01-04 00:19:12.225  INFO 11147 --- [           main] com.glmapper.bridge.boot.BootStrap       : No active profile set, falling back to default profiles: default
-------------------------------
key-spring.config.location
-------------------------------

所以在使用 spring.config.location 指定外部配置文件时,需要此份配置文件需全量满足当前工程运行时所需,因为它不会去与 resources 目录下的配置文件去做 merge 操作。

2.2.1 另外

SpringApplication 将会从如下位置加载application.properties到spring的环境变量中:

  1. 当前目录的子目录/config下
  2. 当前目录
  3. 类路径的/config下
  4. 应用根目录下 

上述也是其优先使用顺序。 如果不想使用application.properties作为其配置文件名字,可以通过配置环境变量spring.config.name进行设置。也可以通过具体化位置的环境变量spring.config.location其指定:如下代码

#通过第一种方式 
java -jar myproject.jar --spring.config.name=myproject
##方式二
 java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

如果spring.config.location 也包含具体目录,需要使用“/”. spring.config.location 不支持具体额配置环境变量,将会被默认的配置环境变量替换。其配置搜索的顺序与配置的顺序刚好相反。例如:配置顺序为:classpath:/,classpath:/config/,file:./,file:./config/,其搜索顺序如下:

  1. file:./config/
  2. file:./
  3. classpath:/config/
  4. classpath:/

2.3 spring.config.additional-location

在使用 spring.config.additional-location 这种方式自定义 locations 时,除了默认 locations 之外,还会使用 spring.config.additional-location 指定的。

additional-location:言外之意就是增量的配置

例如追加的目录为 classpath:/custom-config/,file:./custom-config/,其搜索的顺序如下:

  1. file:./custom-config/
  2. classpath:custom-config/
  3. file:./config/
  4. file:./
  5. classpath:/config/
  6. classpath:/

(备注,我们也可以通过配置环境变量的形式来进行配置)

在工程的根目录的 conf 目录下新建一个 application-addition.properties 配置文件,内容如下:

testKey=key-addition

通过 java -jar -Dspring.config.additional-location=conf/application-addition.properties guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,输出结果如下:

2020-01-04 00:28:30.048  INFO 11384 --- [           main] com.glmapper.bridge.boot.BootStrap       : No active profile set, falling back to default profiles: default
-------------------------------
key-addition
-------------------------------

结论是,会覆盖默认 application.properties 中的配置值。

2.4 spring.config.additional-location 与 spring.profiles.active 配置加载关系

spring.config.location 不用多数,它就是独立的一份,使用它就不能使用其它的。所以这里只分析 spring.config.additional-locationspring.profiles.active 配置加载关系。

2.4.1 同时指定两个配置

通过 java -jar -Dspring.profiles.active=dev -Dspring.config.additional-location=conf/application-addition.properties guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,输出如下:

2020-01-04 00:32:59.044  INFO 11451 --- [           main] com.glmapper.bridge.boot.BootStrap       : The following profiles are active: dev
-------------------------------
key-dev
-------------------------------

为了排除与 -D 参数顺序有关,也使用如下方式再执行一次:java -jar -Dspring.config.additional-location=conf/application-addition.properties -Dspring.profiles.active=dev guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar,输出结果与前面相同,所以可以得出,spring.profiles.active 的优先级比 spring.config.additional-location 要高。

2.4.2 `spring.config.additional-location` 指定差异增量配置

spring.config.additional-location 中增加 additionKey

testKey=key-addition
additionKey=testAddition

使用 java -jar -Dspring.config.additional-location=conf/application-addition.properties -Dspring.profiles.active=dev guides-properties/target/guides-properties-0.0.1-SNAPSHOT.jar 启动工程,输出如下:

2020-01-04 11:44:42.227  INFO 12821 --- [           main] com.glmapper.bridge.boot.BootStrap       : The following profiles are active: dev
-------------------------------
key-dev
testAddition
-------------------------------

结论是 spring.config.additional-location 可以用于提供出 profiles 机制或者默认方式之外的增量配置。

3 springboot如何同时加载多个配置文件

    springboot 默认是在src/main/resources文件夹中加载application.properties默认配置文件,格式为application-{profile}.properties,其中{profile}对应你的环境标识

     在application.properties中添加spring.profiles.active = dev,database

# 加载多个配置文件,系统加载了application.properties application-database.properties  application-dev.properties 三个配置文件
spring.profiles.active = dev,database

     系统加载了src/main/resources目录下的application.properties application-database.properties application-dev.properties 三个配置文件

4 引用官方的文档说明:

      If you don’t like application.properties as the configuration file name you can switch to another by specifying a spring.config.name environment property. You can also refer to an explicit location using the spring.config.location environment property (comma-separated list of directory locations, or file paths).

$ java -jar myproject.jar --spring.config.name=myproject

or

$ java -jar myproject.jar --spring.config.location=classpath:/default.properties,classpath:/override.properties

      spring.config.name and spring.config.location are used very early to determine which files have to be loaded so they have to be defined as an environment property (typically OS env, system property or command line argument).

      If spring.config.location contains directories (as opposed to files) they should end in / (and will be appended with the names generated from spring.config.name before being loaded, including profile-specific file names). Files specified in spring.config.location are used as-is, with no support for profile-specific variants, and will be overridden by any profile-specific properties.

      The default search path classpath:,classpath:/config,file:,file:config/ is always used, irrespective of the value of spring.config.location. This search path is ordered from lowest to highest precedence (file:config/ wins). If you do specify your own locations, they take precedence over all of the default locations and use the same lowest to highest precedence ordering. In that way you can set up default values for your application in application.properties (or whatever other basename you choose with spring.config.name) and override it at runtime with a different file, keeping the defaults.

 默认将从以下位置加载配置文件spring.config.location=classpath:application.properties,classpath:config/application.properties,多个文件路径以逗号间隔。

    如果路径以最后为目录,必须以"/"结尾。spring.config.location=classpath:config/,那么spring.config.name会自动追加到后面!一旦设定了spring.config.location属性,上述的默认位置将不起作用!因为你要修改的是application.properties的名称,所以上面的两个属性建议通过命令行的方式配置,如:
java -jar trade-web-0.0.1-SNAPSHOT-f1f86f1.jar --spring.config.location=/var/www/config/ --spring.config.name=application.properties
java -jar trade-web-0.0.1-SNAPSHOT-f1f86f1.jar --spring.config.location=/var/www/config/application.properties

 

5. 小结

在使用外部化配置文件时,执行顺序为:

spring.config.location > spring.profiles.active > spring.config.additional-location > 默认的 application.proerties

其中通过 spring.profiles.activespring.config.additional-location指定的配置文件会与 默认的application.proerties merge 作为最终的配置,spring.config.location 则不会。

6. 参考:

https://github.com/glmapper/springboot-series-guides/tree/master/guides-properties

http://www.glmapper.com/2020/01/03/springboot-series-externalize-prop/

https://juejin.im/entry/5a4b33e6518825258227bfbe

https://blog.csdn.net/hbiao68/article/details/87360551

https://blog.csdn.net/Alan666156/article/details/53404792

你可能感兴趣的:(SpringBoot)