@RefreshScope(nacos配置熱更新方式)
@RefreshScope(nacos配置熱更新)
源碼分析
宏觀流程解析
1.spring對@RefreshScopre注解的bean做的事情
- 當調(diào)用被@RefreshScope注解的bean的屬性的get方法時 則先從本地緩存里面獲取
- 當本地緩存中 不存在當前bean時 則重新創(chuàng)建 此時 會獲取 spring中最新環(huán)境配置
- 如果本地緩存中 存在當前 bean則 直接返回對應屬性值
2.nacos對@RefreshScopre注解的bean做的事情
- 當配置更改時 nacos服務端會發(fā)步一個配置已被更新事件
- 此時 naocs客戶端 會接受到這個事件 接受到以后 會再在spring中發(fā)布環(huán)境配置刷新事件
- 然后 對應的監(jiān)聽器 收到以后 則刷新spring環(huán)境配置 以及 清空本地緩存
源碼解析
@Target({ ElementType.TYPE, ElementType.METHOD }) @Retention(RetentionPolicy.RUNTIME) @Scope("refresh") @Documented public @interface RefreshScope { /** * @see Scope#proxyMode() * @return proxy mode */ ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS; }
org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan
org.springframework.context.annotation.AnnotationConfigUtils#applyScopedProxyMode -->org.springframework.context.annotation.ScopedProxyCreator#createScopedProxy -->org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy
org.springframework.cloud.context.scope.GenericScope#postProcessBeanDefinitionRegistry
org.springframework.cloud.context.scope.GenericScope.LockedScopedProxyFactoryBean#setBeanFactory
org.springframework.aop.scope.ScopedProxyFactoryBean#setBeanFactory
創(chuàng)建代理
------由上可知,被@RefreshScope注解的bean被包裝為一個
FactoryBean(org.springframework.cloud.context.scope.GenericScope.LockedScopedProxyFactoryBean)
由此調(diào)用時就會調(diào)用getObject()方法,這樣就會得到一個代理對象,執(zhí)行時會獲取到目標對象 SimpleBeanTargetSource.getTarget(),以"scopedTarget."開頭的bean,接下來看一下該bean的創(chuàng)建時機
創(chuàng)建target
org.springframework.cloud.context.scope.refresh.RefreshScope#onApplicationEvent
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.cloud.context.scope.GenericScope#get
以上即@RefreshScope的相關對象的創(chuàng)建
由上可知,目標類都會存于scope的cache里
NacosContextRefresher(nacos配置刷新)
public class NacosContextRefresher implements ApplicationListener<ApplicationReadyEvent>, ApplicationContextAware { public void onApplicationEvent(ApplicationReadyEvent event) { // many Spring context if (this.ready.compareAndSet(false, true)) { this.registerNacosListenersForApplications(); } } }
com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListenersForApplications --->com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener
注冊監(jiān)聽器,監(jiān)聽nacos配置變化,并發(fā)布RefreshEvent
org.springframework.cloud.endpoint.event.RefreshEventListener#onApplicationEvent
org.springframework.cloud.context.refresh.ContextRefresher#refresh
1.刷新了環(huán)境,2清空cache
首先刷新環(huán)境
如下,有個前后對比,關鍵就在addConfigFilesToEnvironment()
首先copyEnvironment,雖說是copy,這里只保留了一些最基本的配置,如下
第二步,創(chuàng)建Spring容器 capture = builder.run();
這里還是走之前的邏輯,具體可參考
只是這次創(chuàng)建的兩個Spring容器都為AnnotationConfigApplicationContext,并且用完就關了
我們看一下方法執(zhí)行之后的environment
之后的邏輯就是對比兩個環(huán)境進行替換了,這就是刷新環(huán)境的大致流程
然后清空cache
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
JavaEE的進程,線程和創(chuàng)建線程的5種方式詳解
這篇文章主要為大家詳細介紹了JavaEE的進程,線程和創(chuàng)建線程的5種方式,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03Java中Set集合轉(zhuǎn)為List集合常見的兩種方式
List是Java中比較常用的集合類,指一系列存儲數(shù)據(jù)的接口和類,可以解決復雜的數(shù)據(jù)存儲問題,這篇文章主要給大家介紹了關于Java中Set集合轉(zhuǎn)為List集合常見的兩種方式,需要的朋友可以參考下2023-12-12基于SpringBoot整合SSMP案例(開啟日志與分頁查詢條件查詢功能實現(xiàn))
這篇文章主要介紹了基于SpringBoot整合SSMP案例(開啟日志與分頁查詢條件查詢功能實現(xiàn)),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋參考下吧2023-11-11Java面試題沖刺第十三天--數(shù)據(jù)庫(3)
這篇文章主要為大家分享了最有價值的三道數(shù)據(jù)庫面試題,涵蓋內(nèi)容全面,包括數(shù)據(jù)結構和算法相關的題目、經(jīng)典面試編程題等,感興趣的小伙伴們可以參考一下2021-07-07打開.properties中文顯示unicode編碼問題以及解決
這篇文章主要介紹了打開.properties中文顯示unicode編碼問題以及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01Spring集成MyBatis?及Aop分頁的實現(xiàn)代碼
這篇文章主要介紹了Spring集成MyBatis?及Aop分頁的實現(xiàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04SpringBoot實現(xiàn)短信發(fā)送及手機驗證碼登錄
本文主要介紹了SpringBoot實現(xiàn)短信發(fā)送及手機驗證碼登錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07