在前司和目前公司,用的配置中心都是使用的 Apollo,经过了业界验证,比较强大的配置管理系统,特别是在0.10 后开始支持对使用 value 注解的配置值进行自动更新,今天刚好有个同学问到我,就顺便写篇文章记录下,其实也是借助于 spring 强大的 bean 生命周期管理,可以实现BeanPostProcessor接口,使用postProcessBeforeInitialization方法,来对bean 内部的属性和方法进行判断,是否有 value 注解,如果有就是将它注册到一个 map 中,可以看到这个方法com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor#processField
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@Override protectedvoidprocessField(Object bean, String beanName, Field field){ // register @Value on field Value value = field.getAnnotation(Value.class); if (value == null) { return; } Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
@Override publicvoidonChange(ConfigChangeEvent changeEvent){ Set<String> keys = changeEvent.changedKeys(); if (CollectionUtils.isEmpty(keys)) { return; } for (String key : keys) { // 1. check whether the changed key is relevant Collection<SpringValue> targetValues = springValueRegistry.get(beanFactory, key); if (targetValues == null || targetValues.isEmpty()) { continue; }
// 2. check whether the value is really changed or not (since spring property sources have hierarchies) // 这里其实有一点比较绕,是因为 Apollo 里的 namespace 划分,会出现 key 相同,但是 namespace 不同的情况,所以会有个优先级存在,所以需要去校验 environment 里面的是否已经更新,如果未更新则表示不需要更新 if (!shouldTriggerAutoUpdate(changeEvent, key)) { continue; }
// 3. update the value for (SpringValue val : targetValues) { updateSpringValue(val); } } }