美文网首页
SpringCloud中Bootstrap配置的生效

SpringCloud中Bootstrap配置的生效

作者: Wannay | 来源:发表于2022-01-15 09:30 被阅读0次

1. Bootstrap配置文件在什么时候才会生效?

SpringBoot 2.4.x的版本之后,对于bootstrap.properties/bootstrap.yaml配置文件(我们合起来成为Bootstrap配置文件)的支持,需要导入如下的依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-bootstrap</artifactId>
            <version>3.1.0</version>
        </dependency>

其实这个jar包里什么都没有,就只有一个标识类Marker,用来标识要开启Bootstrap配置文件的支持,至于原理是什么?我们下面逐步去进行解析

2. Bootstrap配置文件生效的原因

既然是SpringBoot,我们主要研究它的run方法,在这个方法中定义了SpringBoot启动的整个流程。

image.png

我们要研究的是Bootstrap配置文件的相关信息,就肯定和环境对象有关系,因此我们关注准备环境变量的步骤。

image.png

在这里我们可以看到,首先是创建了一个环境对象,接着,通知所有的监听器,告诉它们环境对象已经准备好了,可以开始去进行配置环境信息了。我们关心的application配置文件以及bootstrap配置文件,都是使用监听器的方式去监听环境准备好的事件时去扩展的。

对于Bootstrap的配置文件,将会被BootstrapApplicationListener去进行处理,而这个监听器,在cloud-context的jar包下通过SpringFactories的方式去进行了配置,因此在运行时,就会实例化这个监听器并在创建环境之后去进行回调。

而对于application配置文件,是由另外一个监听器(EnvironmentPostProcessorApplicationListener)去进行处理的,这个监听器里面会读取spring.config.name作为配置文件名,如果没有的话,会使用application作为默认的配置文件名。

image.png

既然它是一个监听器,那么,我们需要关注的是它的onApplicationEvent方法。

image.png

首先我们需要注意一个点,这个监听器的Order很高,一般来说,它都是第一个被回调到的监听器,因此在来到这里时,其实application配置文件并未加载到环境当中,但是命令行参数是已经被解析到环境当中了,我们上面的步骤当中已经提到过。

我们首先要关注的一个点就是bootstrapEnabled(environment),很明显,它是用来判断bootstrap是否要生效的。我们打开它的源码

image.png

我们可以看到,是否开启bootstrap,只需要满足当前环境信息当中有配置spring.cloud.bootstrap.enabled=true,或者当前的依赖当中存在有org.springframework.cloud.bootstrap.marker.Marker这个类,就会开启bootstrap

而我们上面已经说过了,导入spring-cloud-starter-bootstrap这个组件的作用就是为了让容器中存在有该标识类,我们下面点开源码来验证一下。

image.png

我们可以看到,确实只有一个Marker的标识类,其它就什么都没有了。

实际上,通过在启动参数中配置相关的属性也可以(因为Bootstrap的监听器优先级比较高,因此配置在application配置文件当中无效,application配置文件还未加载到环境当中来,所以必须在启动参数中去进行配置),不用非得导入jar包(前提容器中已经有了cloud-context的jar包,因为这个jar包当中导入了BootstrapApplicationListener组件)。

image.png

3. Bootstrap的核心代码-bootstrapServiceContext

我们继续来看BootstrapApplicationListener的后续源码中的bootstrapServiceContext方法,这个方法是整个Bootstrap的核心。

3.1 Bootstrap隔离容器的构建

image.png image.png

我们可以看到,其实这里的主要逻辑,就是去创建一个隔离容器,这个容器中的组件是由BootstrapImportSelectorConfiguration它去进行处理的。还有一个关键点,它往自己构建的一个Map的属性源当中加入了一个配置项spring.config.namebootstrap(如果没有自己额外配置的话),这个配置项,决定的是它在运行时需要加载的配置文件的名称。

而这里其实会运行bootstrap隔离容器,因此也会有环境的监听器EnvironmentPostProcessorApplicationListener,这个组件就会读取到我们配置的spring.config.name配置项,去加载bootstrap配置文件。

image.png

其实它就是导入一个Selector,通过Selector给容器中导入组件。

image.png

而这个Selector,其实就是加载BootstrapConfiguration中配置的相关配置。

那么BootstrapConfiguration配置了什么?下面是cloud-context中配置的自动配置的组件。

image.png

通过自动配置的组件,我们可以看到其中一个肯定是关于处理占位符的组件,它主要给容器中导入一个嵌入式的值解析器,用来解析占位符。

3.2 BootstrapConfigurationPropertySourceBootstrapConfiguration

这个组件值得我们去进行关注

image.png

我们可以看到,它本身是一个ApplicationContext的初始化器,并且会自动注入Bootstrap隔离容器中配置的所有的Locator,这个Locator是实现分布式配置中心的关键。

下面我们来看Nacos-Config的源码,看看它是怎么加载ConfigServer中的配置文件的?

image.png

我们可以看到,它给Bootstrap隔离容器中导入了一个NacosConfigBootstrapConfiguration组件,我们来看这个组件的源码

image.png

我们可以看到,它给容器中导入了一个NacosConfigManager组件,包装一个ConfigService,这个组件是Nacos中用来读取远程ConfigServer中的配置信息的组件。如果使用过Nacos的API的使用的话,应该比较熟悉这个组件。

image.png

它还给容器中导入了一个Locator组件,而导入的这个Locator组件的locate方法的代码如下,我们可以很明确的看到了准备dataId,并且开始去加载配置文件,并将所有要加载的配置文件进行聚合成为一个属性源对象,并返回,Spring就会自己对其去进行处理,并导入到app容器的环境对象当中去。

image.png

我们可以知道,所有的Locator组件,都会被注入到PropertySourceBootstrapConfiguration这个组件中,但是这个组件并不会在Bootstrap隔离容器中生效,这个组件,实际上会在app容器中去生效,我们来找它的源码。

我们在BootstrapApplicationListener这个组件的onApplicationEvent方法中,可以看到有apply这个步骤。这个步骤的源码如下:

image.png

我们可以看到,它将app容器的组件和bootstrap隔离容器中的组件去进行了合并,并设置到app容器所对应的SpringApplication组件当中。

问题来了,ApplicationContext的初始化器在什么时候会被应用?

3.3 ApplicationContext的初始化器什么使用生效

我们回到SpringApplicationrun方法,找到准备Context的一个步骤。

image.png

我们可以看到,在这个方法中存在有applyInitializers这样的步骤,那就很明显了,就是在这里回调的。在创建完ApplicationContext之后,立马就回调所有的初始化器,其实根据初始化器这个名词,我们也可以大概猜到,它会在创建完ApplicationContext之后立马就会去进行回调。

image.png

3.4 对整个过程进行梳理

image.png

相关文章