1.1. 读配置文件的顺序
springboot读配置的类是这个:org.springframework.boot.context.config.ConfigFileApplicationListener

会按这四个目录倒置的顺序读配置文件:“classpath:/,classpath:/config/,file:./,file:./config/”

源码中如下:

spring boot 将配置文件读成Map springboot配置文件读取顺序_读取文件


spring boot 将配置文件读成Map springboot配置文件读取顺序_读取文件_02


我在idea对应的这四个目录中放入配置文件,如下:

spring boot 将配置文件读成Map springboot配置文件读取顺序_yaml_03


从debug日志中可以看到读取文件的顺序如下:

spring boot 将配置文件读成Map springboot配置文件读取顺序_配置文件_04


配置文件扩展格式一共有四种:properties,xml, yml,yaml,

可以看到同一个目录中读取文件顺序是properties,yml,yaml,

其实还有application.xml文件,xml跟在properties后面,只是它的格式问题,我这里没有配xml文件。

最后读取的是application-dev文件。就是spring.profiles.active参数指定的。

配置文件扩展格式是由这两个类决定的PropertiesPropertySourceLoader和YamlPropertySourceLoader
spring会先加载PropertiesPropertySourceLoader,后加载YamlPropertySourceLoader。所以先读取的是properties文件。

spring boot 将配置文件读成Map springboot配置文件读取顺序_yaml_05

1.2. 参数的覆盖

先记住“application”是默认的读的文件名。
如果同名参数在多个文件中出现,同名文件之间会以先读取的文件为有效。(同名文件不包括扩展名,比如,application.properties和application.yaml是同名文件。application-dev.properties和application-dev.yaml是同名文件)
看下图中的读取文件的顺序,有多个application文件,同名参数会以第一个application为有效,后面的application不会覆盖先读取的。

如果application中指定了spring.profiles.active参数,在读完所有application文件后,会按active中指定的顺序读取文件。同名参数会按active中的文件覆盖前面非同名文件中的参数。

spring.profiles.active=test,dev

此时文件名有三个,application,application-test,application-dev。从下图可以看到读取顺序。

spring boot 将配置文件读成Map springboot配置文件读取顺序_配置文件_06


同名参数,application-dev文件会覆盖application-test,application-test会覆盖application文件中的,

同样如要有多个application-dev文件,同名参数会以先读取的application-dev文件为有效。

1.3. 四个目录

“classpath:/,classpath:/config/,file:./,file:./config/”

Springboot项目打包后,这个目录分别是

  1. classpath:/,包中的BOOT-INF\classes目录
  2. classpath:/config/,包中的BOOT-INF\classes\config目录
  3. file:./, 与包同级的目录
  4. file:./config/",与包同级的目录中的config目录

总结几点

  1. 先读application文件,按这四个目录( “classpath:/,classpath:/config/,file:./,file:./config/”
    )倒置顺序读取,同目录下按文件扩展名(properties,xml, yml,yaml)顺序读取。
  2. 再读spring.profiles.active指定的文件,顺序也是先按那四个目录和文件扩展名。
  3. 同名参数,在同名的文件中,会以先读取的文件为有效。
  4. 同名参数,在不同名的文件中,后读取的文件会覆盖先读取的文件,也就是参数的覆盖只在不同名文件之间发生。