首頁 > 軟體

Spring Cloud動態設定重新整理RefreshScope使用範例詳解

2022-08-29 14:01:21

引言

用過Spring Cloud的同學都知道在使用動態設定重新整理的我們要設定一個 @RefreshScope,在類上才可以實現物件屬性的的動態更新。

@RefreshScope 能實現動態重新整理全仰仗著 @Scope這個註解。

一、瞭解@RefreshScope,先要了解@Scope

1、RefreshScope繼承於GenericScope, 而GenericScope實現了Scope介面

2、@Scope代表了Bean的作用域,我們來看下其中的屬性:

@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是單例的。(預設)
     *  prototype    表示該bean是多例的,即每次使用該bean時都會新建一個物件。
     *  request        在一次http請求中,一個bean對應一個範例。
     *  session        在一個httpSession中,一個bean對應一個範例
         */
        @AliasFor("value")
        String scopeName() default "";
        /**
    *   DEFAULT			不使用代理。(預設)
        * 	NO				不使用代理,等價於DEFAULT。
        * 	INTERFACES		使用基於介面的代理(jdk dynamic proxy)。
        * 	TARGET_CLASS	使用基於類的代理(cglib)。
    */
        ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
}

3、@RefreshScope等同於scopeName="refresh"的@Scope:

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

二、RefreshScope 的實現原理

1、@RefreshScope的實現

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

可以看出它使用的就是 @Scope,其內部就一個屬性預設ScopedProxyMode.TARGET_CLASS。那我們來看下Scope這個介面:

public interface Scope {
        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)這個方法幫助我們來建立一個新的bean,也就是說 @RefreshScope在呼叫重新整理的時候會使用get方法來給我們建立新的物件,這樣就可以通過spring的裝配機制將屬性重新注入了,也就實現了所謂的動態重新整理。

2、GenericScope幫我們實現了Scope最重要的 get(String name, ObjectFactory<?> objectFactory) 方法,在GenericScope 裡面 包裝了一個內部類 BeanLifecycleWrapperCache 來對加了 @RefreshScope 從而建立的物件進行快取,使其在不重新整理時獲取的都是同一個物件。

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

三、使用——@RefreshScope 使用流程

1、需要動態重新整理的類標註@RefreshScope註解

2、@RefreshScope 註解標註了@Scope 註解,並預設了ScopedProxyMode.TARGET_CLASS; 屬性,此屬性的功能就是在建立一個代理,在每次呼叫的時候都用它來呼叫GenericScope get 方法來獲取物件

3、如屬性發生變更會呼叫 ContextRefresher refresh() -》RefreshScope refreshAll() 進行快取清理方法呼叫,並行送重新整理事件通知 -》 GenericScope 真正的 清理方法destroy() 實現清除快取

4、在下一次使用物件的時候,會呼叫GenericScope get(String name, ObjectFactory<?> objectFactory) 方法建立一個新的物件,並存入快取中,此時新物件因為Spring 的裝配機制就是新的屬性了。

以上就是Spring Cloud動態設定重新整理RefreshScope使用範例詳解的詳細內容,更多關於RefreshScope設定重新整理的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com