Nacos配置中心客戶端源碼分析(一): 客戶端如何初始化配置

本文收錄于專欄 Nacos
推薦閱讀:Nacos 架構 & 原理

文章目錄

  • 前言
  • 一、NacosConfigBeanDefinitionRegistrar
  • 二、NacosPropertySourcePostProcessor
  • 三、AbstractNacosPropertySourceBuilder
  • 總結「AI生成」


前言

專欄前幾篇文章主要講了Nacos作為服務注冊中心相關的代碼,本章開始梳理Nacos作為配置中心來使用時相關部分的代碼主要邏輯。

??:使用的Nacos版本為2.3.X
??:springboot集成Nacos

 <dependency><groupId>com.alibaba.boot</groupId><artifactId>nacos-config-spring-boot-starter</artifactId><version>0.2.12</version></dependency>

一、NacosConfigBeanDefinitionRegistrar

直接從spring.factories中找和心類:NacosConfigAutoConfiguration
在這里插入圖片描述

@ConditionalOnProperty(name = NacosConfigConstants.ENABLED, matchIfMissing = true)
@ConditionalOnMissingBean(name = CONFIG_GLOBAL_NACOS_PROPERTIES_BEAN_NAME)
@EnableConfigurationProperties(value = NacosConfigProperties.class)
@ConditionalOnClass(name = "org.springframework.boot.context.properties.bind.Binder")
@Import(value = { NacosConfigBootBeanDefinitionRegistrar.class })
@EnableNacosConfig
public class NacosConfigAutoConfiguration {
}

可以看到這個類里啥也沒有,核心就是引入@EnableNacosConfig

@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(NacosConfigBeanDefinitionRegistrar.class)
public @interface EnableNacosConfig {//一些配置文件中nacos配置的占位符定義
}

我們來看關鍵類:NacosConfigBeanDefinitionRegistrar

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry) {AnnotationAttributes attributes = fromMap(metadata.getAnnotationAttributes(EnableNacosConfig.class.getName()));// Register Global Nacos Properties BeanregisterGlobalNacosProperties(attributes, registry, environment,CONFIG_GLOBAL_NACOS_PROPERTIES_BEAN_NAME);// Register Nacos Common BeansregisterNacosCommonBeans(registry);// Register Nacos Config BeansregisterNacosConfigBeans(registry, environment, beanFactory);// Invoke NacosPropertySourcePostProcessor immediately// in order to enhance the precedence of @NacosPropertySource processinvokeNacosPropertySourcePostProcessor(beanFactory);
}

invokeNacosPropertySourcePostProcessor上邊的代碼處理的都是和spring集成相關的邏輯,我們這里暫不去展開。invokeNacosPropertySourcePostProcessor通過這個名字我們可以簡單看出來,這個方法處理的是post processor,一些后置邏輯。

二、NacosPropertySourcePostProcessor

public static void invokeNacosPropertySourcePostProcessor(BeanFactory beanFactory) {NacosPropertySourcePostProcessor postProcessor = beanFactory.getBean(//"nacosPropertySourcePostProcessor"NacosPropertySourcePostProcessor.BEAN_NAME,NacosPropertySourcePostProcessor.class);postProcessor.postProcessBeanFactory((ConfigurableListableBeanFactory) beanFactory);
}

代碼看到這里我們做個暫停,再次想一想我們到底要找什么,有了明確的方向才不至于在洋洋灑灑的源碼里一頭霧水。
那么,我們到底要找什么?

🏹對!我們想要知道的是Nacos是如何給@NacosValue標注的字段賦值的。🏹

然后再來看代碼,是否就清晰了一點?

🏹對!代碼中的關鍵詞就是process🏹

那就繼續看postProcessor.postProcessBeanFactory((ConfigurableListableBeanFactory) beanFactory);

@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)throws BeansException {String[] abstractNacosPropertySourceBuilderBeanNames = BeanUtils.getBeanNames(beanFactory, AbstractNacosPropertySourceBuilder.class);this.nacosPropertySourceBuilders = new ArrayList<AbstractNacosPropertySourceBuilder>(abstractNacosPropertySourceBuilderBeanNames.length);for (String beanName : abstractNacosPropertySourceBuilderBeanNames) {this.nacosPropertySourceBuilders.add(beanFactory.getBean(beanName,AbstractNacosPropertySourceBuilder.class));}NacosPropertySourcePostProcessor.beanFactory = beanFactory;this.configServiceBeanBuilder = getConfigServiceBeanBuilder(beanFactory);String[] beanNames = beanFactory.getBeanDefinitionNames();for (String beanName : beanNames) {processPropertySource(beanName, beanFactory);}
}

有了關鍵詞,那我們就繼續看processPropertySource(beanName, beanFactory);

private void processPropertySource(String beanName,ConfigurableListableBeanFactory beanFactory) {//processedBeanNames記錄的是已經處理過的beanName, 看下這個方法的最后一行就知道了。if (processedBeanNames.contains(beanName)) {return;}//BeanDefinition:通過spring factory獲取的bean定義類BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName);// Build multiple instance if possibleList<NacosPropertySource> nacosPropertySources = buildNacosPropertySources(beanName, beanDefinition);// Add Orderlyfor (NacosPropertySource nacosPropertySource : nacosPropertySources) {addNacosPropertySource(nacosPropertySource);Properties properties = configServiceBeanBuilder.resolveProperties(nacosPropertySource.getAttributesMetadata());addListenerIfAutoRefreshed(nacosPropertySource, properties, environment);}processedBeanNames.add(beanName);
}private List<NacosPropertySource> buildNacosPropertySources(String beanName,BeanDefinition beanDefinition) {for (AbstractNacosPropertySourceBuilder builder : nacosPropertySourceBuilders) {if (builder.supports(beanDefinition)) {return builder.build(beanName, beanDefinition);}}return Collections.emptyList();
}

builder.build(beanName, beanDefinition)
我們來著重看下這個方法

三、AbstractNacosPropertySourceBuilder

我們看下這個build方法的具體實現

public List<NacosPropertySource> build(String beanName, T beanDefinition) {Map<String, Object>[] attributesArray = resolveRuntimeAttributesArray(beanDefinition, globalNacosProperties);int size = attributesArray == null ? 0 : attributesArray.length;if (size == 0) {return Collections.emptyList();}List<NacosPropertySource> nacosPropertySources = new ArrayList<NacosPropertySource>(size);for (int i = 0; i < size; i++) {Map<String, Object> attributes = attributesArray[i];if (!CollectionUtils.isEmpty(attributes)) {NacosPropertySource nacosPropertySource = doBuild(beanName,beanDefinition, attributesArray[i]);NacosConfigMetadataEvent metadataEvent = createMetaEvent(nacosPropertySource, beanDefinition);initMetadataEvent(nacosPropertySource, beanDefinition, metadataEvent);publishMetadataEvent(metadataEvent);nacosPropertySources.add(nacosPropertySource);}}return nacosPropertySources;
}

這個方法返回的是List<NacosPropertySource>,而NacosPropertySource是在doBuild(beanName,beanDefinition, attributesArray[i]);這里給出的,那就著重看下這里的實現。

ps: 篇幅限制,只給出重要代碼

protected NacosPropertySource doBuild(String beanName, T beanDefinition,Map<String, Object> runtimeAttributes) {//。。。String nacosConfig = nacosConfigLoader.load(dataId, groupId, nacosProperties);//。。。NacosPropertySource nacosPropertySource = new NacosPropertySource(dataId, groupId,name, nacosConfig, type);//。。。
}

NacosPropertySource中存放配置的位置:在這里插入圖片描述

這個方法主要做了兩件事:

  1. 獲取 nacosConfig。我們知道,Nacos客戶端在第一次獲取數據的時候會去server端全量拉取一次,那所以這里肯定有和服務端交互的邏輯。
  2. 生成NacosPropertySource:這是doBuild要返回的數據。

總結「AI生成」

本文分析了Nacos客戶端源碼,重點探討了Nacos作為配置中心的主要邏輯。以下是關鍵類的描述和功能總結:

  1. NacosConfigAutoConfiguration

    • 位于Spring的spring.factories中,負責自動配置Nacos。雖然類本身不包含邏輯,但通過@EnableNacosConfig注解引入了Nacos配置的核心類NacosConfigBeanDefinitionRegistrar
  2. NacosConfigBeanDefinitionRegistrar

    • 負責注冊Nacos的相關Bean定義。主要方法registerBeanDefinitions包括注冊全局Nacos屬性、Nacos通用Bean和Nacos配置Bean,并調用NacosPropertySourcePostProcessor處理后置邏輯。
  3. NacosPropertySourcePostProcessor

    • 通過invokeNacosPropertySourcePostProcessor方法調用,負責后置處理邏輯,主要處理配置源的加載和Nacos屬性的解析。其核心方法postProcessBeanFactory遍歷所有Bean定義并處理Nacos配置源。
  4. AbstractNacosPropertySourceBuilder

    • 通過build方法構建NacosPropertySource。該方法首先解析運行時屬性數組,然后根據屬性構建Nacos配置源。核心方法doBuild實現了與Nacos服務端的交互,獲取配置數據并生成NacosPropertySource
  5. NacosPropertySource

    • 存放從Nacos服務端獲取的配置數據,是Nacos配置管理的核心數據結構。

本文通過深入分析這些關鍵類和方法,揭示了Nacos客戶端在作為配置中心時的工作機制,特別是如何通過@NacosValue注解為字段賦值的流程。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/38342.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/38342.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/38342.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

zram壓縮機制看swapon系統調用

1.swapon開啟zram交換分區 swapon /dev/block/zram0 mkswap /dev/block/zram0 上面命令調用了linux的swapon系統調用啟動zram0交換分區;mkswap命令向塊設備文件/dev/block/zram0寫入了swap_header信息 問題:實際安卓平臺是哪里觸發swapon和mkswap調用的,我們已MTK8195平臺…

平衡三進制類腦計算

PS:用來記錄一些新奇又有趣的想法。。。 1、量子的世界 1.1薛定諤的貓 這感覺是個有趣的話題。 在宏觀中可以觀測到的&#xff0c;是穩定的兩種狀態&#xff0c;但隨著尺寸不斷縮小&#xff0c;直至達到微觀尺度&#xff0c;這一切都變的有趣了起來&#xff0c;一只“既死又活…

zabbix server client 安裝配置

Zabbix Server 采用源碼包部署&#xff0c;數據庫采用 MySQL8.0 版本&#xff0c;zabbix-web 使用 nginxphp 來實現。具體信息如下&#xff1a; 軟件名 版本 安裝方式 Zabbix Server 6.0.3 源碼安裝 Zabbix Agent 6.0.3 源碼安裝 MySQL 8.0.28 yum安裝 Nginx 1.20…

Ubuntu20.04安裝vimplus插件

參考文章&#xff1a; Ubuntu Linux下vimplus的安裝及使用安裝vimplus之后亂碼問題解決 1、安裝步驟&#xff1a; $ git clone https://github.com/chxuan/vimplus.git ~/.vimplus$ cd ~/.vimplus$ ./install.sh2、./install.sh 過程 出現選擇是否備份 /home/yin-roc/.vim…

一個中文和越南語雙語版本的助貸平臺開源源碼

一個中文和越南語雙語版本的助貸平臺開源源碼。后臺試nodejs。 后臺 代理 前端均為vue源碼&#xff0c;前端有中文和越南語。 前端ui黃色大氣&#xff0c;邏輯操作簡單&#xff0c;注冊可對接國際短信&#xff0c;可不對接。 用戶注冊進去填寫資料&#xff0c;后臺審批&…

庫存管理系統基于spingboot vue的前后端分離倉庫庫存管理系統java項目java課程設計java畢業設計

文章目錄 庫存管理系統一、項目演示二、項目介紹三、部分功能截圖四、部分代碼展示五、底部獲取項目源碼&#xff08;9.9&#xffe5;帶走&#xff09; 庫存管理系統 一、項目演示 庫存管理系統 二、項目介紹 基于spingboot和vue前后端分離的庫存管理系統 功能模塊&#xff…

熱題系列章節7

劍指 Offer 04. 二維數組中的查找 題目描述&#xff1a; 在一個二維數組中&#xff08;每個一維數組的長度相同&#xff09;&#xff0c;每一行都按照從左到右遞增的順序排序&#xff0c;每一列都按照從上到下遞增的順序排序。請完成一個函數&#xff0c;輸入這樣的一個二維數…

Go 語言環境搭建

本篇文章為Go語言環境搭建及下載編譯器后配置Git終端方法。 目錄 安裝GO語言SDK Window環境安裝 下載 安裝測試 安裝編輯器 下載編譯器 設置git終端方法 總結 安裝GO語言SDK Window環境安裝 網站 Go下載 - Go語言中文網 - Golang中文社區 還有 All releases - The…

策略模式在金融業務中的應用及其框架實現

引言 策略模式&#xff08;Strategy Pattern&#xff09;是一種行為設計模式&#xff0c;它允許在不修改客戶端代碼的情況下&#xff0c;動態地改變一個類的行為。它通過定義一系列算法并將它們封裝在獨立的策略類中&#xff0c;使這些算法可以互相替換&#xff0c;而不會影響…

Spark Cache 的用武之地

在什么情況下適合使用 Cache 我建議你在做決策的時候遵循以下 2 條基本原則&#xff1a; 如果 RDD/DataFrame/Dataset 在應用中的引用次數為 1&#xff0c;就堅決不使用 Cache如果引用次數大于 1&#xff0c;且運行成本占比超過 30%&#xff0c;應當考慮啟用 Cache第一條很好…

各維度卷積神經網絡內容收錄

各維度卷積神經網絡內容收錄 卷積神經網絡&#xff08;CNN&#xff09;&#xff0c;通常是指用于圖像分類的2D CNN。但是&#xff0c;現實世界中還使用了其他兩種類型的卷積神經網絡&#xff0c;即1D CNN和3D CNN。 在1D CNN中&#xff0c;內核沿1個方向移動。1D CNN的輸入和…

高通Android 12 /13根據包名授權懸浮窗權限

代碼路徑frameworks/base/service/core/com/android/server/policy/PhoneWindowManager.java 1、 PhoneWindowManager.java中關于根據包名實現懸浮窗權限授權的功能實現 在實現根據包名授予懸浮窗權限的核心的功能開發中&#xff0c;在通過上述的功能原理實現的過程中分析得知…

EigenLayer 生態解析-再質押與 AVS 崛起

基于以太坊網絡的再質押協議 EigenLayer 提出了利用為以太坊網絡驗證而質押的 ETH 來與其他協議共享安全性和資本效率,同時為協議參與者提供額外利息。在 AVS、再質押、積分系統等概念的推動下,逐漸形成一個龐大的生態系統,從 2024 年初到現在 EigenLayer 的 TVL 增加了 12 …

5.Spring IOC 循環依賴問題源碼深度剖析

Spring IOC 容器解決循環依賴問題主要涉及到幾個關鍵的緩存和對象創建過程中的處理邏輯。以下是對循環依賴問題進行深度剖析的概述&#xff1a; 循環依賴的背景 循環依賴發生在兩個或多個Bean相互依賴對方&#xff0c;形成一個閉環。這可能是直接的&#xff0c;比如Bean A依賴B…

全球最大智能立體書庫|北京:3萬貨位,715萬冊,自動出庫、分揀、搬運

導語 大家好&#xff0c;我是社長&#xff0c;老K。專注分享智能制造和智能倉儲物流等內容。 新書《智能物流系統構成與技術實踐》 北京城市圖書館的立體書庫采用了先進的WMS&#xff08;倉庫管理系統&#xff09;和WCS&#xff08;倉庫控制系統&#xff09;&#xff0c;與圖書…

Linux磁盤監控思路分析

磁盤監控原理 設備又名I/O設備&#xff0c;泛指計算機系統中除主機以外的所有外部設備。 1.1 計算機分類 1.1.1 按照信息傳輸速度分&#xff1a; 1.低速設備&#xff1a;每秒傳輸信息僅幾個字節或者百個字節&#xff0c;如&#xff1a;鍵盤、鼠標等 2.中速設備&#xff1a…

leetCode.98. 驗證二叉搜索樹

leetCode.98. 驗證二叉搜索樹 題目描述 代碼 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(n…

100張linux C/C++工程師面試高質量圖

文章目錄 雜項BIOSlinux開機啟動流程內核啟動流程網絡編程網絡編程流程tcp狀態機三次握手四次斷開reactor模型proactor模型select原理poll原理epoll原理文件系統虛擬文件系統文件系統調用阻塞IO非阻塞IO異步IO同步阻塞同步非阻塞IO多路復用進程管理進程狀態程序加載內存管理MMU…

力扣(2024.06.30)

1. 81——搜索旋轉排序數組2 已知存在一個按非降序排列的整數數組 nums &#xff0c;數組中的值不必互不相同。 在傳遞給函數之前&#xff0c;nums 在預先未知的某個下標 k&#xff08;0 < k < nums.length&#xff09;上進行了旋轉&#xff0c;使數組變為 [nums[k], n…

vue響應式原理細節分享

在講解之前&#xff0c;我們先了解一下數據響應式是什么&#xff1f;所謂數據響應式就是建立響應式數據與依賴&#xff08;調用了響應式數據的操作&#xff09;之間的關系&#xff0c;當響應式數據發生變化時&#xff0c;可以通知那些使用了這些響應式數據的依賴操作進行相關更…