NacosValue 注解

NacosValue 定义在 nacos-api 工程中:com.alibaba.nacos.api.config.annotation.NacosValueweb

 

注解解析在 nacos-spring-project 工程中:spring

com.alibaba.nacos.spring.util.NacosBeanUtils#registerNacosValueAnnotationBeanPostProcessorapi

com.alibaba.nacos.spring.context.annotation.config.NacosValueAnnotationBeanPostProcessorapp

实现 BeanPostProcessor 接口,能够在建立 bean 的过程当中插入自定义逻辑,NacosValueAnnotationBeanPostProcessor 扫描属性和方法上的 NacosValue 注解。webapp

执行顺序:bean 的构造方法,postProcessBeforeInitialization,init,postProcessAfterInitialization异步

@Override public Object postProcessBeforeInitialization(Object bean, final String beanName) throws BeansException { doWithFields(bean, beanName); doWithMethods(bean, beanName); return super.postProcessBeforeInitialization(bean, beanName); }

 

nacos 客户端定时从 nacos server 拉取更新,若是有更新,则经过事件把新值注入到属性中。ide

com.alibaba.nacos.client.config.impl.ClientWorker.LongPullingRunnable
com.alibaba.nacos.client.config.impl.CacheData#safeNotifyListener
检测到变化post

 

 

// 配置文件发生变化,把这种变化转化为 spring 事件
private void safeNotifyListener(final String dataId, final String group, final String content, final String md5, final ManagerListenerWrap listenerWrap) { final Listener listener = listenerWrap.listener; // 把逻辑封装成 job,可异步可同步
    Runnable job = new Runnable() { public void run() { ClassLoader myClassLoader = Thread.currentThread().getContextClassLoader(); ClassLoader appClassLoader = listener.getClass().getClassLoader(); try { if (listener instanceof AbstractSharedListener) { AbstractSharedListener adapter = (AbstractSharedListener) listener; adapter.fillContext(dataId, group); LOGGER.info("[{}] [notify-context] dataId={}, group={}, md5={}", name, dataId, group, md5); } // 执行回调以前先将线程classloader设置为具体webapp的classloader,以避免回调方法中调用spi接口是出现异常或错用(多应用部署才会有该问题)。
 Thread.currentThread().setContextClassLoader(appClassLoader); ConfigResponse cr = new ConfigResponse(); cr.setDataId(dataId); cr.setGroup(group); cr.setContent(content); configFilterChainManager.doFilter(null, cr); String contentTmp = cr.getContent(); // 真正发布事件的地方
 listener.receiveConfigInfo(contentTmp); listenerWrap.lastCallMd5 = md5; LOGGER.info("[{}] [notify-ok] dataId={}, group={}, md5={}, listener={} ", name, dataId, group, md5, listener); } catch (NacosException de) { LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} errCode={} errMsg={}", name, dataId, group, md5, listener, de.getErrCode(), de.getErrMsg()); } catch (Throwable t) { LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} tx={}", name, dataId, group, md5, listener, t.getCause()); } finally { Thread.currentThread().setContextClassLoader(myClassLoader); } } }; final long startNotify = System.currentTimeMillis(); try { if (null != listener.getExecutor()) { listener.getExecutor().execute(job); } else { job.run(); } } catch (Throwable t) { LOGGER.error("[{}] [notify-error] dataId={}, group={}, md5={}, listener={} throwable={}", name, dataId, group, md5, listener, t.getCause()); } final long finishNotify = System.currentTimeMillis(); LOGGER.info("[{}] [notify-listener] time cost={}ms in ClientWorker, dataId={}, group={}, md5={}, listener={} ", name, (finishNotify - startNotify), dataId, group, md5, listener); }

发布事件spa

com.alibaba.nacos.spring.context.event.config.DelegatingEventPublishingListener#publishEvent线程

DelegatingEventPublishingListener 类在 nacos-spring-context 工程中

private void publishEvent(String content) { NacosConfigReceivedEvent event = new NacosConfigReceivedEvent(configService, dataId, groupId, content); applicationEventPublisher.publishEvent(event); }

消费事件

com.alibaba.nacos.spring.context.annotation.config.NacosValueAnnotationBeanPostProcessor#onApplicationEvent

NacosValueAnnotationBeanPostProcessor 类在 nacos-spring-context 工程中

NacosValueAnnotationBeanPostProcessor 实现了 ApplicationListener<NacosConfigReceivedEvent> 接口,NacosConfigReceivedEvent 继承自 ApplicationEvent。

public void onApplicationEvent(NacosConfigReceivedEvent event) { String content = event.getContent(); if (content != null) { Properties configProperties = toProperties(content); for (Object key : configProperties.keySet()) { String propertyKey = (String)key; List<NacosValueTarget> beanPropertyList = placeholderNacosValueTargetMap.get(propertyKey); if (beanPropertyList == null) { continue; } String propertyValue = configProperties.getProperty(propertyKey); for (NacosValueTarget nacosValueTarget : beanPropertyList) { if (nacosValueTarget.method == null) { setField(nacosValueTarget, propertyValue); } else { setMethod(nacosValueTarget, propertyValue); } } } } }
相关文章
相关标签/搜索