@RefreshScop原理整理

1、@controller 控制器(注入服務)

用於標註控制層,相當於struts中的action層
2、@service 服務(注入dao)

用於標註服務層,主要用來進行業務的邏輯處理
3、@repository(實現dao訪問)

用於標註數據訪問層,也可以說用於標註數據訪問組件,即DAO組件.
4、@component (把普通pojo實例化到spring容器中,相當於配置文件中的

泛指各種組件,就是說當我們的類不屬於各種歸類的時候(不屬於@Controller、@Services等的時候),我們就可以使用@Component來標註這個類。

@ConditionalOnProperty
這個註解能夠控制某個configuration是否生效。具體操作是通過其兩個屬性name以及havingValue來實現的,其中name用來從application.properties中讀取某個屬性值,如果該值爲空,則返回false;如果值不爲空,則將該值與havingValue指定的值進行比較,如果一樣則返回true;否則返回false。如果返回值爲false,則該configuration不生效;爲true則生效。

@RefreshScope

首先看看這個類的註釋

Note that all beans in this scope are only initialized when first accessed, so the scope forces lazy initialization semantics. The implementation involves creating a proxy for every bean in the scope, so there is a flag

If a bean is refreshed then the next time the bean is accessed (i.e. a method is executed) a new instance is created. All lifecycle methods are applied to the bean instances, so any destruction callbacks that were registered in the bean factory are called when it is refreshed, and then the initialization callbacks are invoked as normal when the new instance is created. A new bean instance is created from the original bean definition, so any externalized content (property placeholders or expressions in string literals) is re-evaluated when it is created.

這裏提到了兩個重點:

  1. 所有 @RefreshScope 的 Bean 都是延遲加載的,只有在第一次訪問時纔會初始化
  2. 刷新 Bean 也是同理,下次訪問時會創建一個新的對象

再看一下方法實現:

public void refreshAll() {
  super.destroy();
  this.context.publishEvent(new RefreshScopeRefreshedEvent());
}

這個類中有一個成員變量 cache,用於緩存所有已經生成的 Bean,在調用 get 方法時嘗試從緩存加載,如果沒有的話就生成一個新對象放入緩存,並通過 getBean 初始化其對應的 Bean:

public Object get(String name, ObjectFactory<?> objectFactory) {
  if (this.lifecycle == null) {
    this.lifecycle = new StandardBeanLifecycleDecorator(this.proxyTargetClass);
  }
  BeanLifecycleWrapper value = this.cache.put(name,
      new BeanLifecycleWrapper(name, objectFactory, this.lifecycle));
  try {
    return value.getBean();
  }
  catch (RuntimeException e) {
    this.errors.put(name, e);
    throw e;
  }
}

所以在銷燬時只需要將整個緩存清空,下次獲取對象時自然就可以重新生成新的對象,也就自然綁定了新的屬性:

public void destroy() {
  List<Throwable> errors = new ArrayList<Throwable>();
  Collection<BeanLifecycleWrapper> wrappers = this.cache.clear();
  for (BeanLifecycleWrapper wrapper : wrappers) {
    try {
      wrapper.destroy();
    }
    catch (RuntimeException e) {
      errors.add(e);
    }
  }
  if (!errors.isEmpty()) {
    throw wrapIfNecessary(errors.get(0));
  }
  this.errors.clear();
}

清空緩存後,下次訪問對象時就會重新創建新的對象並放入緩存了。

而在清空緩存後,它還會發出一個 RefreshScopeRefreshedEvent 事件,在某些 Spring Cloud 的組件中會監聽這個事件並作出一些反饋。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章