@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 的组件中会监听这个事件并作出一些反馈。

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