【小家Spring】一篇文章彻底搞懂Spring Boot配置文件的加载顺序(项目内部配置和外部配置) - Go语言中文社区

【小家Spring】一篇文章彻底搞懂Spring Boot配置文件的加载顺序(项目内部配置和外部配置)


每篇一句

天上飞的理念,必定有落地的实现,而且一般都不止一个

说在前面

Spring这么流星很重要的一个思想是:配置化思想。从而达到解耦的目的,很多都不需要硬编码,配置一下即可完成,可谓大大提高了编码的效率。

Spring支持的配置文件加载的方式繁多,一方面是扩大了灵活性,另一方面其实也带来了较大的复杂性。因此本文旨在用一篇文章解决读者朋友的烦恼,同时有时候也是我的烦恼

加载项目内部配置文件

我们从https://start.spring.io初始化一个项目下来后,在resources目录下会放置一个application.properties文件。现在我们这么操作:
删除掉application.properties文件,新建一个application.yml文件,写上

config:
  icon: "classpath:resource_yml"

直接运行我的测试程序:

@RunWith(SpringRunner.class)
@SpringBootTest
public class Run2ApplicationTests {

    @Value("${config.icon}")
    private String key;

    @Test
    public void contextLoads() {
        System.out.println(key);
    }

}
输出:
classpath:resource_yml

因此我们可以知道,yml文件是完全可以代替application.properties文件的,事实也确实如此。SpringBoot支持这两种格式的配置文件。(Spring Framwork只支持application.properties)

如果application.properties和application.yml共存呢?

基于上面代码,我们再建立一个application.properties文件,写上相同的key

config.icon=classpath:resource

运行测试结果为:

classpath:resource

结论:
当application.properties和yml文件在并存时(同一目录下),application.properties优先级更好,会先读它,若它没有,再去读yml中的值


有了上面的结论,下面的演示仅演示application.properties文件

1、在Resource目录下创建config文件夹,然后放置properties配置文件

config.icon=classpath:resource/config

运行结果为:

classpath:resource/config

2、继续添加。在项目根目录创建一个配置文件

config.icon=file:

运行结果为:

file:

3、继续添加。在项目的根目录创建一个文件夹config,然后放入配置文件

config.icon=file:/config

运行结果为:

file:/config

看看我们现在的配置文件结构和运行顺序:
在这里插入图片描述
似乎我们已经掌握了Spring Boot加载这个的顺序和优先级。

我们可以从ConfigFileApplicationListener这类便可看出,其中DEFAULT_SEARCH_LOCATIONS属性设置了加载的目录:

private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/";
看看Spring Boot官网怎么说

官方文档说明:
在这里插入图片描述
翻译成文件系统:

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

翻译成语言如下(按照优先级从高到低的顺序):

  1. 先去项目根目录找config文件夹下找配置文件件
  2. 再去根目录下找配置文件
  3. 去resources下找cofnig文件夹下找配置文件
  4. 去resources下找配置文件

整个设计非常巧妙。SpringBoot会从这四个位置全部加载主配置文件,如果高优先级中配置文件属性与低优先级配置文件不冲突的属性,则会共同存在—互补配置

备注:

这里说的配置文件,都还是项目里面。最终都会被打进jar包里面的,需要注意。

1、如果同一个目录下,有application.yml也有application.properties,默认先读取application.properties。
2、如果同一个配置属性,在多个配置文件都配置了,默认使用第1个读取到的,后面读取的不覆盖前面读取到的。
3、创建SpringBoot项目时,一般的配置文件放置在“项目的resources目录下”

项目打包好以后,我们可以使用命令行参数的形式,启动项目的时候来指定配置文件的新位置。(这个很多时候在运维时经常用到)
指定配置文件和默认加载的这些配置文件共同起作用形成互补配置。

java -jar run-0.0.1-SNAPSHOT.jar --spring.config.location=D:/application.properties

外部配置(非常重要)

先看官网怎么说吧
在这里插入图片描述
中文翻译:
在这里插入图片描述
优先级从高到低(本文只解释较为常用的):

  1. 命令行参数(所以我们java -jar启动时指定的参数优先级最高啊)
    所有的配置都可以在命令行上进行指定;
    多个配置用空格分开; --配置项=值
--server.port=8087 --server.context-path=/abc
  1. Java系统属性(System.getProperties())
    由此课件,Spring启动的时候,默认会把系统的很多属性都默认加载进来。
    @Test
    public void contextLoads() {
        //看看spring容易里面是否存在系统属性
        System.out.println(environment.containsProperty("user.name"));
        System.out.println(environment.containsProperty("java.runtime.name"));
        System.out.println(environment.containsProperty("user.dir"));
        System.out.println(environment.containsProperty("os.name"));
        System.out.println(environment.containsProperty("sun.boot.library.path"));

        //打印系统的所有属性(很多的系统属性)
        Properties properties = System.getProperties();
        for (Map.Entry<Object, Object> entry : properties.entrySet()) {
            System.out.println(entry);
        }
    }
输出:
一路true

Tips:因此你自定义key的时候,应该去避免和系统自带的key重名,否则不起作用。

  1. 操作系统环境变量(比如操作系统的username等等,下面讲@Value的时候会介绍这个坑)
  2. RandomValuePropertySource配置的random.*属性值
  3. jar包外部的application-{profile}.properties配置文件
  4. jar包内部的application-{profile}.properties配置文件
  5. jar包外部的application.properties配置文件(此级别在测试环境经常使用。比如就在jar包同级目录放置一个配置文件,就内覆盖jar包内部所有的配置文件了)
  6. jar包内部的application.properties配置文件

由jar包外向jar包内进行寻找,优先加载待profile的,再加载不带profile的。

  1. @Configuration注解类上的@PropertySource(手动指定导入外部配置文件)
  2. 通过SpringApplication.setDefaultProperties指定的默认属性,自己程序代码里设置,优先级最低

加载了外部配置,还会记载内部配置吗?

我通过一个小实验来证明

//读取外部配置的key
        System.out.println(environment.getProperty("abcd"));

        //读取内部配置的key
        System.out.println(environment.getProperty("config.icon"));

内部配置:

config.icon=classpath:resource

外部配置:

abcd=abcd

结构如下图:
在这里插入图片描述
我用java -jar启动后,结果是:
内、外部配置的key对应的value都能输出

因此我们可以得出结论:不管内部、外部配置,形成的都是互补配置,都会加载

知识交流

在这里插入图片描述
若群二维码失效,请加微信号(或者扫描下方二维码):fsx641385712。
并且备注:“java入群” 字样,会手动邀请入群

在这里插入图片描述

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/f641385712/article/details/84401629
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢