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<String>(){{
add("nwpu.name");
}}, new HashSet<String>(){{
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允許同時註冊多個監聽器。