项目中在使用apollo作为配置中心。现在有需求:配置项发生变化,对应的配置需动态刷新。
背景
配置类:
@Component
@Data
@RefreshScope
@ConfigurationProperties(prefix = "home.setting.dict")
public class HomeSettingProperties {
@ApiModelProperty("金刚区")
private String kingKongSetting;
//...
}
主要是对 HomeSettingProperties 中的属性 kingKongSetting 进行动态更新
实现方式
在项目使用的是结合 RefreshScope 的方式实现动态刷新,需要注意的是,在配置类中需要配置注解 @RefreshScope,@ConfigurationProperties
监听类:
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.factory.annotation.Autowired;
import org.springframework.cloud.context.scope.refresh.RefreshScope;
import org.springframework.context.annotation.Configuration;
@Configuration
@Slf4j
public class ApolloConfig {
@Autowired
private RefreshScope refreshScope;
@ApolloConfigChangeListener
public void changeHandler(ConfigChangeEvent changeEvent) {
for (String key : changeEvent.changedKeys()) {
ConfigChange change = changeEvent.getChange(key);
log.info("配置发生变化 {}", change.toString());
refresh(key);
}
}
/**
* 刷新配置
*
* @param key
*/
public void refresh(String key) {
if (key.contains("home.setting")) {
log.info("before refresh:{}",homeSettingProperties);
refreshScope.refresh("homeSettingProperties");
log.info("after refresh:{}",homeSettingProperties);
}
}
}
修改下配置,可以看到配置生效了
'[2022-02-09 16:53:56.860] 配置发生变化 ConfigChange{namespace='application', propertyName='home.setting.kingKongSetting', oldValue='123', newValue='456', changeType=MODIFIED}
[2022-02-09 16:53:56.861] [Apollo-Config-1] [INFO ] before refresh: kingKongSetting=123
[2022-02-09 16:53:56.862] [Apollo-Config-1] [INFO ] after refresh:kingKongSetting=456
原理
被 @RefreshScope 标注的类的scope为 refresh。
当调用 refreshScope.refresh 方法的时候,首先销毁 scope 为 refresh 的bean实例,然后发出 RefreshScopeRefreshedEvent 事件,通知spring容器重新创建bean,获取新的配置。具体可以参考这个文章