目录

  • 实践
    • dubbo-demo-interface
    • dubbo-demo-xml-provider
      • notify-provider.xml
      • UserNotifyServiceImpl
      • ProviderApplication
    • dubbo-demo-xml-consumer
      • ConsumerNotifyService
      • ConsumerNotifyServiceImpl
      • notify-consumer.xml
      • ConsumerApplication
    • 运行
  • 源码

今天主要给大家分享一下dubbo的事件通知机制。
先看下dubbo中文官网的示例解释:事件通知。

在调用之前、调用之后、出现异常时,会触发 oninvoke、onreturn、onthrow 三个事件,可以配置当事件发生时,通知哪个类的哪个方法.

实践

溪源目的是快速学习dubbo的相关机制,故定义的相同的接口和方法,采用分包的方式解耦合,便于后期维护。
先看服务接口

dubbo-demo-interface

  • 目录如图
  • ** UserNotifyService **
/*** @author wx* @date 2020/9/8 1:44 下午* 测试事件通知*/
public interface UserNotifyService {/*** 获取用户名字* @param userId* @return*/String getUserName(String userId);
}

dubbo-demo-xml-provider

  • 目录如下

notify-provider.xml

定义一个新的配置文件,用于配置事件通知相关bean。

UserNotifyServiceImpl

/*** @author wx* @date 2020/9/8 1:46 下午*/
@Service
public class UserNotifyServiceImpl implements UserNotifyService {private static final String USER_ID  = "1503892";@Overridepublic String getUserName(String userId) {if (StringUtils.isBlank(userId)) {throw new RpcException("userId is null");}return USER_ID.equals(userId) ? "溪~源" : "";}
}

ProviderApplication

/*** 事件通知* @throws IOException*/private static void notifyTest() throws IOException {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/notify-provider.xml");context.start();System.in.read();}

dubbo-demo-xml-consumer

  • 目录如下

ConsumerNotifyService

扩展点

1. oninvoke方法:必须具有与真实的被调用方法sayHello相同的入参列表:例如,oninvoke(String name)
2. onreturn方法:2.1 至少要有一个入参且第一个入参必须与getUserName的返回类型相同,接收返回结果:例如,onReturnWithoutParam(String result);2.2 可以有多个参数,多个参数的情况下,第一个后边的所有参数都是用来接收getUserName入参的:例如, onreturn(String result, String name)
3. onthrow方法:3.1 至少要有一个入参且第一个入参类型为Throwable或其子类,接收返回结果;例如,onthrow(Throwable ex);3.2 可以有多个参数,多个参数的情况下,第一个后边的所有参数都是用来接收getUserName入参的:例如,onthrow(Throwable ex, String name);
4. 如果是consumer在调用provider的过程中,出现异常时不会走onthrow方法的,onthrow方法只会在provider返回的RpcResult中含有Exception对象时,才会执行。(dubbo中下层服务的Exception会被放在响应RpcResult的exception对象中传递给上层服务)

对于上面的解释,大家可能会存在疑惑,部分方法要求第一个参数为服务接口的返回值类型???约定大于配置???揭开迷底的方法就是debug源码设计实现逻辑~
源代码:


/*** @author wx* @date 2020/9/8 1:53 下午*/
public interface ConsumerNotifyService {/*** 调用之前* @param name*/void onInvoke(String name);/*** 无参数:调用之后* @param result 参数用于接收 [事件通知]服务接口的方法返回值类型保持一致*/void onReturnWithoutParam(String result);/*** 有参数:调用之后* @param result 第一个参数 接收 [事件通知]服务接口的方法返回值类型保持一致* @param name 第二个或者之后,与[事件通知]服务接口的方法入参保持一致*/void onReturn(String result, String name);/*** 抛异常* @param ex* @param name*/void onThrow(Throwable ex, String name);
}

ConsumerNotifyServiceImpl

/*** @author wx* @date 2020/9/8 1:59 下午*/
@Service
public class ConsumerNotifyServiceImpl implements ConsumerNotifyService{@Overridepublic void onInvoke(String name) {System.out.println("[事件通知]执行onInvoke方法,参数:" + name);}@Overridepublic void onReturnWithoutParam(String result) {System.out.println("[事件通知]执行onReturnWithoutParam方法,返回结果:" + result);}@Overridepublic void onReturn(String result, String name) {System.out.println("[事件通知]执行onReturn方法,参数:" + name + ", 返回结果:" + result);}@Overridepublic void onThrow(Throwable ex, String name) {System.out.println("[事件通知]执行onThrow方法,参数:" + name + ", 异常信息:" + ex.getMessage());}
}

notify-consumer.xml

同理,消费者端也新建notify-consumer.xml文件,具体配置如图:

ConsumerApplication

 private static void notifyTest() {ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring/notify-consumer.xml");UserNotifyService notifyService = context.getBean(UserNotifyService.class);String userName = notifyService.getUserName("1503892");System.out.println(userName);}

运行

分别启动生产者和消费者,运行结果如图:
分别执行了onInvoke方法和onReturn方法

源码

关于dubbo的事件通知机制,源码实现基本上位于FutureFilter类中,先给大家贴一下类方法目录:

上面溪源提到为什么部分方法要约定第一个参数与接口方法返回值类型保持一致呢?下面揭开迷底,我们进入fireReturnCallback方法

private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) {....//省略部分代码Object[] params;//获取方法参数类型Class<?>[] rParaTypes = onReturnMethod.getParameterTypes();if (rParaTypes.length > 1) {//两个参数:第一个参数与真实方法getUserName方法返回结果类型相同,第二个接收所有的真实请求参数if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)) {params = new Object[2];// 真实方法的返回结果params[0] = result;//执行方法入参params[1] = args;} else {//多个参数:第一个参数与真实方法getUserName结果类型相同,后边几个接收所有的真实请求参数params = new Object[args.length + 1];params[0] = result;System.arraycopy(args, 0, params, 1, args.length);}} else {//只有一个参数:接收返回执行结果params = new Object[]{result};}try {onReturnMethod.invoke(onReturnInst, params);} catch (InvocationTargetException e) {fireThrowCallback(invoker, invocation, e.getTargetException());} catch (Throwable e) {fireThrowCallback(invoker, invocation, e);}}

事件通知机制,底层实际上利用了反射机制实现类方法的调用。

溪源初次接触dubbo本地存根机制,如文中存在错误之处,希望大家及时指正!

源码传送门:https://github.com/stream-source/dubbo/tree/master/dubbo-demo

dubbo学习之事件通知实践相关推荐

  1. 学习笔记(07):C++网络编程进阶-IO模型之重叠Overlapped IO(基于事件通知)

    立即学习:https://edu.csdn.net/course/play/6082/113760?utm_source=blogtoedu 重叠Overlapped IO模型 重叠模型让应用程序使用 ...

  2. 案例学习BlazeDS+Spring之八InSync06“松耦合”UI同步事件通知

    InSync06:增加"松耦合"UI同步事件通知 一.运行DEMO: 1.运行程序:http://localhost:8400/spring-flex-testdrive/insy ...

  3. 零信任策略下云上安全信息与事件管理实践

    简介:随着企业数字化转型的深入推进,网络安全越来越被企业所重视.为了构建完备的安全防御体系,企业通常会引入了防火墙(Firewall).防病毒系统(Anti-Virus System,AVS).入侵防 ...

  4. 一个近乎完美基于Dubbo的微服务改造实践

    网易考拉(以下简称考拉)是网易旗下以跨境业务为主的综合型电商,自 2015 年 1 月 9 日上线公测后,业务保持了高速增长,这背后离不开其技术团队的支撑. 微服务化是电商 IT 架构演化的必然趋势, ...

  5. dubbo学习视频资料

    dubbo学习视频资料 请叫我小橙,橙橙 偶遇青春 Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 Spring框架无缝集成. ...

  6. java 事件通知_正确获取Java事件通知

    java 事件通知 实现观察者模式以提供Java事件通知似乎是一件容易的事. 但是,容易陷入一些陷阱. 这是我在各种场合不慎造成的常见错误的解释-- Java事件通知 让我们从一个简单的bean St ...

  7. 正确获取Java事件通知

    实现观察者模式以提供Java事件通知似乎是一件容易的事. 但是,容易陷入一些陷阱. 这是我在各种场合不慎造成的常见错误的解释-- Java事件通知 让我们从一个简单的bean StateHolder开 ...

  8. 【七夕特殊礼物】Dubbo学习之SPI实战与debug源码

    目录 绪论 环境搭建 dubbo-demo-interface dubbo-demo-xml dubbo-demo-xml-provider 源码跟踪 getExtension createExten ...

  9. Dubbo学习总结(10)——里程碑式 Dubbo 2.7.5 版本发布,性能提升30%,支持 HTTP/2、TLS、Protobuf等特性。

    作者简介:刘军,GitHub账号Chickenlj,Apache Dubbo PMC,项目核心维护者,见证了Dubbo从重启开源到Apache毕业的整个流程.现任职阿里云云原生应用平台团队,参与服务框 ...

最新文章

  1. 什么是Python?好学吗?
  2. 【Flutter】Flutter 混合开发 ( Flutter 与 Native 通信 | 在 Flutter 端实现 EventChannel 通信 )
  3. show()和exec()的区别
  4. ADO.NET连接字符串
  5. mysql lock_MySQL-锁总结
  6. 面试题22. 链表中倒数第k个节点
  7. 图论算法 —— 图论概述
  8. 2019青海大学计算机调剂,2019青海大学招收硕士研究生调剂公告
  9. 从0开始学习 GitHub 系列之「07.GitHub 常见的几种操作」
  10. tomcat启动报错:java.lang.NoClassDefFoundError
  11. 安卓中的数据存储方式以及ContentProvider的简单介绍
  12. 使用listen()和accept()函数
  13. BAT常见的20道Java面试题详解,完整版开放免费下载!
  14. android 计时器服务,启动时使用计时器/alarmclock,更新服务_android_开发99编程知识库...
  15. wpf界面菜单栏设计
  16. PHP框架设计之 ThinkPHP5 源码解析
  17. 前端开发基础知识汇总
  18. pt100+51单片机的温控系统程序+仿真图 还带压力显示的
  19. javascript 实现blob加密视频(html video),服务端为php
  20. 【BZOJ4668】冷战(并查集)

热门文章

  1. spark ui 上schedulingDelay理解
  2. php post fsockopen,php_fsockopen_post
  3. Toolbar详解 · Material Design Part 2
  4. java运输_JAVA-基础-方法
  5. SpringBoot精通系列-开发案例之配置Druid数据库连接池
  6. Java中Random详解
  7. 并发编程的数据竞争问题以及解决之道
  8. 《Go 语言程序设计》读书笔记(十)反射
  9. Laravel源码解析之Response
  10. 实战:自定义简易版SpringBoot