真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

@RefreshScope刷新機(jī)制是什么

這篇文章主要介紹“@RefreshScope刷新機(jī)制是什么”,在日常操作中,相信很多人在@RefreshScope刷新機(jī)制是什么問(wèn)題上存在疑惑,小編查閱了各式資料,整理出簡(jiǎn)單好用的操作方法,希望對(duì)大家解答”@RefreshScope刷新機(jī)制是什么”的疑惑有所幫助!接下來(lái),請(qǐng)跟著小編一起來(lái)學(xué)習(xí)吧!

在惠濟(jì)等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專(zhuān)注、極致的服務(wù)理念,為客戶提供網(wǎng)站設(shè)計(jì)制作、網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需策劃,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),成都全網(wǎng)營(yíng)銷(xiāo),成都外貿(mào)網(wǎng)站建設(shè),惠濟(jì)網(wǎng)站建設(shè)費(fèi)用合理。

一、前言

用過(guò)Spring Cloud的同學(xué)都知道在使用動(dòng)態(tài)配置刷新的我們要配置一個(gè)@RefreshScope 在類(lèi)上才可以實(shí)現(xiàn)對(duì)象屬性的的動(dòng)態(tài)更新,本著知其所以然的態(tài)度,晚上沒(méi)事兒又把這個(gè)點(diǎn)回顧了一下,下面就來(lái)簡(jiǎn)單的說(shuō)下自己的理解。

總覽下,實(shí)現(xiàn)@RefreshScope 動(dòng)態(tài)刷新的就需要以下幾個(gè):

  • @ Scope   

  • @RefreshScope

  • RefreshScope       

  • GenericScope   

  • Scope

  • ContextRefresher

二、@Scope

一句話,@RefreshScope 能實(shí)現(xiàn)動(dòng)態(tài)刷新全仰仗著@Scope 這個(gè)注解,這是為什么呢?

@Scope 代表了Bean的作用域,我們來(lái)看下其中的屬性:

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scope {

	/**
	 * Alias for {@link #scopeName}.
	 * @see #scopeName
	 */
	@AliasFor("scopeName")
	String value() default "";

	/**
	 *  singleton  表示該bean是單例的。(默認(rèn))
     *  prototype    表示該bean是多例的,即每次使用該bean時(shí)都會(huì)新建一個(gè)對(duì)象。
     *  request        在一次http請(qǐng)求中,一個(gè)bean對(duì)應(yīng)一個(gè)實(shí)例。
     *  session        在一個(gè)httpSession中,一個(gè)bean對(duì)應(yīng)一個(gè)實(shí)例
	 */
	@AliasFor("value")
	String scopeName() default "";

	/**
    *   DEFAULT			不使用代理。(默認(rèn))
	* 	NO				不使用代理,等價(jià)于DEFAULT。
	* 	INTERFACES		使用基于接口的代理(jdk dynamic proxy)。
	* 	TARGET_CLASS	使用基于類(lèi)的代理(cglib)。
    */
	ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;

}

通過(guò)代碼我們可以清晰的看到兩個(gè)主要屬性value 和 proxyMode,value就不多說(shuō)了,大家平時(shí)經(jīng)常用看看注解就可以。proxyMode 這個(gè)就有意思了,而這個(gè)就是@RefreshScope  實(shí)現(xiàn)的本質(zhì)了。

我們需要關(guān)心的就是ScopedProxyMode.TARGET_CLASS 這個(gè)屬性,當(dāng)ScopedProxyMode 為T(mén)ARGET_CLASS 的時(shí)候會(huì)給當(dāng)前創(chuàng)建的bean 生成一個(gè)代理對(duì)象,會(huì)通過(guò)代理對(duì)象來(lái)訪問(wèn),每次訪問(wèn)都會(huì)創(chuàng)建一個(gè)新的對(duì)象。

理解起來(lái)可能比較晦澀,那先來(lái)看下實(shí)現(xiàn)再回頭來(lái)看這句話。

三、RefreshScope 的實(shí)現(xiàn)原理

  1. 先來(lái)看下@RefreshScope

@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Scope("refresh")
@Documented
public @interface RefreshScope {
	/**
	 * @see Scope#proxyMode()
	 */
	ScopedProxyMode proxyMode() default ScopedProxyMode.TARGET_CLASS;

}

2. 可以看出,它使用就是 @Scope ,其內(nèi)部就一個(gè)屬性默認(rèn) ScopedProxyMode.TARGET_CLASS。知道了是通過(guò)Spring Scope 來(lái)實(shí)現(xiàn)的那就簡(jiǎn)單了,我們來(lái)看下Scope 這個(gè)接口     

public interface Scope {

	/**
	 * Return the object with the given name from the underlying scope,
	 * {@link org.springframework.beans.factory.ObjectFactory#getObject() creating it}
	 * if not found in the underlying storage mechanism.
	 * 

This is the central operation of a Scope, and the only operation  * that is absolutely required.  * @param name the name of the object to retrieve  * @param objectFactory the {@link ObjectFactory} to use to create the scoped  * object if it is not present in the underlying storage mechanism  * @return the desired object (never {@code null})  * @throws IllegalStateException if the underlying scope is not currently active  */ Object get(String name, ObjectFactory objectFactory);   @Nullable Object remove(String name);   void registerDestructionCallback(String name, Runnable callback);   @Nullable Object resolveContextualObject(String key);   @Nullable String getConversationId(); }

看下接口,我們只看Object get(String name, ObjectFactory objectFactory); 這個(gè)方法幫助我們來(lái)創(chuàng)建一個(gè)新的bean ,也就是說(shuō),@RefreshScope 在調(diào)用 刷新的時(shí)候會(huì)使用此方法來(lái)給我們創(chuàng)建新的對(duì)象,這樣就可以通過(guò)spring 的裝配機(jī)制將屬性重新注入了,也就實(shí)現(xiàn)了所謂的動(dòng)態(tài)刷新。

  1. 那它究竟是怎么處理老的對(duì)象,又怎么除法創(chuàng)建新的對(duì)象呢?

在開(kāi)頭我提過(guò)幾個(gè)重要的類(lèi),而其中 RefreshScope extends GenericScope, GenericScope  implements Scope。

所以通過(guò)查看代碼,是GenericScope 實(shí)現(xiàn)了 Scope 最重要的  get(String name, ObjectFactory objectFactory) 方法,在GenericScope 里面 包裝了一個(gè)內(nèi)部類(lèi) BeanLifecycleWrapperCache 來(lái)對(duì)加了 @RefreshScope 從而創(chuàng)建的對(duì)象進(jìn)行緩存,使其在不刷新時(shí)獲取的都是同一個(gè)對(duì)象。(這里你可以把 BeanLifecycleWrapperCache 想象成為一個(gè)大Map 緩存了所有@RefreshScope  標(biāo)注的對(duì)象)

知道了對(duì)象是緩存的,所以在進(jìn)行動(dòng)態(tài)刷新的時(shí)候,只需要清除緩存,重新創(chuàng)建就好了。 來(lái)看代碼,眼見(jiàn)為實(shí),只留下關(guān)鍵方法:

// ContextRefresher 外面使用它來(lái)進(jìn)行方法調(diào)用 ============================== 我是分割線

	public synchronized Set refresh() {
		Set keys = refreshEnvironment();
		this.scope.refreshAll();
		return keys;
	}

// RefreshScope 內(nèi)部代碼  ============================== 我是分割線

	@ManagedOperation(description = "Dispose of the current instance of all beans in this scope and force a refresh on next method execution.")
	public void refreshAll() {
		super.destroy();
		this.context.publishEvent(new RefreshScopeRefreshedEvent());
	}


// GenericScope 里的方法 ============================== 我是分割線

	//進(jìn)行對(duì)象獲取,如果沒(méi)有就創(chuàng)建并放入緩存
	@Override
	public Object get(String name, ObjectFactory objectFactory) {
		BeanLifecycleWrapper value = this.cache.put(name,
				new BeanLifecycleWrapper(name, objectFactory));
		locks.putIfAbsent(name, new ReentrantReadWriteLock());
		try {
			return value.getBean();
		}
		catch (RuntimeException e) {
			this.errors.put(name, e);
			throw e;
		}
	}
	//進(jìn)行緩存的數(shù)據(jù)清理
	@Override
	public void destroy() {
		List errors = new ArrayList();
		Collection wrappers = this.cache.clear();
		for (BeanLifecycleWrapper wrapper : wrappers) {
			try {
				Lock lock = locks.get(wrapper.getName()).writeLock();
				lock.lock();
				try {
					wrapper.destroy();
				}
				finally {
					lock.unlock();
				}
			}
			catch (RuntimeException e) {
				errors.add(e);
			}
		}
		if (!errors.isEmpty()) {
			throw wrapIfNecessary(errors.get(0));
		}
		this.errors.clear();
	}

通過(guò)觀看源代碼我們得知,我們截取了三個(gè)片段所得之,ContextRefresher 就是外層調(diào)用方法用的,GenericScope 里面的 get 方法負(fù)責(zé)對(duì)象的創(chuàng)建和緩存,destroy 方法負(fù)責(zé)再刷新時(shí)緩存的清理工作。

到此,關(guān)于“@RefreshScope刷新機(jī)制是什么”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識(shí),請(qǐng)繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會(huì)繼續(xù)努力為大家?guī)?lái)更多實(shí)用的文章!


本文標(biāo)題:@RefreshScope刷新機(jī)制是什么
網(wǎng)站地址:http://weahome.cn/article/ggpjes.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部