apollo 动态监听配置文件
Posted bohu83
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了apollo 动态监听配置文件相关的知识,希望对你有一定的参考价值。
1 默认的@Value 就能自动监听更新。底层也是依赖于ConfigChangeListener。
缺点是不够灵活,如果你配置了一堆数据,监听到更新做业务处理。可以使用@ApolloConfigChangeListener。
******************
有个隐藏的坑,发现每次更新依靠@Value 不一定获取到最新的值。重复修改几次,有事可以有事不行,靠changeEvent 获取的新旧值更稳妥些。
****************
底层实现:
public class ApolloAnnotationProcessor extends ApolloProcessor {
public ApolloAnnotationProcessor() {
}
protected void processField(Object bean, String beanName, Field field) {
ApolloConfig annotation = (ApolloConfig)AnnotationUtils.getAnnotation(field, ApolloConfig.class);
if (annotation != null) {
Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()), "Invalid type: %s for field: %s, should be Config", new Object[]{field.getType(), field});
String namespace = annotation.value();
Config config = ConfigService.getConfig(namespace);
ReflectionUtils.makeAccessible(field);
ReflectionUtils.setField(field, bean, config);
}
}
protected void processMethod(final Object bean, String beanName, final Method method) {
ApolloConfigChangeListener annotation = (ApolloConfigChangeListener)AnnotationUtils.findAnnotation(method, ApolloConfigChangeListener.class);
if (annotation != null) {
Class<?>[] parameterTypes = method.getParameterTypes();
Preconditions.checkArgument(parameterTypes.length == 1, "Invalid number of parameters: %s for method: %s, should be 1", new Object[]{parameterTypes.length, method});
Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]), "Invalid parameter type: %s for method: %s, should be ConfigChangeEvent", new Object[]{parameterTypes[0], method});
ReflectionUtils.makeAccessible(method);
String[] namespaces = annotation.value();
String[] annotatedInterestedKeys = annotation.interestedKeys();
String[] annotatedInterestedKeyPrefixes = annotation.interestedKeyPrefixes();
ConfigChangeListener configChangeListener = new ConfigChangeListener() {
public void onChange(ConfigChangeEvent changeEvent) {
ReflectionUtils.invokeMethod(method, bean, new Object[]{changeEvent});
}
};
Set<String> interestedKeys = annotatedInterestedKeys.length > 0 ? Sets.newHashSet(annotatedInterestedKeys) : null;
Set<String> interestedKeyPrefixes = annotatedInterestedKeyPrefixes.length > 0 ? Sets.newHashSet(annotatedInterestedKeyPrefixes) : null;
String[] var12 = namespaces;
int var13 = namespaces.length;
for(int var14 = 0; var14 < var13; ++var14) {
String namespace = var12[var14];
Config config = ConfigService.getConfig(namespace);
if (interestedKeys == null && interestedKeyPrefixes == null) {
config.addChangeListener(configChangeListener);
} else {
config.addChangeListener(configChangeListener, interestedKeys, interestedKeyPrefixes);
}
}
}
}
}
可以看到,除了关于namespace外如“application.properties”,
这里有关的两个属性:interestedKeys、interestedKeyPrefixes
设置了就取关心的值,不设置就监控整个文件。
*********************************
@Value 相关的类:
ApolloProcessor 实现了BeanPostProcessor,在postProcessBeforeInitialization中对字段和方法进行了处理。
public abstract class ApolloProcessor implements BeanPostProcessor, PriorityOrdered {
public ApolloProcessor() {
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
Class clazz = bean.getClass();
Iterator var4 = this.findAllField(clazz).iterator();
while(var4.hasNext()) {
Field field = (Field)var4.next();
this.processField(bean, beanName, field);
}
var4 = this.findAllMethod(clazz).iterator();
while(var4.hasNext()) {
Method method = (Method)var4.next();
this.processMethod(bean, beanName, method);
}
return bean;
}
在ApolloProcessor 子类SpringValueProcessor中processField、和 processMethod 对注解@Value进行了处理
ublic class SpringValueProcessor extends ApolloProcessor implements BeanFactoryPostProcessor, BeanFactoryAware {
private static final Logger logger = LoggerFactory.getLogger(SpringValueProcessor.class);
private final ConfigUtil configUtil = (ConfigUtil)ApolloInjector.getInstance(ConfigUtil.class);
private final PlaceholderHelper placeholderHelper = (PlaceholderHelper)SpringInjector.getInstance(PlaceholderHelper.class);
private final SpringValueRegistry springValueRegistry = (SpringValueRegistry)SpringInjector.getInstance(SpringValueRegistry.class);
private BeanFactory beanFactory;
private Multimap<String, SpringValueDefinition> beanName2SpringValueDefinitions = LinkedListMultimap.create();
public SpringValueProcessor() {
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
if (this.configUtil.isAutoUpdateInjectedSpringPropertiesEnabled() && beanFactory instanceof BeanDefinitionRegistry) {
this.beanName2SpringValueDefinitions = SpringValueDefinitionProcessor.getBeanName2SpringValueDefinitions((BeanDefinitionRegistry)beanFactory);
}
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (this.configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) {
super.postProcessBeforeInitialization(bean, beanName);
this.processBeanPropertyValues(bean, beanName);
}
return bean;
}
protected void processField(Object bean, String beanName, Field field) {
Value value = (Value)field.getAnnotation(Value.class);
if (value != null) {
Set<String> keys = this.placeholderHelper.extractPlaceholderKeys(value.value());
if (!keys.isEmpty()) {
Iterator var6 = keys.iterator();
while(var6.hasNext()) {
String key = (String)var6.next();
SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false);
this.springValueRegistry.register(this.beanFactory, key, springValue);
logger.debug("Monitoring {}", springValue);
}
}
}
}
protected void processMethod(Object bean, String beanName, Method method) {
Value value = (Value)method.getAnnotation(Value.class);
if (value != null) {
if (method.getAnnotation(Bean.class) == null) {
if (method.getParameterTypes().length != 1) {
logger.error("Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters", new Object[]{bean.getClass().getName(), method.getName(), method.getParameterTypes().length});
} else {
Set<String> keys = this.placeholderHelper.extractPlaceholderKeys(value.value());
if (!keys.isEmpty()) {
Iterator var6 = keys.iterator();
while(var6.hasNext()) {
String key = (String)var6.next();
SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, method, false);
this.springValueRegistry.register(this.beanFactory, key, springValue);
logger.info("Monitoring {}", springValue);
}
}
}
}
}
}
判断字段是否被@Value标记,不为空的情况下解析@Value注解里面设置的value 。
构造SpringValue对象 ,并存到SpringValueRegistry。
在ApolloProcessor 子类ApolloAnnotationProcessor中processMethod对注解@ApolloConfigChangeListener进行了处理
public class AutoUpdateConfigChangeListener implements ConfigChangeListener {
private static final Logger logger = LoggerFactory.getLogger(AutoUpdateConfigChangeListener.class);
private final boolean typeConverterHasConvertIfNecessaryWithFieldParameter = this.testTypeConverterHasConvertIfNecessaryWithFieldParameter();
private final Environment environment;
private final ConfigurableBeanFactory beanFactory;
private final TypeConverter typeConverter;
private final PlaceholderHelper placeholderHelper;
private final SpringValueRegistry springValueRegistry;
private final Gson gson;
public AutoUpdateConfigChangeListener(Environment environment, ConfigurableListableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
this.typeConverter = this.beanFactory.getTypeConverter();
this.environment = environment;
this.placeholderHelper = (PlaceholderHelper)SpringInjector.getInstance(PlaceholderHelper.class);
this.springValueRegistry = (SpringValueRegistry)SpringInjector.getInstance(SpringValueRegistry.class);
this.gson = new Gson();
}
public void onChange(ConfigChangeEvent changeEvent) {
Set<String> keys = changeEvent.changedKeys();
if (!CollectionUtils.isEmpty(keys)) {
Iterator var3 = keys.iterator();
while(true) {
Collection targetValues;
do {
do {
if (!var3.hasNext()) {
return;
}
String key = (String)var3.next();
targetValues = this.springValueRegistry.get(this.beanFactory, key);
} while(targetValues == null);
} while(targetValues.isEmpty());
Iterator var6 = targetValues.iterator();
while(var6.hasNext()) {
SpringValue val = (SpringValue)var6.next();
this.updateSpringValue(val);
}
}
}
}
changeEvent.changedKeys();获取到变更keys
遍历key,通过targetValues = this.springValueRegistry.get取值。
通过updateSpringValue 更新value。
致谢:
https://blog.csdn.net/u013445220/article/details/95590749
以上是关于apollo 动态监听配置文件的主要内容,如果未能解决你的问题,请参考以下文章