版本
- spring-cloud-nacos-config 2021.0.5.0
 - spring-alibaba-cloud 2021.0.5.0
 - spring-boot 2.7.14
 
配置
application.yml
spring:
  application:
    name: wf-activity-web
  config:
    # ?refreshEnabled=true
    import:
      - optional:nacos:web.yml
nacos配置
比如启动给的时候配置文件是空的,后续在nacos管理后台新增或者修改 x: 100 此时会触发EnvironmentChangeEvent 事件。
x: 100
源码解析
nacos 客户端 在启动时候 启动一个异步任务 定时调度com.alibaba.nacos.client.config.impl.ClientWorker.ConfigRpcTransportClient#startInternal
@Override
public void startInternal() {
    executor.schedule(() -> {
        while (!executor.isShutdown() && !executor.isTerminated()) {
            try {
                listenExecutebell.poll(5L, TimeUnit.SECONDS);
                if (executor.isShutdown() || executor.isTerminated()) {
                    continue;
                }
                // 核心逻辑
                executeConfigListen();
            } catch (Throwable e) {
                LOGGER.error("[ rpc listen execute ] [rpc listen] exception", e);
            }
        }
    }, 0L, TimeUnit.MILLISECONDS);
    
}
如果数据 md5变化就推送事件
com.alibaba.cloud.nacos.refresh.NacosContextRefresher#registerNacosListener
private void registerNacosListener(final String groupKey, final String dataKey) {
   String key = NacosPropertySourceRepository.getMapKey(dataKey, groupKey);
   Listener listener = listenerMap.computeIfAbsent(key,
         lst -> new AbstractSharedListener() {
            @Override
            public void innerReceive(String dataId, String group,
                  String configInfo) {
               refreshCountIncrement();
               nacosRefreshHistory.addRefreshRecord(dataId, group, configInfo);
               // 发送 刷新时间RefreshEvent
               applicationContext.publishEvent(
                     new RefreshEvent(this, null, "Refresh Nacos config"));
               if (log.isDebugEnabled()) {
                  log.debug(String.format(
                        "Refresh Nacos config group=%s,dataId=%s,configInfo=%s",
                        group, dataId, configInfo));
               }
            }
         });
   try {
      configService.addListener(dataKey, groupKey, listener);
      log.info("[Nacos Config] Listening config: dataId={}, group={}", dataKey,
            groupKey);
   }
   catch (NacosException e) {
      log.warn(String.format(
            "register fail for nacos listener ,dataId=[%s],group=[%s]", dataKey,
            groupKey), e);
   }
}
这个时候 发送了一个org.springframework.cloud.endpoint.event.RefreshEvent 事件,这个时候找下消费者
发现 org.springframework.cloud.endpoint.event.RefreshEventListener#onApplicationEvent消费了
@Override
public void onApplicationEvent(ApplicationEvent event) {
   if (event instanceof ApplicationReadyEvent) {
      handle((ApplicationReadyEvent) event);
   }
   else if (event instanceof RefreshEvent) {
      // 刷新事件
      handle((RefreshEvent) event);
   }
}
进入handle事件
public void handle(RefreshEvent event) {
  // this.ready.get() 这个是在 spring ready 的时候发送的事件改成true 默认false,
   if (this.ready.get()) { // don't handle events before app is ready
      log.debug("Event received " + event.getEventDesc());
      Set<String> keys = this.refresh.refresh();
      log.info("Refresh keys changed: " + keys);
   }
}
进入 refresh方法
org.springframework.cloud.context.refresh.ContextRefresher#refresh
public synchronized Set<String> refresh() {
   Set<String> keys = refreshEnvironment();
   this.scope.refreshAll();
   return keys;
}
进入 refreshEnvironment 方法
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());
   updateEnvironment();
   Set<String> keys = changes(before, extract(this.context.getEnvironment().getPropertySources())).keySet();
   //发送 EnvironmentChangeEvent 事件
   this.context.publishEvent(new EnvironmentChangeEvent(this.context, keys));
   return keys;
}
这个时候如果想监听nacos 配置变化 加一个EnvironmentChangeEvent 监听器即可