spring cloud的RefreshScope注解进行热部署

需要热加载的bean需要加上@RefreshScope注解,当配置发生变更的时候可以在不重启应用的前提下完成bean中相关属性的刷新。

 

经由@RefreshScope修饰的bean将会被RefreshScope代理,其关于bean生命周期的相关方法也在此定义。

@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());
}

RefreshScope代理的bean强制为懒加载,只有在第一次使用的时候才会生成实例,当其需要刷新配置的时候直接调用destory()方法销毁当前bean,这样在刷新配置后在需要生成的bean已经是根据新的配置信息生成,完成bean的热加载。

 

在spring cloud中,当配置发生变更,将会通过soring cloud bus发送RefreshRemoteApplicationEvent事件给相关应用,在RefreshListener中,开始对于配置的刷新。

public void onApplicationEvent(RefreshRemoteApplicationEvent event) {
    Set<String> keys = this.contextRefresher.refresh();
    log.info("Received remote refresh request. Keys refreshed " + keys);
}

最终刷新将在refreshContext的refresh()方法中进行。

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

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(context, keys));
   return keys;
}

在这里的刷新一共被分为两个步骤,首先获取新的配置值与老的配置值进行比对并更新,之后再销毁所有被RefreshScope代理的bean。

 

在第一步,重点在于获取新的配置值,具体实现在addConfigFilesToEnvironment()方法中。

StandardEnvironment environment = copyEnvironment(
      this.context.getEnvironment());
SpringApplicationBuilder builder = new SpringApplicationBuilder(Empty.class)
      .bannerMode(Mode.OFF).web(WebApplicationType.NONE)
      .environment(environment);
// Just the listeners that affect the environment (e.g. excluding logging
// listener because it has side effects)
builder.application()
      .setListeners(Arrays.asList(new BootstrapApplicationListener(),
            new ConfigFileApplicationListener()));
capture = builder.run();
if (environment.getPropertySources().contains(REFRESH_ARGS_PROPERTY_SOURCE)) {
   environment.getPropertySources().remove(REFRESH_ARGS_PROPERTY_SOURCE);
}
MutablePropertySources target = this.context.getEnvironment()
      .getPropertySources();
String targetName = null;
for (PropertySource<?> source : environment.getPropertySources()) {
   String name = source.getName();
   if (target.contains(name)) {
      targetName = name;
   }
   if (!this.standardSources.contains(name)) {
      if (target.contains(name)) {
         target.replace(name, source);
      }
      else {
         if (targetName != null) {
            target.addAfter(targetName, source);
         }
         else {
            // targetName was null so we are at the start of the list
            target.addFirst(source);
            targetName = name;
         }
      }
   }
}

此处将会以当前的应用的envionment深克隆一份,并根据复制出来的为依据重新建立一个spring boot application,在新的应用建立过程中,将会重新获取配置值,此处也将获取新的配置值,在新的副本应用建立完毕之后,将会返回其配置值准备与旧的配置值进行比对并更新。

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值