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);
}
}
}
}
}

NacosValue 注解的更多相关文章

  1. Spring Cloud Alibaba Nacos 入门

    概览 阿里巴巴在2018年7月份发布Nacos, Nacos是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台.并表示在6-8个月完成到生产可用的0.8版本,目前版本是0.9版本. Na ...

  2. SpringBoot使用Nacos配置中心

    本文介绍SpringBoot如何使用阿里巴巴Nacos做配置中心. 1.Nacos简介 Nacos是阿里巴巴集团开源的一个易于使用的平台,专为动态服务发现,配置和服务管理而设计.它可以帮助您轻松构建云 ...

  3. Nacos深入浅出(九)

    然而Nacos的发布操作并不是上面我们想的那样通过代理去实现,通过下面的代码我们分析下: public class NacosConfigurationPropertiesBindingPostPro ...

  4. Spring Boot 2.x 基础案例:整合Dubbo 2.7.3+Nacos1.1.3(配置中心)

    本文原创首发于公众号:Java技术干货 1.概述 本文将Nacos作为配置中心,实现配置外部化,动态更新.这样做的优点:不需要重启应用,便可以动态更新应用里的配置信息.在如今流行的微服务应用下,将应用 ...

  5. Nacos快速开始

    Nacos是一个服务发现.配置管理和服务管理的组件. 说到服务注册与发现,我想到Eureka.Zookeeper 说到服务治理,我想到Dubbo 说到配置管理,我想到Apollo 作为后起之秀的Nac ...

  6. Nacos系列(一):Nacos环境安装及Hello World示例

    现在微服务架构越来越火,微服务架构中比较重要的一项就是配置中心, Nacos是阿里巴巴的一个开源项目,它的其中一个功能就是可以作为配置中心,实现配置的动态变更.历史版本对比.配置回滚等功能. 更多的描 ...

  7. 微服务从nacos配置中心获得配置信息

    一,安装nacos, 略 二,创建父工程和微服务工程 service1, service2,以idea为例 1, new -> project -> Maven -> 填写group ...

  8. nacos 作为配置中心使用心得--配置使用

    1.页面配置 撇开原理不谈,先来介绍下nacos的基本使用,如下图nacos配置是以data id为单位进行使用的,基本上一个服务的一个配置文件就对应一个data id,支持的格式有xml,yaml, ...

  9. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

随机推荐

  1. vue项目1-pizza点餐系统8-登陆和注册结构

    <template> <!-- 设置行 --> <div class="row mt-3"> <!-- 设置列 --> <di ...

  2. Centos克隆虚拟机后配置网络

    修改网卡相关信息,复制第二个网卡的mac地址. vim /etc/udev/rules.d/70-persistent-net.rules 修改网卡的信息 vim /etc/sysconfig/net ...

  3. IDEA tomcat热部署方法

    项目开发过程中,我们一般希望在修改完代码之后不重启项目即可提现出修改的结果,那么热部署项目就显得十分必要了.在idea中将项目热部署至tomcat中的方法如下: 首先打开tomcat配置界面,在ser ...

  4. Django开发环境配置(win10)

    开发工具 pycharm专业版 安装Django pip install Django==2.0 如果不带版本号,默认安装最新版本查看Django 查看版本: python -m django --v ...

  5. centos 7 安装相关环境

    How To Create a Sudo User on CentOS 7 https://www.digitalocean.com/community/tutorials/how-to-create ...

  6. Java Annotation 刷课笔记(二)

    1.反射机制性能问题(安全检查) 1.1setAccessible 启用和禁用访问安全检查的开关,值为true,则指示反射的对象在使用时应该取消Java语言访问检查,值为false,则指示反射的对象应 ...

  7. python dict字典常用操作

    字典的特性:key唯一无序 '''特性:key唯一:无序''' info = { 'stu1101': "安徽", 'stu1102': "北京", 'stu1 ...

  8. js 动态时间

    <script type="text/javascript"> function show_cur_times(){ //获取当前日期 var date_time = ...

  9. Flask【第5篇】:用Falsk实现的分页

    用flask实现的分页 一.flask实现的分页组件 from urllib.parse import urlencode,quote,unquote class Pagination(object) ...

  10. linux下安装MySQL(mariadb)

    MySQL(mariadb) MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可. 开发这个分支的原因之一是:甲骨文公司收购了MySQL后,有将MySQL闭源 ...