问题描述
在使用 Apollo Client 1.6.0 结合 Spring Cloud 的 @RefreshScope 和 @Value 注解时,遇到以下问题:
- 项目启动时第一次属性注入成功
- 后续配置变更时,@Value 属性会刷新,但总是刷新为第一次的旧值,而不是最新的配置值
<dependency><groupId>com.ctrip.framework.apollo</groupId><artifactId>apollo-client</artifactId><version>1.6.0</version>
</dependency>
问题本质深度解构
解决方案
apollo客户端升级到2.1.0
<dependency><groupId>com.ctrip.framework.apollo</groupId><artifactId>apollo-client</artifactId><version>2.1.0</version>
</dependency>
自定监听
import com.ctrip.framework.apollo.model.ConfigChange;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.cloud.context.environment.EnvironmentChangeEvent;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;@Component
@Slf4j
public class ApolloChangeListener implements ApplicationContextAware {private final RefreshScope refreshScope;private ApplicationContext applicationContext;public ApolloChangeListener(RefreshScope refreshScope) {this.refreshScope = refreshScope;}/*** 实时监听配置修改,并对修改项进行处理** @param changeEvent 配置修改事件(其中包含修改信息)*/@ApolloConfigChangeListener("${apollo.bootstrap.namespaces}")private void configChangeHandler(ConfigChangeEvent changeEvent) {log.info("================Apollo auto refresh start===========================");for (String changedKey : changeEvent.changedKeys()) {ConfigChange configChange = changeEvent.getChange(changedKey);String oldValue = configChange.getOldValue();String newValue = configChange.getNewValue();log.info("changedKey:{},oldValue:{}, newValue:{}", changedKey, oldValue, newValue);}refreshContext(changeEvent);log.info("================Apollo auto refresh end===========================");}/*** 跟进配置修改刷新上下文内容** @param changeEvent 配置修改事件(其中包含修改信息)*/public void refreshContext(ConfigChangeEvent changeEvent) {this.applicationContext.publishEvent(new EnvironmentChangeEvent(changeEvent.changedKeys()));refreshScope.refreshAll();}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.applicationContext = applicationContext;}
}