最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springcloud中的@RefreshScope的實(shí)現(xiàn)

 更新時(shí)間:2024年06月14日 11:19:45   作者:夜空下的星  
@RefreshScope注解是Spring Cloud中的一個(gè)注解,它用來(lái)實(shí)現(xiàn)Bean中屬性的動(dòng)態(tài)刷新,本文就來(lái)介紹一下@RefreshScope注解的使用,感興趣的可以了解一下

一、概述

@RefreshScope注解是Spring Cloud中的一個(gè)注解,它用來(lái)實(shí)現(xiàn)Bean中屬性的動(dòng)態(tài)刷新,這意味著您可以在不停止和重新啟動(dòng)應(yīng)用程序的情況下更改配置,它在微服務(wù)配置中心的場(chǎng)景下經(jīng)常出現(xiàn)。

二、@RefreshScope 實(shí)現(xiàn)動(dòng)態(tài)刷新的原理

1.在應(yīng)用程序中使用 @RefreshScope 注解時(shí),這個(gè)注解內(nèi)部使用了@Scope注解,并將其值設(shè)置為"refresh",定義了一個(gè)新的作用域名為refresh。

2.當(dāng)Spring容器啟動(dòng)時(shí),它會(huì)解析所有的Bean定義,并遇到@RefreshScope注解時(shí),Spring容器會(huì)知道這是一個(gè)特殊的作用域。它使用RefreshScope類(繼承自GenericScope)來(lái)處理這些Bean的生命周期

3.當(dāng)應(yīng)用首次請(qǐng)求一個(gè)被@RefreshScope標(biāo)記的Bean時(shí),Spring容器會(huì)調(diào)用RefreshScope的get方法來(lái)創(chuàng)建Bean的實(shí)例,創(chuàng)建完成后,這個(gè)Bean實(shí)例會(huì)被緩存在RefreshScope中,以便后續(xù)快速獲取。

4.在應(yīng)用運(yùn)行時(shí),如果外部配置源中的配置發(fā)生了更改(比如通過(guò) Nacos Server),客戶端應(yīng)用需要被通知到這些更改。

5.客戶端應(yīng)用可以通過(guò)多種方式觸發(fā)刷新事件,比如通過(guò)Spring Cloud Bus廣播配置更改消息。

6.在刷新事件被觸發(fā)之前或之后,需要更新本地的Environment對(duì)象,以反映外部配置源中的最新配置。

7.當(dāng)Environment對(duì)象更新后,RefreshScope會(huì)遍歷其緩存中的所有Bean,對(duì)它們進(jìn)行銷毀和重新創(chuàng)建。這是通過(guò)調(diào)用GenericScope提供的生命周期管理方法來(lái)完成的。舊的Bean實(shí)例被銷毀,新的Bean實(shí)例根據(jù)最新的配置(從更新后的Environment中獲?。┍粍?chuàng)建并緩存。

8.經(jīng)過(guò)刷新操作后,應(yīng)用中的Bean將使用新的配置。由于@RefreshScope僅影響標(biāo)記了此注解的Bean,因此未標(biāo)記的Bean不會(huì)受到影響。

三、如何在 Spring Boot中使用 @RefreshScope?

1.添加 相關(guān)的Maven 依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-config</artifactId>
</dependency>

2.創(chuàng)建一個(gè)需要刷新的bean對(duì)象。

@Component
@RefreshScope
public class RefleshBean {
    @Value("${config.property}")
    private String configProperty;

    public String getConfigProperty() {
        return configProperty;
    }
}

上面我們使用 @RefreshScope 注解標(biāo)記 RefleshBean 類。這意味著當(dāng) config.property屬性更改時(shí),Spring Boot 將重新加載這個(gè) bean。

四、@RefreshScope 源碼解析

1.首先看下@RefreshScope 注解

package org.springframework.cloud.context.config.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;

/**
 * Convenience annotation to put a <code>@Bean</code> definition in
 * {@link org.springframework.cloud.context.scope.refresh.RefreshScope refresh scope}.
 * Beans annotated this way can be refreshed at runtime and any components that are using
 * them will get a new instance on the next method call, fully initialized and injected
 * with all dependencies.
 *
 * @author Dave Syer
 *
 */
@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;

}

可以看出其是一個(gè)復(fù)合注解,被標(biāo)注了 @Scope(“refresh”),@RefreshScope 是scopeName="refresh"的 @Scope。

2.RefreshScope的實(shí)現(xiàn)

2.1 RefreshScope 繼承GenericScope,其父類GenericScope的get方法實(shí)現(xiàn)獲取Bean,注意創(chuàng)建Bean還是由IOC#createBean實(shí)現(xiàn)。
GenericScope類

    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
      //通過(guò)cache把bean緩存下來(lái),如果不存在則創(chuàng)建
        BeanLifecycleWrapper value = this.cache.put(name, new BeanLifecycleWrapper(name, objectFactory));
        this.locks.putIfAbsent(name, new ReentrantReadWriteLock());
        try {
            return value.getBean();
        }
        catch (RuntimeException e) {
            this.errors.put(name, e);
            throw e;
        }
    }

GenericScope 里面的 get 方法負(fù)責(zé)對(duì)象的創(chuàng)建和緩存。

上面代碼中看似每次都新創(chuàng)建一個(gè)對(duì)象放入緩存中,實(shí)際上是創(chuàng)建了一個(gè)objectFactory的封裝對(duì)象,并沒(méi)有真正創(chuàng)建對(duì)象。而cache的put邏輯最終實(shí)現(xiàn)為map的putIfAbsent,即緩存中已存在key則返回原來(lái)的value。實(shí)現(xiàn)在 StandardScopeCache類

public class StandardScopeCache implements ScopeCache {
 
	private final ConcurrentMap<String, Object> cache = new ConcurrentHashMap<String, Object>();	
	// ...
	public Object put(String name, Object value) {
		Object result = this.cache.putIfAbsent(name, value);
		if (result != null) {
			return result;
		}
		return value;
	}
}

2.2 RefreshScope緩存清理。

配置更新后需要清除RefreshScope中的緩存,ContextRefresher負(fù)責(zé)完成這一任務(wù)。它由RefreshAutoConfiguration引入,創(chuàng)建的時(shí)候會(huì)自動(dòng)注入RefreshScope和context。

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RefreshScope.class)
@ConditionalOnProperty(name = RefreshAutoConfiguration.REFRESH_SCOPE_ENABLED,
		matchIfMissing = true)
@AutoConfigureBefore(HibernateJpaAutoConfiguration.class)
public class RefreshAutoConfiguration {	
 
	@Bean
	@ConditionalOnMissingBean(RefreshScope.class)
	public static RefreshScope refreshScope() {
		return new RefreshScope();
	}
	
	@Bean
	@ConditionalOnMissingBean
	public ContextRefresher contextRefresher(ConfigurableApplicationContext context,
			RefreshScope scope) {
		return new ContextRefresher(context, scope);
	}
    // ...
}

2.3 ContextRefresher的refresh方法就是清理RefreshScope緩存的入口。

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

其中refreshAll最終會(huì)落實(shí)到GenericScope的destroy方法,其中清理了所有的緩存。

	@Override
	public void destroy() {
		List<Throwable> errors = new ArrayList<Throwable>();
		Collection<BeanLifecycleWrapper> wrappers = this.cache.clear();
		for (BeanLifecycleWrapper wrapper : wrappers) {
			try {
				Lock lock = this.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();
	}

2.4 重新加載

想實(shí)現(xiàn)動(dòng)態(tài)刷新配置,光清除RefreshScope的緩存還不夠,還要具備重新加載配置到context中的能力,這一任務(wù)也是ContextRefresher完成的。
實(shí)際上就是在refresh方法中清理RefreshScope緩存之前,即refreshEnvironment方法中完成了配置的重新加載。

public synchronized Set<String> refreshEnvironment() {
	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(this.context, keys));
	return keys;
}

總結(jié):

帶有@RefreshScope注解的Bean在配置發(fā)生變化時(shí)進(jìn)行刷新,可以確保配置的動(dòng)態(tài)生效。但是,使用@RefreshScope并不是必須的。如果你希望配置的變化立即生效,并且不想手動(dòng)刷新Bean,可以直接使用@ConfigurationProperties注解來(lái)獲取配置項(xiàng)的值,這樣配置的變化會(huì)立即反映在應(yīng)用程序中。使用@RefreshScope的目的是延遲Bean的刷新,只在需要的時(shí)候才進(jìn)行刷新。這對(duì)于一些開(kāi)銷較大的Bean或需要?jiǎng)討B(tài)加載配置的場(chǎng)景比較合適。

到此這篇關(guān)于Springcloud中的@RefreshScope的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Springcloud @RefreshScope內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot?AspectJ切面配合自定義注解實(shí)現(xiàn)權(quán)限校驗(yàn)的示例詳解

    SpringBoot?AspectJ切面配合自定義注解實(shí)現(xiàn)權(quán)限校驗(yàn)的示例詳解

    本文章介紹了如何通過(guò)創(chuàng)建自定義的權(quán)限校驗(yàn)注解,配合AspectJ切面攔截注解實(shí)現(xiàn)權(quán)限校驗(yàn),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2025-09-09
  • java圖搜索算法之DFS與BFS詳解

    java圖搜索算法之DFS與BFS詳解

    這篇文章主要為大家介紹了java數(shù)據(jù)結(jié)構(gòu)中可以秒殺一切圖算法的DFS與BFS作用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • Java 使用Calendar計(jì)算時(shí)間的示例代碼

    Java 使用Calendar計(jì)算時(shí)間的示例代碼

    這篇文章主要介紹了Java 使用Calendar計(jì)算時(shí)間的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • JAVA中Collections工具類sort()排序方法

    JAVA中Collections工具類sort()排序方法

    這篇文章主要介紹了JAVA中Collections工具類sort()排序方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下。
    2016-11-11
  • Spring組件開(kāi)發(fā)模式支持SPEL表達(dá)式

    Spring組件開(kāi)發(fā)模式支持SPEL表達(dá)式

    今天小編就為大家分享一篇關(guān)于Spring組件開(kāi)發(fā)模式支持SPEL表達(dá)式,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-12-12
  • Java Bigdecimal使用原理詳解

    Java Bigdecimal使用原理詳解

    這篇文章主要介紹了Java Bigdecimal使用原理詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-03-03
  • SpringBoot項(xiàng)目使用@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù)的方法

    SpringBoot項(xiàng)目使用@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù)的方法

    文章介紹了在SpringBoot項(xiàng)目中使用@Scheduled注解實(shí)現(xiàn)定時(shí)任務(wù)的三種方式:基于注解、基于接口和基于注解設(shè)定多線程定時(shí)任務(wù),詳細(xì)講解了@Scheduled注解的使用方法、各個(gè)參數(shù)以及如何配置動(dòng)態(tài)定時(shí)任務(wù)和多線程定時(shí)任務(wù),感興趣的朋友一起看看吧
    2025-03-03
  • Nacos源碼之注冊(cè)中心的實(shí)現(xiàn)詳解

    Nacos源碼之注冊(cè)中心的實(shí)現(xiàn)詳解

    這篇文章主要為大家介紹了Nacos源碼之注冊(cè)中心的實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • Spring Boot定時(shí)任務(wù)的使用方法

    Spring Boot定時(shí)任務(wù)的使用方法

    這篇文章為大家詳細(xì)主要介紹了Spring Boot定時(shí)任務(wù)的使用方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • 關(guān)于Java for循環(huán)的正確用法介紹

    關(guān)于Java for循環(huán)的正確用法介紹

    Java里的循環(huán)結(jié)構(gòu)我們可以通過(guò)while、do-while、for、foreach等方式實(shí)現(xiàn)循環(huán),這篇文章會(huì)把這幾種循環(huán)方式都給大家講解到,但本文主要介紹for循環(huán)的使用,感興趣的同學(xué)可以參考閱讀
    2023-05-05

最新評(píng)論

和平县| 邳州市| 云安县| 隆安县| 临夏市| 丹凤县| 潞西市| 区。| 天峨县| 元谋县| 广宁县| 巴彦县| 黔江区| 双城市| 寿阳县| 潼关县| 贺州市| 鄂托克旗| 正安县| 陕西省| 崇明县| 葫芦岛市| 江门市| 民权县| 兖州市| 镇康县| 英山县| 恩平市| 沁源县| 板桥市| 浦江县| 德安县| 洛川县| 宜良县| 彝良县| 伊金霍洛旗| 宜春市| 浦县| 香河县| 东辽县| 龙胜|