成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Java Apollo是如何實現配置更新的

瀏覽:4日期:2022-08-15 17:54:26

這篇文檔主要關注下配置修改后對應的 Java 對象是如何更新,并不關注整體的配置改動流程

所有代碼都來自 apollo-client 項目

更新流程

在 Apollo 控制臺進行配置修改并發布后,對應的 client 端拉取到更新后,會調用到 com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener#onChange 方法

在調用 onChange 會收到對應的修改的配置信息 ConfigChangeEvent, 其中包含改動的 key 和 value, 則改動流程如下:

根據改動的配置的 key 從 springValueRegistry 找到對應的關聯到這個 key 的 Spring Bean 信息,如果找不到則不處理 根據找到的 Spring Bean 信息,進行對應關聯配置的更新

在第二步中會判斷關聯配置是用過屬性關聯還是方法進行關聯的,代碼如下

public void update(Object newVal) throws IllegalAccessException, InvocationTargetException { if (isField()) { injectField(newVal); } else { injectMethod(newVal); }}

在上面的問題中,還有兩個問題存疑

如何通過 key 找到對應的 Spring Bean 信息 如何將 Apollo 的配置值轉換為 Spring 的識別的值

public class AutoUpdateConfigChangeListener implements ConfigChangeListener{ private static final Logger logger = LoggerFactory.getLogger(AutoUpdateConfigChangeListener.class); private final boolean typeConverterHasConvertIfNecessaryWithFieldParameter; 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.typeConverterHasConvertIfNecessaryWithFieldParameter = testTypeConverterHasConvertIfNecessaryWithFieldParameter(); this.beanFactory = beanFactory; this.typeConverter = this.beanFactory.getTypeConverter(); this.environment = environment; this.placeholderHelper = SpringInjector.getInstance(PlaceholderHelper.class); this.springValueRegistry = SpringInjector.getInstance(SpringValueRegistry.class); this.gson = new Gson(); } @Override public void onChange(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. update the value for (SpringValue val : targetValues) { updateSpringValue(val); } } } private void updateSpringValue(SpringValue springValue) { try { Object value = resolvePropertyValue(springValue); springValue.update(value); logger.info('Auto update apollo changed value successfully, new value: {}, {}', value, springValue); } catch (Throwable ex) { logger.error('Auto update apollo changed value failed, {}', springValue.toString(), ex); } } /** * Logic transplanted from DefaultListableBeanFactory * @see org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter) */ private Object resolvePropertyValue(SpringValue springValue) { // value will never be null, as @Value and @ApolloJsonValue will not allow that Object value = placeholderHelper .resolvePropertyValue(beanFactory, springValue.getBeanName(), springValue.getPlaceholder()); if (springValue.isJson()) { value = parseJsonValue((String)value, springValue.getGenericType()); } else { if (springValue.isField()) { // org.springframework.beans.TypeConverter#convertIfNecessary(java.lang.Object, java.lang.Class, java.lang.reflect.Field) is available from Spring 3.2.0+ if (typeConverterHasConvertIfNecessaryWithFieldParameter) { value = this.typeConverter .convertIfNecessary(value, springValue.getTargetType(), springValue.getField()); } else { value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType()); } } else { value = this.typeConverter.convertIfNecessary(value, springValue.getTargetType(), springValue.getMethodParameter()); } } return value; } private Object parseJsonValue(String json, Type targetType) { try { return gson.fromJson(json, targetType); } catch (Throwable ex) { logger.error('Parsing json ’{}’ to type {} failed!', json, targetType, ex); throw ex; } } private boolean testTypeConverterHasConvertIfNecessaryWithFieldParameter() { try { TypeConverter.class.getMethod('convertIfNecessary', Object.class, Class.class, Field.class); } catch (Throwable ex) { return false; } return true; }}如何將配置 key 和 Spring Bean 關聯起來

在 Spring 常見配置包括 2 種

public class ApiConfig { // 1. 直接在 Field 是進行注入 @Value('${feifei.appId}') protected String appId; protected String predUrl; // 2. 在方法上進行注入 @Value('${predUrl}') public void setPredUrl(String predUrl) { this.predUrl = predUrl; }}

在 Apollo 代碼中,通過實現 BeanPostProcessor 接口來檢測所有的Spring Bean 的創建過程,在 Spring Bean 創建的過程中會調用對應的 org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization 和 org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization 方法。

Apollo 通過在 Bean 生成過程中,檢測 Bean 類中屬性和方法是否存在 @Value 注解,如果存在,提出其中的 key, 其處理方法在 processField 和 processMethod 分別處理 Field 和 Method 中可能出現的 @Value 注解。如果存在注解則將對應的信息存到 SpringValue 對應 springValueRegistry 全局對象中,方便在其它地方可以直接獲取。

在屬性除了通過 @Value 注入,也可以用過 xml 進行配置,在這種情況通過 processBeanPropertyValues 方法來處理

通過兩種處理方式就可以將 key 和對應的 Spring Bean 信息關聯起來

public class SpringValueProcessor extends ApolloProcessor implements BeanFactoryPostProcessor, BeanFactoryAware { private static final Logger logger = LoggerFactory.getLogger(SpringValueProcessor.class); private final ConfigUtil configUtil; private final PlaceholderHelper placeholderHelper; private final SpringValueRegistry springValueRegistry; private BeanFactory beanFactory; private Multimap<String, SpringValueDefinition> beanName2SpringValueDefinitions; public SpringValueProcessor() { configUtil = ApolloInjector.getInstance(ConfigUtil.class); placeholderHelper = SpringInjector.getInstance(PlaceholderHelper.class); springValueRegistry = SpringInjector.getInstance(SpringValueRegistry.class); beanName2SpringValueDefinitions = LinkedListMultimap.create(); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled() && beanFactory instanceof BeanDefinitionRegistry) { beanName2SpringValueDefinitions = SpringValueDefinitionProcessor .getBeanName2SpringValueDefinitions((BeanDefinitionRegistry) beanFactory); } } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (configUtil.isAutoUpdateInjectedSpringPropertiesEnabled()) { super.postProcessBeforeInitialization(bean, beanName); processBeanPropertyValues(bean, beanName); } return bean; } @Override protected void processField(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()); if (keys.isEmpty()) { return; } for (String key : keys) { SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false); springValueRegistry.register(beanFactory, key, springValue); logger.debug('Monitoring {}', springValue); } } @Override protected void processMethod(Object bean, String beanName, Method method) { //register @Value on method Value value = method.getAnnotation(Value.class); if (value == null) { return; } //skip Configuration bean methods if (method.getAnnotation(Bean.class) != null) { return; } if (method.getParameterTypes().length != 1) { logger.error('Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters', bean.getClass().getName(), method.getName(), method.getParameterTypes().length); return; } Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value()); if (keys.isEmpty()) { return; } for (String key : keys) { SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, method, false); springValueRegistry.register(beanFactory, key, springValue); logger.info('Monitoring {}', springValue); } } private void processBeanPropertyValues(Object bean, String beanName) { Collection<SpringValueDefinition> propertySpringValues = beanName2SpringValueDefinitions .get(beanName); if (propertySpringValues == null || propertySpringValues.isEmpty()) { return; } for (SpringValueDefinition definition : propertySpringValues) { try { PropertyDescriptor pd = BeanUtils .getPropertyDescriptor(bean.getClass(), definition.getPropertyName()); Method method = pd.getWriteMethod(); if (method == null) { continue; } SpringValue springValue = new SpringValue(definition.getKey(), definition.getPlaceholder(), bean, beanName, method, false); springValueRegistry.register(beanFactory, definition.getKey(), springValue); logger.debug('Monitoring {}', springValue); } catch (Throwable ex) { logger.error('Failed to enable auto update feature for {}.{}', bean.getClass(), definition.getPropertyName()); } } // clear beanName2SpringValueDefinitions.removeAll(beanName); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; }}

以上就是Java Apollo是如何實現配置更新的的詳細內容,更多關于Java Apollo 配置更新的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
色婷婷香蕉在线一区二区| 奇米精品一区二区三区在线观看一| 亚洲综合偷拍欧美一区色| 欧美日韩国产欧| 久久人人爽爽爽人久久久| 高清beeg欧美| 欧美草草影院在线视频| 国产精品一区2区| 欧美精品99久久久**| 亚洲va天堂va国产va久| 国产欧美精品| 亚洲一区二区av在线| 国产精品久久久久久久久久直播| 亚洲欧美日韩在线播放| 亚洲高清不卡一区| 国产精品国产三级国产三级人妇 | 中文字幕精品在线不卡| 成人午夜电影网站| 日韩女优av电影| 午夜精品123| 老司机精品导航| 日本欧美一区二区在线观看| 久久婷婷麻豆| 免费三级欧美电影| 欧美日韩成人一区| 国产一区二区三区精品视频| 欧美一区二区人人喊爽| 成人av在线一区二区| 欧美xxxxxxxxx| 91美女在线看| 国产精品乱人伦中文| 亚洲国产欧美不卡在线观看| 一区二区三国产精华液| 国产精品一区二区欧美| 日本不卡免费在线视频| 538在线一区二区精品国产| av在线播放成人| 中文字幕 久热精品 视频在线| 极品av少妇一区二区| 一区二区三区在线播放| 免费在线成人| 久久国产尿小便嘘嘘尿| 欧美一区二区三区影视| av福利精品导航| 国产精品成人在线观看| 国产欧美日韩综合一区在线观看 | 五月天激情综合网| 欧美视频一二三区| 国产激情偷乱视频一区二区三区| 久久先锋影音av| 一区免费视频| 三级一区在线视频先锋| 9191国产精品| 女生裸体视频一区二区三区| 一区二区三区在线观看网站| 91精品福利视频| 国产成人精品一区二| 欧美高清在线精品一区| 国产精品亚洲综合| 久久国产成人午夜av影院| 精品国产伦一区二区三区观看体验| 你懂的国产精品永久在线| 亚洲精品伦理在线| 色美美综合视频| 国产成人免费视频网站 | 亚洲高清视频中文字幕| 欧美性做爰猛烈叫床潮| 成人高清免费观看| 亚洲男同性恋视频| 精品视频一区二区不卡| 欧美在线精品一区| 亚洲国产精品久久人人爱| 欧美一区二区视频在线观看2020 | 亚洲成人福利片| 91精品国产福利| 国内精品美女在线观看 | 国产一区二三区好的| 国产亚洲婷婷免费| 久久精品网址| av资源网一区| 亚洲福利视频一区二区| 欧美一区二区精美| 亚洲人成久久| 精品一区二区免费视频| 国产精品亲子伦对白| 一本久道中文字幕精品亚洲嫩| 成人国产精品免费观看动漫| 亚洲精品亚洲人成人网| 欧美精品三级在线观看| 欧美视频亚洲视频| 久久国产精品无码网站| 国产精品成人在线观看| 欧美精品tushy高清| 99视频精品| 东方aⅴ免费观看久久av| 一区二区三区精品视频在线| 欧美一三区三区四区免费在线看| 亚洲日本无吗高清不卡| 国产成人亚洲综合a∨婷婷图片| 伊人开心综合网| 日韩一级黄色片| 国产精品美女诱惑| 不卡免费追剧大全电视剧网站| 亚洲一卡二卡三卡四卡无卡久久| 日韩欧美的一区| 免费在线成人av| 欧美99在线视频观看| 美女一区二区视频| 精品免费日韩av| 在线观看视频欧美| 亚洲激情一区二区| 粉嫩av一区二区三区| 亚洲一区二区影院| 久久精品人人做人人综合| 欧美亚洲综合色| 亚洲欧洲日本国产| eeuss鲁片一区二区三区在线看| 日韩成人一级片| 中文字幕五月欧美| 欧美v亚洲v综合ⅴ国产v| 一本一道久久a久久精品综合蜜臀| 欧美视频导航| 成人中文字幕电影| 强制捆绑调教一区二区| 日韩码欧中文字| 精品国精品国产| 免费亚洲一区二区| 欧美三级网页| 成人视屏免费看| 蜜臀av性久久久久蜜臀aⅴ流畅| 日韩一区日韩二区| 久久毛片高清国产| 91精品国产综合久久精品性色 | 伊人久久亚洲美女图片| 国产传媒一区在线| 日韩高清中文字幕一区| 一区二区三区日韩精品视频| 欧美极品aⅴ影院| 日韩情涩欧美日韩视频| 91国模大尺度私拍在线视频| 亚洲专区免费| 亚洲免费高清| 激情成人亚洲| 欧美在线看片| 91丨porny丨首页| 成人午夜免费视频| 国产一区二区三区久久久| 日韩电影在线一区二区| 亚洲激情一二三区| 亚洲欧洲www| 国产精品高潮呻吟久久| 日本一区二区在线不卡| 精品国产制服丝袜高跟| 91麻豆精品国产91久久久久久久久 | 久久一区二区三区四区| 3d动漫精品啪啪一区二区竹菊| 色视频成人在线观看免| 久久久www| 久久人人精品| 国产精品入口66mio| 99精品视频免费| 日韩午夜电影| 亚洲激情黄色| 亚洲激情在线| 亚洲激情一区二区三区| 欧美三日本三级少妇三99| 午夜久久久久| 欧美日韩少妇| 欧美日韩一区二区视频在线观看 | 欧美日本高清| 亚洲欧美综合| 国产精品国产三级国产专区53| 欧美a级一区| 国产精品av久久久久久麻豆网| 亚洲欧美综合国产精品一区| 午夜精彩国产免费不卡不顿大片| 欧美一站二站| 国内综合精品午夜久久资源| 亚洲天堂黄色| 在线精品一区| 国产一区91| 性欧美长视频| 欧美亚一区二区| 欧美女孩性生活视频| 制服丝袜成人动漫| 精品国内二区三区| 国产欧美日韩在线看| 中文字幕+乱码+中文字幕一区| 国产精品国产精品国产专区不片| 亚洲欧美另类久久久精品2019| 亚洲午夜激情av| 奇米色一区二区三区四区| 国产制服丝袜一区| www.成人网.com| 欧美精品一区三区在线观看| 亚洲精品国产精品国自产观看| 美女日韩在线中文字幕| 欧美日韩精品福利| 欧美成人video| 中文字幕第一区第二区|