Apollo 本身是可以基于事件监听实时推送(Http长连接)变更(AutoUpdateConfigChangeListener),也会定时拉取(fallback)最新配置。
如果说我们还需要在配置更新时,做一些其他的业务,比如:对配置做了一些自己的数据缓存,或者业务变更等,那么我们需要控制监听器,apollo提供了这样的策略。可手动配置一个监听器在容器中。
有两种方式如下:
一、手动初始化监听器并配置到Config上下文中
@SpringBootApplication
@EnableApolloConfig
public class ConfigApplication {
public static void main(String[] args) {
SpringApplication.run(ConfigApplication.class, args);
// 手动配置 apolloConfigListener,添加配置改动监听
ConfigChangeListener configChangeListener = new ConfigChangeListener() {
@Override
public void onChange(ConfigChangeEvent configChangeEvent) {
ConfigChange change;
for (String key : configChangeEvent.changedKeys()) {
change = configChangeEvent.getChange(key);
// 打印改动的配置信息
System.out.println(
String.format(String.format("Change - key: %s, oldValue: %s, newValue: %s, changeType: %s",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType())));
}
}
};
// 也可@ApolloConfig注入
ConfigService.getAppConfig().addChangeListener(configChangeListener);
}
}
这里我将实现过程写在启动类中,手动实现一个匿名类ConfigListener然后配置到Config中,ConfigService.getAppConfig()是Apollo提供的静态方法,用于获取当前容器默认的ApolloConfig,默认是指的namespace是默认“application”,也就是说获取的是“application”的config,上面这样操作,监听的是application。
可以看到getAppConfig的实现:
如果想要获得其他namespace的话,getConfig(“namespace”),形参为你所指定的namespace,然后addChangeListener(),即可以监听指定namespace下的配置变换。可以理解Config是namespace维度下的,每个namespace(同一应用,同一集群,同一环境)下都一个Config。
支持监听namespace下指定配置key,提供三个重载方法,默认无参的,则监听namespace下所有key,下图中第一个方法监听指定key,第二个监听指定以其开头的key。
使用如下:
config.addChangeListener(configChangeListener, new HashSet(){{
add("nwpu.name");
}}, new HashSet(){{
add("nwpu");
}});
二、用@ApolloConfigChangeListener注解标记,自动注册ConfigChangeListener
@Configuration
public class ApolloConfig {
@Autowired
private RefreshScope refreshScope;
@ApolloConfigChangeListener(value = {"application", "datasource"})
private void onChangeToAll(ConfigChangeEvent changeEvent) {
ConfigChange change;
for (String key : changeEvent.changedKeys()) {
// 如果@ConfigurationProperties配置发生变化,则需要手动刷新
// if (key.substring(0, 5).equals("nwpu")) {
// refreshScope.refresh("nwpuDTO");
// }
change = changeEvent.getChange(key);
// 打印出新增或者变化的配置 相关信息
System.out.println(String.format("Change - key: %s, oldValue: %s, newValue: %s, changeType: %s",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType()));
}
}
@ApolloConfigChangeListener(value = "application", interestedKeyPrefixes = "nwpu")
private void onChangeToApplication(ConfigChangeEvent changeEvent) {
ConfigChange change;
for (String key : changeEvent.changedKeys()) {
// 如果@ConfigurationProperties配置发生变化,则需要手动刷新
refreshScope.refresh("nwpuDTO");
change = changeEvent.getChange(key);
// 打印出新增或者变化的配置 相关信息
System.out.println(String.format("Change - key: %s, oldValue: %s, newValue: %s, changeType: %s",
change.getPropertyName(), change.getOldValue(), change.getNewValue(),
change.getChangeType()));
}
}
}
这种方式应该是用注解标记,然后aop切面标记的方法,然后注入Config中。标记方法的实现是配置变化后的处理业务。
分析上面的代码,我们总共对两个config操作,一个application config,一个datasource config,然后分别注册监听器,注意application注册两次监听器,第一次没有指定key,第二次指定了key前缀,测试发现均可用,也就是说config允许同时注册多个监听器。