在Spring Boot项目中,bootstrap.yml的优先级高于application.yml,这一设计决策主要是基于Spring Cloud环境下配置加载的特性和需求。以下结合底层源码分析这一现象的原因:

  1. 引导上下文与应用上下文的加载顺序
    在Spring Cloud中,应用的启动过程涉及两个上下文的创建:引导上下文(Bootstrap Context)和应用上下文(Application Context)。这两个上下文是父子关系,其中引导上下文是应用上下文的父上下文。

引导上下文的加载:在Spring Cloud环境下,引导上下文会在应用上下文之前被创建和初始化。引导上下文的主要任务是加载和解析外部配置源(如配置中心)中的配置属性。
配置文件的加载:在引导上下文初始化过程中,会首先加载bootstrap.yml(或bootstrap.properties)配置文件,用于配置引导上下文所需的属性。
2. 配置属性的优先级规则
Spring Boot和Spring Cloud遵循一定的优先级规则来加载和解析配置属性。这些规则决定了当多个配置源中存在相同属性时,哪个配置源的属性将被使用。

优先级顺序:通常,配置属性的优先级顺序如下(从高到低):命令行参数、外部application.yml(或.properties)、外部bootstrap.yml(或.properties)、内部application.yml(或.properties)、内部bootstrap.yml(或.properties)、其他配置源(如@PropertySource、@ConfigurationProperties等)。
然而,需要注意的是,在Spring Cloud的特定场景下,由于引导上下文在应用上下文之前被加载,因此bootstrap.yml中的配置属性实际上会在application.yml中的配置属性之前被加载到Environment中。这意味着,即使按照通常的优先级规则,application.yml中的配置应该覆盖bootstrap.yml中的相同属性,但在Spring Cloud环境下,由于加载顺序的不同,bootstrap.yml中的配置属性仍然会保留并生效(除非被命令行参数等更高优先级的配置源覆盖)。

  1. 底层源码分析
    在Spring Boot和Spring Cloud的底层源码中,这种配置加载顺序和优先级规则是通过一系列的配置解析器和加载器来实现的。这些组件负责从不同类型的配置源中读取配置属性,并按照优先级顺序将它们合并到Environment中。

配置解析器:负责解析特定类型的配置文件(如YAML、Properties等),并将解析后的配置属性添加到Environment中。
配置加载器:负责从不同类型的配置源(如文件系统、类路径、配置中心等)中加载配置文件,并调用配置解析器进行解析。
优先级管理:在合并配置属性时,根据优先级规则来决定哪个配置源的属性将被保留。这通常是通过比较配置源的优先级顺序来实现的。
在Spring Cloud的源码中,可以观察到引导上下文在创建时会首先加载bootstrap.yml(或.properties)配置文件,并将其中的配置属性添加到Environment中。然后,在应用上下文创建时,会加载application.yml(或.properties)配置文件,并将其中的配置属性与Environment中已有的属性进行合并。由于bootstrap.yml中的配置属性已经先被加载到Environment中,因此它们具有较高的优先级(除非被更高优先级的配置源覆盖)。

总结
综上所述,bootstrap.yml的优先级高于application.yml主要是由于Spring Cloud环境下配置加载的特性和需求所决定的。引导上下文在应用上下文之前被加载和初始化,并且会首先加载bootstrap.yml配置文件中的配置属性。这些属性在后续的应用上下文创建和配置属性合并过程中具有较高的优先级。这种设计使得Spring Cloud能够更灵活地处理外部配置源(如配置中心)中的配置属性,并提供了更强大的配置管理和动态更新能力。