@RefreshScope 核心原理深度解析:Spring Boot 的動態魔法

讓我們通過全新的原理圖解和代碼級分析,揭開@RefreshScope實現配置熱更新的神秘面紗!


一、工作原理全景圖(優化版)

開發者/運維配置文件Spring Boot應用Spring容器動態代理ClientNew Bean修改配置文件內容發送POST /actuator/refresh觸發RefreshEvent事件標記@RefreshScope Bean過期調用Bean方法檢查Bean是否過期?銷毀舊Bean實例創建新Bean實例注入新配置值更新代理目標alt[已過期]轉發方法調用返回結果返回新配置結果loop[請求處理流程]開發者/運維配置文件Spring Boot應用Spring容器動態代理ClientNew Bean

二、核心組件協作解析

1. 組件關系圖
觸發刷新
注冊Bean
代理增強
RefreshScope
+destroy()
+get()
?abstract?
GenericScope
+postProcessBeanFactory()
RefreshEventListener
+handle(RefreshEvent)
AnnotatedBeanDefinitionReader
+registerBean()
ConfigurationClassPostProcessor
+enhanceConfigurationClasses()
2. 關鍵組件職責
組件職責關鍵方法
@RefreshScope標記Bean支持動態刷新-
RefreshScope管理Bean生命周期destroy(), get()
RefreshEventListener監聽配置刷新事件handle(RefreshEvent)
ConfigurationClassPostProcessor創建作用域代理enhanceConfigurationClasses()
ScopedProxyFactoryBean生成動態代理對象getObject()

三、動態代理實現原理(代碼級剖析)

1. 代理創建流程
// Spring容器初始化時
public class ConfigurationClassPostProcessor {public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {for (String beanName : beanFactory.getBeanDefinitionNames()) {BeanDefinition bd = beanFactory.getBeanDefinition(beanName);if (bd.getScope().equals(RefreshScope.SCOPE_REFRESH)) {// 創建作用域代理BeanDefinition proxyDef = ScopedProxyCreator.createScopedProxy(new BeanDefinitionHolder(bd, beanName), beanFactory, true);// 替換原始Bean定義beanFactory.registerBeanDefinition(beanName, proxyDef);}}}
}
2. 代理對象執行邏輯
public class RefreshScopeProxy implements MethodInterceptor {private BeanFactory beanFactory;private String targetBeanName;private Object target; // 當前目標對象public Object invoke(MethodInvocation invocation) throws Throwable {// 檢查是否需要刷新if (isBeanExpired()) {synchronized(this) {if (isBeanExpired()) {// 1. 銷毀舊實例beanFactory.destroyScopedBean(targetBeanName);// 2. 創建新實例target = beanFactory.getBean(targetBeanName);}}}// 轉發到目標對象return invocation.getMethod().invoke(target, invocation.getArguments());}private boolean isBeanExpired() {// 檢查Scope中的過期標記RefreshScope scope = beanFactory.getBean(RefreshScope.class);return scope.isBeanExpired(targetBeanName);}
}

四、配置刷新事件傳播鏈

POST /actuator/refresh
RefreshEndpoint.refresh
ContextRefresher.refresh
發布EnvironmentChangeEvent
RefreshEventListener.onApplicationEvent
RefreshScope.refreshAll
標記所有Bean過期
清理Bean緩存
關鍵代碼實現:
// org.springframework.cloud.context.refresh.ContextRefresher
public synchronized Set<String> refresh() {// 1. 更新環境變量Map<String, Object> before = extract(this.context.getEnvironment().getPropertySources());addConfigFilesToEnvironment();// 2. 發布環境變更事件Set<String> keys = changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();this.context.publishEvent(new EnvironmentChangeEvent(context, keys));// 3. 觸發Scope刷新this.scope.refreshAll();return keys;
}// org.springframework.cloud.context.scope.refresh.RefreshScope
public void refreshAll() {// 標記所有Bean過期this.cache.clear();// 發布RefreshScopeRefreshedEventpublishEvent(new RefreshScopeRefreshedEvent());
}

五、典型場景執行流程

場景:更新數據庫超時配置
管理員應用服務數據庫修改timeout=5000ms發送/actuator/refresh標記DataSourceConfig過期發起訂單查詢請求檢查DataSourceConfig代理重建DataSourceConfig注入新timeout值執行查詢(timeout=5000ms)返回結果返回響應管理員應用服務數據庫
關鍵時序說明:
  1. 配置變更:管理員修改數據庫超時配置
  2. 觸發刷新:調用Actuator端點
  3. 惰性重建:Bean在首次使用時重建
  4. 新值生效:新配置在數據庫操作中應用

六、性能優化關鍵點

1. 代理層級控制
@Service
@RefreshScope
public class OrderService {// 推薦:僅代理需要刷新的組件@Autowiredprivate PaymentService paymentService; // 普通注入
}
2. 部分刷新策略
// 自定義刷新策略
@RefreshScope(proxyMode = ScopedProxyMode.TARGET_CLASS)
public class CustomRefresher {// 僅刷新帶注解的字段@Refreshable private String dynamicField;
}
3. 批量刷新優化
// 批量刷新配置類
@Configuration
@RefreshScope
public class BatchConfig {@Value("${batch.size}")private int batchSize; // 批量更新時減少重建次數
}

七、與普通Bean的生命周期對比

階段標準Bean@RefreshScope Bean
初始化容器啟動時創建容器啟動時創建代理
依賴注入啟動時完成首次訪問時完成
配置綁定啟動時固定每次重建時更新
銷毀時機容器關閉時配置刷新時
內存占用常駐內存支持舊實例GC回收

結語:動態配置的藝術

@RefreshScope的精妙之處在于:

  1. 懶加載思想:按需重建,避免不必要的開銷
  2. 代理模式:無感切換底層實現
  3. 事件驅動:優雅解耦組件關系
  4. 作用域擴展:Spring核心機制的自然延伸

最佳實踐提示:在微服務架構中,結合Spring Cloud Config和Bus實現集群級配置刷新,可達到"一次修改,全網生效"的效果!

通過本文的全新圖解和代碼級分析,您應該對@RefreshScope的內部機制有了更深入的了解。下次當您的配置動態更新時,不妨想象一下背后這場精妙的"Bean換裝秀"!

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

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

相關文章

萬字詳解——OSI七層模型:網絡通信的完整架構解析

OSI七層模型&#xff1a;網絡通信的完整架構解析OSI&#xff08;Open Systems Interconnection&#xff09;七層模型是計算機網絡領域最基礎、最權威的參考框架。它由國際標準化組織&#xff08;ISO&#xff09;于1984年提出&#xff0c;旨在為不同廠商、不同技術的網絡設備和系…

一個人開發一個App(OpenApi)

為了少寫代碼&#xff0c;統一前后端的網絡層&#xff0c;我使用了OpenApi設計restful接口。然后用openapi-generator來生成flutter的代碼。生成go代碼用的是oapi-codegen,它對go更友好一些。 我們直接在api.yml中設計接口&#xff0c;所有的返回值與請求者都提取到components里…

光伏氣象監測系統:助力光伏發電的智慧大腦

光伏氣象監測系統&#xff1a;助力光伏發電的智慧大腦 柏峰【BF-GFQX】在全球積極推動能源轉型、大力倡導 “雙碳” 目標的當下&#xff0c;光伏發電憑借其清潔、可再生的顯著優勢&#xff0c;宛如一顆冉冉升起的新星&#xff0c;在能源領域迅速嶄露頭角&#xff0c;得以廣泛推…

SpringCloud01——項目演變、微服務遠程調用三種方式、springcloud介紹、nacos注冊中心

目錄 一、項目架構演變過程 1、單體應用架構 2、垂直應用架構 3、分布式服務架構 4、流動計算架構&#xff08;SOA架構&#xff09; 5、微服務架構 二、如何實現微服務遠程調用 1、HttpClient工具類&#xff08;springboot中&#xff09; 形式1&#xff1a;調用第三方…

Oracle 和 MySQL 中的日期類型比較

Oracle 和 MySQL 都提供了多種日期和時間數據類型&#xff0c;但它們在實現和功能上有一些差異。以下是兩者的主要日期類型對比&#xff1a;Oracle 日期類型DATE存儲日期和時間&#xff08;精確到秒&#xff09;格式&#xff1a;YYYY-MM-DD HH24:MI:SS示例&#xff1a;TO_DATE(…

基于 Redis 實現共享 Session 登錄的多種方法與實踐

全文目錄&#xff1a;開篇語**前言****1. 什么是共享 Session 登錄&#xff1f;****2. 基于 Redis 實現共享 Session 的基本方法****2.1 通過 Redis 存儲 Session 數據****2.1.1 基本流程****2.1.2 示例代碼&#xff08;Java Spring Boot Redis&#xff09;****3. 使用 Redis…

spring cloud + easyRules 零基礎搭建智能規則引擎

你是否曾想過在項目中嵌入一套輕量級且高度可擴展的規則引擎&#xff0c;輕松實現動態化的業務決策&#xff1f;在金融、電商、政務等領域&#xff0c;風險控制是業務安全的核心。傳統硬編碼方式很難應對復雜多變的風控需求&#xff0c;而規則引擎允許我們將這些規則獨立出來&a…

AI應用:電路板設計

Diode Computers 公司 Diode Computers是一家專注于利用AI技術進行定制電路板設計和制造的公司&#xff0c;提供從概念到量產的全流程服務。其核心優勢在于將電路板設計轉化為AI可理解的代碼形式&#xff0c;大幅提升設計效率并降低傳統EDA工具的使用門檻 0。 核心服務 設計與制…

RocketMQ學習系列之——客戶端消息確認機制

一、客戶端使用MQ基本代碼示例1、添加maven依賴<dependency><groupId>org.apache.rocketmq</groupId><artifactId>rocketmq-client</artifactId><version>5.3.0</version> </dependency>2、生產者代碼示例public class Produc…

[leetcode] 組合總和

39. 組合總和 - 力扣&#xff08;LeetCode&#xff09; i class Solution {int aim;vector<vector<int>> ret;vector<int> path; public:vector<vector<int>> combinationSum(vector<int>& nums, int target) {aim target;dfs(nums…

新能源行業B端極簡設計:碳中和目標下的交互輕量化實踐

新能源行業B端極簡設計&#xff1a;碳中和目標下的交互輕量化實踐內容摘要在新能源行業&#xff0c;碳中和目標正推動著企業追求更高的運營效率和更低的資源消耗。然而&#xff0c;傳統的B端交互設計往往復雜繁瑣&#xff0c;不僅增加了用戶的操作成本&#xff0c;還可能導致資…

減速機:自動化生產線的“精密傳動心臟”

減速機作為自動化生產線的核心傳動部件&#xff0c;通過調節轉速與扭矩實現設備精準控制&#xff0c;其在自動化生產線中發揮著關鍵作用。以下是其具體應用方式&#xff1a;輸送線驅動在自動化生產線中&#xff0c;輸送線用于運輸物料、半成品或成品&#xff0c;通過減速機可以…

從0到1學PHP(五):PHP 數組:高效存儲與處理數據

目錄一、數組的定義與分類1.1 索引數組1.2 關聯數組1.3 多維數組二、數組的基本操作2.1 數組元素的添加、刪除、修改和訪問2.2 數組指針的操作三、數組處理函數3.1 數組排序函數3.2 數組統計函數3.3 數組過濾與轉換函數一、數組的定義與分類 在 PHP 中&#xff0c;數組是一種非…

vscode 字體的跟換

打開vscode 左下角輸入電腦中已經有的字體&#xff1a;有想要用的可以自己進行安裝刷新這樣就可改變了

墨者:SQL過濾字符后手工注入漏洞測試(第3題)

1. 墨者學院&#xff1a;SQL過濾字符后手工注入漏洞測試(第3題)&#x1f680; 因為練習過太多的sql注入&#xff0c;廢話不多介紹&#xff0c;我會通過圍繞手動注入和工具爆破的方式達到靶場目標&#xff0c;開練&#xff01;&#xff01;&#xff01; 2. 手工注入方式&#x1…

【Spring AI實戰】實現仿DeepSeek頁面對話機器人(支持多模態上傳)

一、前言 二、實現效果 三、代碼實現 3.1 后端代碼 3.2 前端代碼 一、前言 Spring AI詳解&#xff1a;【Spring AI詳解】開啟Java生態的智能應用開發新時代(附不同功能的Spring AI實戰項目)-CSDN博客 二、實現效果 可上傳圖片或音頻數據給大模型分析 三、代碼實現 3.1 后…

Vue 正在熱映模塊

Vue 漸進式JavaScript 框架 基于Vue2的移動端項目&#xff1a;正在熱映模塊 目錄 正在熱映 數據修改 導入axios 配置反向代理 正在熱映渲染 賦值數據 渲染列表 顯示圖片 優化列表 設置列表樣式 主演 定義過濾器 使用過濾器 主演過長處理 無主演情況處理 觀眾評…

阿里云上進行k8s集群的配置

在阿里云容器服務Kubernetes&#xff08;ACK&#xff09;中配置集群的核心步驟可分為以下六大關鍵環節&#xff0c;涵蓋架構設計到運維管理&#xff1a;1. 集群規劃與基礎配置 集群類型選擇 托管版&#xff1a;Master節點由阿里云托管&#xff08;推薦生產環境&#xff09;專有…

頁面性能優化

優化點解決方案效果雙向綁定數量過多競對設置單元格內部涉及雙向綁定的輸入組件過多&#xff0c;線上頁面最多有88個該和抽屜中的編輯表格一樣的組件&#xff0c;共計930個&#xff08;按每行最少6個來計算的&#xff09;雙向綁定的組件&#xff0c;嚴重拖累頁面性能。數據計算…

詳細說明零拷貝

詳細說明零拷貝【一】零拷貝介紹【1】說明【2】為什么需要零拷貝&#xff1f;—— 傳統數據傳輸的問題【3】零拷貝的核心優化【4】零拷貝的實現方式&#xff08;1&#xff09;mmap&#xff08;內存映射&#xff09;&#xff08;2&#xff09;sendfile&#xff08;Linux 系統調用…