日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 前端技术 > javascript >内容正文

javascript

Spring Cloud @RefreshScope 原理是什么?

發(fā)布時(shí)間:2025/3/21 javascript 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring Cloud @RefreshScope 原理是什么? 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

要清楚RefreshScope,先要了解Scope

Scope(org.springframework.beans.factory.config.Scope)是Spring 2.0開(kāi)始就有的核心的概念

RefreshScope(org.springframework.cloud.context.scope.refresh)是spring cloud提供的一種特殊的scope實(shí)現(xiàn),用來(lái)實(shí)現(xiàn)配置、實(shí)例熱加載。

Scope -> GenericScope -> RefreshScope

Scope與ApplicationContext生命周期

AbstractBeanFactory#doGetBean創(chuàng)建Bean實(shí)例

protected?<T>?T?doGetBean(...){final?RootBeanDefinition?mbd?=?...if?(mbd.isSingleton())?{...}?else?if?(mbd.isPrototype())...}?else?{String?scopeName?=?mbd.getScope();final?Scope?scope?=?this.scopes.get(scopeName);Object?scopedInstance?=?scope.get(beanName,?new?ObjectFactory<Object>()?{...});...}... }

Singleton和Prototype是硬編碼的,并不是Scope子類。

Scope實(shí)際上是自定義擴(kuò)展的接口,Scope?Bean實(shí)例交由Scope自己創(chuàng)建,例如SessionScope是從Session中獲取實(shí)例的,ThreadScope是從ThreadLocal中獲取的,而RefreshScope是在內(nèi)建緩存中獲取的。

@Scope 對(duì)象的實(shí)例化

@RefreshScope 是scopeName="refresh"的 @Scope

... @Scope("refresh") public?@interface?RefreshScope?{... }

@Scope 的注冊(cè) AnnotatedBeanDefinitionReader#registerBean

public?void?registerBean(...){ ... ScopeMetadata?scopeMetadata?=?this.scopeMetadataResolver.resolveScopeMetadata(abd);abd.setScope(scopeMetadata.getScopeName());...definitionHolder?=?AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata,?definitionHolder,?this.registry); }

讀取@Scope元數(shù)據(jù), AnnotationScopeMetadataResolver#resolveScopeMetadata

public?ScopeMetadata?resolveScopeMetadata(BeanDefinition?definition)?{AnnotationAttributes?attributes?=?AnnotationConfigUtils.attributesFor(annDef.getMetadata(),?Scope.class);if?(attributes?!=?null)?{metadata.setScopeName(attributes.getString("value"));ScopedProxyMode?proxyMode?=?attributes.getEnum("proxyMode");if?(proxyMode?==?null?||?proxyMode?==?ScopedProxyMode.DEFAULT)?{proxyMode?=?this.defaultProxyMode;}metadata.setScopedProxyMode(proxyMode);} }

Scope實(shí)例對(duì)象通過(guò)ScopedProxyFactoryBean創(chuàng)建,其中通過(guò)AOP使其實(shí)現(xiàn)ScopedObject接口,這里不再展開(kāi)。

說(shuō)RefreshScope是如何實(shí)現(xiàn)配置和實(shí)例刷新的

RefreshScope注冊(cè)

RefreshAutoConfiguration#RefreshScopeConfiguration

@Component @ConditionalOnMissingBean(RefreshScope.class) protected?static?class?RefreshScopeConfiguration?implements?BeanDefinitionRegistryPostProcessor{ ...registry.registerBeanDefinition("refreshScope",BeanDefinitionBuilder.genericBeanDefinition(RefreshScope.class).setRole(BeanDefinition.ROLE_INFRASTRUCTURE).getBeanDefinition()); ... }

RefreshScope extends GenericScope, 大部分邏輯在 GenericScope 中。

GenericScope#postProcessBeanFactory 中向AbstractBeanFactory注冊(cè)自己

public?class?GenericScope?implements?Scope,?BeanFactoryPostProcessor...{@Overridepublic?void?postProcessBeanFactory(ConfigurableListableBeanFactory?beanFactory)throws?BeansException?{beanFactory.registerScope(this.name/*refresh*/,?this/*RefreshScope*/);...} }

RefreshScope 刷新過(guò)程

入口在ContextRefresher#refresh

refresh()?{Map<String,?Object>?before?=?①extract(this.context.getEnvironment().getPropertySources());②addConfigFilesToEnvironment();Set<String>?keys?=?④changes(before,③extract(this.context.getEnvironment().getPropertySources())).keySet();this.context.⑤publishEvent(new?EnvironmentChangeEvent(keys));this.scope.⑥r(nóng)efreshAll();}

①提取標(biāo)準(zhǔn)參數(shù)(SYSTEM,JNDI,SERVLET)之外所有參數(shù)變量

②把原來(lái)的Environment里的參數(shù)放到一個(gè)新建的Spring Context容器下重新加載,完事之后關(guān)閉新容器

③提起更新過(guò)的參數(shù)(排除標(biāo)準(zhǔn)參數(shù))

④比較出變更項(xiàng)

⑤發(fā)布環(huán)境變更事件,接收:EnvironmentChangeListener/LoggingRebinder

⑥RefreshScope用新的環(huán)境參數(shù)重新生成Bean,重新生成的過(guò)程很簡(jiǎn)單,清除refreshscope緩存幷銷毀Bean,下次就會(huì)重新從BeanFactory獲取一個(gè)新的實(shí)例(該實(shí)例使用新的配置)

RefreshScope#refreshAll

public?void?refreshAll()?{<b>super.destroy();</b>this.context.publishEvent(new?RefreshScopeRefreshedEvent()); }

GenericScope#destroy

public?void?destroy()?{...Collection<BeanLifecycleWrapper>?wrappers?=?<b>this.cache.clear()</b>;for?(BeanLifecycleWrapper?wrapper?:?wrappers)?{<b>wrapper.destroy();</b>} }

Spring Cloud Bus 如何觸發(fā) Refresh

BusAutoConfiguration#BusRefreshConfiguration 發(fā)布一個(gè)RefreshBusEndpoint

@Configuration @ConditionalOnClass({?Endpoint.class,?RefreshScope.class?}) protected?static?class?BusRefreshConfiguration?{@Configuration@ConditionalOnBean(ContextRefresher.class)@ConditionalOnProperty(value?=?"endpoints.spring.cloud.bus.refresh.enabled",?matchIfMissing?=?true)protected?static?class?BusRefreshEndpointConfiguration?{@Beanpublic?RefreshBusEndpoint?refreshBusEndpoint(ApplicationContext?context,BusProperties?bus)?{return?new?RefreshBusEndpoint(context,?bus.getId());}} }

RefreshBusEndpoint 會(huì)從http端口觸發(fā)廣播RefreshRemoteApplicationEvent事件

@Endpoint(id?=?"bus-refresh") public?class?RefreshBusEndpoint?extends?AbstractBusEndpoint?{public?void?busRefresh()?{publish(new?RefreshRemoteApplicationEvent(this,?getInstanceId(),?null));} }

BusAutoConfiguration#refreshListener 負(fù)責(zé)接收事件(所有配置bus的節(jié)點(diǎn))

@Bean @ConditionalOnProperty(value?=?"spring.cloud.bus.refresh.enabled",?matchIfMissing?=?true) @ConditionalOnBean(ContextRefresher.class) public?RefreshListener?refreshListener(ContextRefresher?contextRefresher)?{return?new?RefreshListener(contextRefresher); }

RefreshListener#onApplicationEvent 觸發(fā) ContextRefresher

public?void?onApplicationEvent(RefreshRemoteApplicationEvent?event)?{Set<String>?keys?=?contextRefresher.refresh(); }

大部分需要更新的服務(wù)需要打上@RefreshScope, EurekaClient是如何配置更新的

EurekaClientAutoConfiguration#RefreshableEurekaClientConfiguration

@Configuration @ConditionalOnRefreshScope protected?static?class?RefreshableEurekaClientConfiguration{@Bean@RefreshScopepublic?EurekaClient?eurekaClient(...)?{return?new?CloudEurekaClient(manager,?config,?this.optionalArgs,this.context);}@Bean@RefreshScopepublic?ApplicationInfoManager?eurekaApplicationInfoManager(...)?{...return?new?ApplicationInfoManager(config,?instanceInfo);}}

作者:黃大海
https://www.jianshu.com/p/188013dd3d02

總結(jié)

以上是生活随笔為你收集整理的Spring Cloud @RefreshScope 原理是什么?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。