8000字+22张图探秘SpringCloud配置中心的核心原理

laomugua
发布于 2023-11-6 15:06
浏览
1收藏

大家好,我是三友~~

这篇文章来扒一扒SpringCloud配置中心的核心原理。

不知你是否跟我一样,在刚开始使用SpringCloud配置中心的时候也有很多的疑惑:

  • SpringCloud是什么时候去拉取配置中心的?
  • 配置中心客户端的配置信息为什么要写在bootstrap文件中?
  • 对象中注入的属性是如何动态刷新的?
  • 一些开源的配置中心是如何整合SpringCloud的?
  • ...

本文就通过探讨上述问题来探秘SpringCloud配置中心核心的底层原理。

从SpringBoot的启动过程说起

在SpringBoot启动的时候会经历一系列步骤,核心就是SpringApplication的run方法的逻辑

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

整个过程大致可以划分为三个阶段:

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

ApplicationContext刷新前阶段,这个阶段主要也干三件事

  • 准备Environment(注意我这里加粗了,你懂得),也就是准备SpringBoot的整个外部化配置的对象
  • 创建一个ApplicationContext
  • 为ApplicationContext做一些准备工作

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

ApplicationContext刷新阶段,这个阶段其实就是调用​ApplicationContext#refresh​方法来刷新容器

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

刷新的整个过程可以看我之前写的​​万字+20张图剖析Spring启动时12个核心步骤​​这篇文章

ApplicationContext刷新后阶段,这个阶段其实就是收尾的阶段,这个过程其实没有什么非常核心的事

ok,在说完上面这三个阶段之后,思考一个问题

你觉得在上面的三个阶段,哪个阶段最有可能从配置中心拉取配置?

其实稍微思考一下,肯定是想到的就是刷新前阶段

因为我已经明示了,准备Environment

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

玩笑归玩笑,为什么是这个阶段?

很好理解,因为这个阶段是准备Environment,也就是准备外部化配置

只需要在这个阶段加载配置中心的配置,放到Environment中,后面在整个ApplicationContext刷新阶段创建Bean的时候,就可以使用到配置中心的配置了

其实不光是配置中心的配置,比如配置文件的配置,也是在这里阶段读取的

至于如何实现的,我们接着往下瞅

准备Environment的核心操作

上一节得出一个结论

准备Environment,也就是prepareEnvironment方法的实现,是拉取配置的核心

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

不过在说这个方法之前,先来讲一下一些前置操作

前置操作

在SpringApplication创建的时候,会去加载spring.factories中的一些对象,其中就包括:

  • ​org.springframework.context.ApplicationListener​​​键对应的​​ApplicationListener​​的实现

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

  • ​org.springframework.boot.SpringApplicationRunListener​​​键对应的​​SpringApplicationRunListener​​的实现类

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

SpringApplicationRunListener仅仅只有一个实现EventPublishingRunListener

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

构造的时候会创建一个​​SimpleApplicationEventMulticaster​​​,再将加载的​​ApplicationListener​​添加进去

SimpleApplicationEventMulticaster是用来发布事件用的,不清楚的话可以看​​三万字盘点Spring 9大核心基础功能​​这篇文章

按照传统,画张图来理一下这部分前置操作

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

prepareEnvironment的核心逻辑

接着来讲一下prepareEnvironment方法

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

这个方法会首先创建一个Environment对象

之后会执行这么一行方法,传入刚刚创建的Environment对象

listeners.environmentPrepared(environment);

这个方法最终会走到这个方法

EventPublishingRunListener#environmentPrepared

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

这个方法最终会发布一个ApplicationEnvironmentPreparedEvent事件

而对这个事件有两个特别重要的监听器:

  • ConfigFileApplicationListener
  • BootstrapApplicationListener

这些监听器都是通过前置操作从spring.factories配置文件中加载的

ConfigFileApplicationListener,用来处理配置文件的,他会解析配置文件的配置,放到Environment中

BootstrapApplicationListener这个跟本文探讨的主题相关了,它是用来专门来跟配置中心交互的

到这,我们就找到了SpringCloud配置中心配置拉取的整个入口逻辑

不过在分析BootstrapApplicationListener是如何从配置中心拉取配置的之前,先来张图总结一下这部分prepareEnvironment的操作

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

SpringCloud是如何巧妙地拉取配置的?

在BootstrapApplicationListener中,他首先也会创建一个SpringApplication去执行

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

其实本质上就是创建一个Spring容器,也就是ApplicationContext

这个容器非常重要,这个容器是专门用来跟配置中心交互的

这个容器在创建的时候会给它两个比较重要的配置

第一个就是设置这个容器所用的配置文件的名称

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

默认就是bootstrap

这就解释了为什么配置中心的配置信息需要写在bootstrap配置文件中

第二个就是会加入一个配置类

BootstrapImportSelectorConfiguration

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

这个配置类又会通过@Import注解导入另一个配置类

BootstrapImportSelector

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

BootstrapImportSelector实现了(间接)ImportSelector接口

那么这个容器在启动的时候,就会调用BootstrapImportSelector的selectImports方法的实现获取到一些配置类

而BootstrapImportSelector的selectImports实现从截图中也就可以看出

他会加载所有的spring.factories中的键为​​org.springframework.cloud.bootstrap.BootstrapConfiguration​​的配置类

其实这里​​@BootstrapConfiguration​​​的作用其实跟​​@EnableAutoConfiguration​​的作用是差不多的,都是用来导入配置类的

所以,总的来说,这个用来跟配置中心交互的Spring容器最最主要就是干两件事:

  • 加载bootstrap配置文件
  • 加载所有的spring.factories中的键为​​org.springframework.cloud.bootstrap.BootstrapConfiguration​​对应的配置类

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

而在spring-cloud-context包下,​@BootstrapConfiguration​会导入一个很重要的配置类

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

PropertySourceBootstrapConfiguration

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

这个配置类中会注入这么一个集合对象

PropertySourceLocator

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

这个接口非常非常重要,先来看看注释

Strategy for locating (possibly remote) property sources for the Environment. Implementations should not fail unless they intend to prevent the application from starting.

我用我的四级英语功力给大家翻译一下

以一种策略的方式为Environment定位(可能是远程)属性配置(PropertySource)。实现不应该失败,除非打算阻止应用程序启动。

从这个翻译后的意思就是说,这个接口是用来定位,也就是说获取属性配置的

并且可能是远程告诉我们一个很重要的信息,那就是获取的配置信息不仅仅可以存在本地,而且还可以存在远程。

远程?作者这里就差直接告诉你可以从配置中心获取了。。

所以这个接口的作用就是用配置中心获取配置的!

那么自然而然不同的配置中心要想整合到SpringCloud就得实现这个接口

当注入完PropertySourceLocator集合之后,在某个阶段会调用所有的PropertySourceLocator,获取配置中心中的配置

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区

之后在把这些配置放到Environment中

这样在ApplicationContext的刷新阶段就可以使用到配置中心的那些配置了

小总结

到这我们就弄明白了在项目启动中加载配置中心的配置了

其实就是项目在启动时会额外创建一个跟配置中心相关的Spring容器

这个容器会去加载bootstrap配置文件和所有的spring.factories中的键为​​org.springframework.cloud.bootstrap.BootstrapConfiguration​​对应的配置类

之后会去调用这个容器中所有的PropertySourceLocator对象,从配置中心获取配置

再放到Environment中就完成了启动时从配置中心获取配置的方式

最后,来张全家福概括一下前面整体的步骤

8000字+22张图探秘SpringCloud配置中心的核心原理-鸿蒙开发者社区



文章转载自公众号:三友的java日记

标签
已于2023-11-6 15:06:28修改
收藏 1
回复
举报
回复
    相关推荐