NacosValue 注解
NacosValue 定义在 nacos-api 工程中:com.alibaba.nacos.api.config.annotation.NacosValue
注解解析在 nacos-spring-project 工程中:
com.alibaba.nacos.spring.util.NacosBeanUtils#registerNacosValueAnnotationBeanPostProcessor
com.alibaba.nacos.spring.context.annotation.config.NacosValueAnnotationBeanPostProcessor
实现 BeanPostProcessor 接口,可以在创建 bean 的过程中插入自定义逻辑,NacosValueAnnotationBeanPostProcessor 扫描属性和方法上的 NacosValue 注解。
执行顺序: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 拉取更新,如果有更新,则通过事件把新值注入到属性中。
com.alibaba.nacos.client.config.impl.ClientWorker.LongPullingRunnable
com.alibaba.nacos.client.config.impl.CacheData#safeNotifyListener
检测到变化
// 配置文件发生变化,把这种变化转化为 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);
}
发布事件
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);
}
}
}
}
}
最新文章
- How to install ruby on mac/ change ruby source in china
- 基于Andoird 4.2.2的同步框架源代码学习——同步发起端
- android99 拍照摄像
- DateTimePicker时间控件:
- Android Studio学习随笔-模拟耗时操作(sleep)
- 将vim改造成C/C++开发环境(IDE) 2011
- 数据分析与展示——Matplotlib库入门
- 24 服务AIDL
- PHP内核之旅-6.垃圾回收机制
- App 基本图片配置(I)
- HOWTO: Avizo/Amira使用前的显卡设置(Volume Rendering,Volren不显示)
- 剑指offer(14)链表中倒数第K个节点
- 【Java】 剑指offer(17) 在O(1)时间删除链表结点
- mysql5.7 生成列 generated column
- python 基础 列表生成式 生成器
- highcharts柱状图实现legend和数据列一一对应效果
- Spring MVC、MyBatis整合文件配置详解
- c++重在运算符
- 样条曲线catmull rom转bezier
- java 文件操作知识点