问题:
apollo动态刷新,应用在@value
这种注入方式的属性没有问题,但是如果使用@ConfigurationProperties
注解的bean,动态刷新就不好使了,会注入不到的。
Apollo动态刷新官网介绍
需要注意的是,@ConfigurationProperties
如果需要在Apollo配置变化时自动更新注入的值,
需要配合使用EnvironmentChangeEvent
或RefreshScope
。
相关代码实现,可以参考apollo-use-cases项目中的ZuulPropertiesRefresher.java和apollo-demo项目中的SampleRedisConfig.java以及SpringBootApolloRefreshConfig.java
例如注入一个 map 对象: {"Sea":"v1","Sea1" :"v2"} ,希望动态修改
applocation.yml:
#my.user.config
sea.xx.user_config[Sea]=v1 sea.xx.user_config[dmisy] = {"name":"dmisy","secret":"d6f57e00f2","type":"a"} sea.xx.user_config[jerry] = {"name":"jerry","secret":"e73d18909cdaa","type":"b"}
@Service @ConfigurationProperties(prefix = "sea.xx") public class UserServiceImpl implements UserService { public Map<String,String> user_config =new HashMap<String,String>() ; public void setUser_config(Map<String, String> user_config) { this.user_config = user_config; }
现在如果想修改,或添加配置, 服务需要重启财生效
解决方案:
step1. 添加 @RefreshScope
@Service @RefreshScope @ConfigurationProperties(prefix = "sea.xx") public class UserServiceImpl implements UserService { public Map<String,String> user_config =new HashMap<String,String>() ;
step2: add ApolloChangeListener
/*************************** *<pre> * @Author : Sea * @Mail : lshan523@16.com * @Date : 2023/4/27 10:29 * 用于解决 被@ConfigurationProperties修饰的类, 修改apollo配置后不会动态修改的问题 * 使用方式: * 被@ConfigurationProperties修饰的类 需要加上:@Component @RefreshScope 注解 *</pre> ***************************/ @Slf4j @Configuration public class ApolloChangeListener { @Autowired private RefreshScope refreshScope; /** * 使用说明 * @ApolloConfigChangeListener(value = {"application.yml","user"}, interestedKeyPrefixes = {"spring.","my.config"}): * 当在Apollo配置中心,修改application.yml或user.properties下的,前缀为spring.或my.config的属性时,触发刷新方法执行。 * @param changeEvent */ @ApolloConfigChangeListener(value = "application.yml", interestedKeyPrefixes = "sea.xx.") public void refresh(ConfigChangeEvent changeEvent) { log.info("Changes for namespace " + changeEvent.getNamespace()); for(String key : changeEvent.changedKeys()) { ConfigChange change = changeEvent.getChange(key); log.info(String.format("Found change - key: %s, oldValue: %s, newValue: %s, changeType: %s", change.getPropertyName(), change.getOldValue(), change.getNewValue(), change.getChangeType())); } // 刷新的bean 所有 带@RefreshScope 的类 refreshScope.refreshAll(); // 刷新指定的bean // refreshScope.refresh("myConfigProperties"); } }
这样就可以动态修改这个map了
!!! 对于 mysql redis mongo 等DB, 依然需要重启, 或者添加 重新建立连接的逻辑,财真的生效