文章目录
- 前言
- 一、NacosPropertySourceLocator
- 1.1、加载共享的配置文件
- 1.2、加载扩展的配置文件
- 1.3、加载当前应用配置
- 二、补充:bootstrap.yml 与 application.yml 的优先级问题
前言
本篇主要介绍客户端主动向服务端发起请求拉取配置信息,以及加载配置文件的核心源码。
一、NacosPropertySourceLocator
前篇中提到,在Nacos客户端启动的过程中,会通过Spring Boot的自动配置机制,加载NacosConfigBootstrapConfiguration,该类中会条件装配三个Bean,第一个是和配置文件的信息有关,第二个是和接收listenExecutebell队列中的标记并向服务端发起请求,获取配置信息有关。第三个则是和加载配置文件,以及获取配置信息有关。

客户端Spring Boot启动的过程中,会去调用其中的locate方法,在该方法中,主要做了四件事:
- 获取配置中心服务
- 加载共享的配置文件
- 加载扩展的配置文件
- 加载当前应用配置

1.1、加载共享的配置文件
共享的配置文件,对应的是bootstrap.yml的shared-configs这一部分:

NacosConfigProperties也是在NacosConfigBootstrapConfiguration中加入的Bean,代表了Nacos的配置信息。

1.2、加载扩展的配置文件
扩展的配置文件,对应的是bootstrap.yml的extension-configs这一部分:


1.3、加载当前应用配置
按照 服务名、服务名.后缀名、服务名-环境名.后缀名 的顺序加载,后者的优先级高于前者

无论是上述的何种方式,最后都会调用到loadNacosDataIfPresent方法:
然后调用NacosPropertySourceBuilder的build方法:

调用loadNacosData:

loadNacosData的核心代码是configService.getConfig:

最终调用到的是getConfigInner,其中优先会去读取本地磁盘上保存的配置。

如果获取不到,则会发起请求,从服务端获取配置:

后面的逻辑就和前篇中提到的,客户端接收到listenExecutebell队列中的标记,然后发起请求从服务端获取存在服务端磁盘上的配置,然后获取到结果,存在客户端磁盘上完全相同了
二、补充:bootstrap.yml 与 application.yml 的优先级问题
首先,在原生的Spring Boot 中 是不存在bootstrap.yml 这个概念的。它的出现是由于 Spring Cloud 引入的一层机制,Spring Boot 原生启动时,配置加载顺序由ConfigFileApplicationListener控制,加载如下配置文件(优先级从高到低):
| 加载顺序 | 配置文件来源 | 描述 |
|---|---|---|
| 1 | 命令行参数 | 如 --server.port=8081 |
| 2 | application.properties / application.yml(位于 config/ 目录) | 外部配置优先 |
| 3 | application.properties / application.yml(位于 classpath 根目录) | 通常用于默认配置 |
| 4 | 默认属性(由代码指定) | SpringApplication.setDefaultProperties(...) |
bootstrap.yml 是 Spring Cloud 中通过扩展机制添加的,在spring-cloud-alibaba的相关组件的spring-cloud-context的jar包中的spring.factories 文件中,引入了BootstrapApplicationListener监听器。
spring-cloud-context是个特殊的 Bootstrap Context,由BootstrapApplicationListener 在应用启动最早阶段注入。其作用是优先加载一批基础配置(如 Nacos、Apollo、Consul)来初始化上下文环境,供后续正式环境使用。

该监听器监听了Spring Boot启动过程中发布的ApplicationEnvironmentPreparedEvent事件。

触发时机:


它会在主 ApplicationContext 之前:
- 创建一个“父上下文”(BootstrapContext)
- 加载 bootstrap.yml
- 提前注入环境变量到 Environment
- 然后再加载 application.yml 到主 ApplicationContext
在其onApplicationEvent方法中:

如果开发者明确配置了 spring.cloud.bootstrap.enabled=false,则直接跳过,不加载 bootstrap.yml。

如果 bootstrap 的配置已经加载进了环境变量中(如:bootstrapProperties),就不用重复初始化。

是否已有这个“父上下文”被创建过

如果没有,则创建 Bootstrap 上下文,将 context 加入到主上下文之前,作为其 parent

这个步骤将 bootstrap 加载的配置文件内容注入到当前的 Environment 中。虽然顺序上早于 application.yml,但其优先级较低,这就是为什么 application.yml 可以覆盖 bootstrap.yml 中的值。
