dubbo新手学习之事件通知实践教程

前言

今天主要给大家分享一下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";
 @Override
 public 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{
 @Override
 public void onInvoke(String name) {
  System.out.println("[事件通知]执行onInvoke方法,参数:" + name);
 }

 @Override
 public void onReturnWithoutParam(String result) {
  System.out.println("[事件通知]执行onReturnWithoutParam方法,返回结果:" + result);
 }

 @Override
 public void onReturn(String result, String name) {
  System.out.println("[事件通知]执行onReturn方法,参数:" + name + ", 返回结果:" + result);
 }

 @Override
 public 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新手学习之事件通知实践教程的文章就介绍到这了,更多相关dubbo事件通知内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot2.0整合dubbo的示例代码

    写在前面: 使用springboot作为web框架,方便开发许多,做分布式开发,dubbo又不可少,那么怎么整合在一起呢, 跟我学一遍,至少会用 注意,springboot2.0和springboot1.x与dubbo整合不一样, 1.环境 1.新建一个空的maven项目,作为父工程,新建moudle,,service(接口层,及实现层,没有具体分,),web(web层,springboot项目) 项目结构如下 父pom如下 <properties> <project.build.sou

  • 基于注解的Dubbo服务配置方法(实例讲解)

    基于注解的Dubbo服务配置可以大大减少dubbo xml配置文件中的Service配置量,主要步骤如下: 一.服务提供方 1. Dubbo配置文件中增加Dubbo注解扫描 <!-- 开启dubbo注解支持 --> <!-- 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类 --> <dubbo:annotation package="com.bounter" /> 2.Service实现

  • dubbo的配置文件详解(推荐)

    一.dubbo常用配置 <dubbo:service/> 服务配置,用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心. eg.<dubbo:service ref="demoService" interface="com.unj.dubbotest.provider.DemoService" /> <dubbo:reference/> 引用服务配置,用于创建一个远程服务代理,一个引用

  • SpringBoot与Dubbo整合的方式详解

    1. 使用默认application.properties和注解的方式 导入dubbo-starter,在application.properties配置属性,使用@Service注解来暴露服务,使用@Reference来引用服务.具体可参考 Dubbo整合SpringBoot,这里截取部分代码方便理解. 属性在application.properties中配置 服务提供方使用@Service注解暴露服务 部分配置如"timeout"等可以在注解上添加 服务消费方使用@Referenc

  • Spring Boot 集成Dubbo框架实例

    使用Spring Boot 与Dubbo集成,这里我之前尝试了使用注解的方式,简单的使用注解注册服务其实是没有问题的,但是当你涉及到使用注解的时候在服务里面引用事务,注入其他对象的时候,会有一些问题.于是我就果断放弃了注解了,使用的是XML,这里可能介绍的是Dubbo,但是如果使用Dubbox的话,基本上是兼容的.接下来,将说说使用XML的方式与Spring Boot在一起开发. 1.创建工程在pom.xml中加入依赖 创建工程名为: (1)springboot-dubbo-provide (2

  • dubbo 管理控制台安装和使用详解

    关于dubbo的配置使用已经配置好了简单的示例,下面先记录下dubbo管理控制台的安装和使用(用的zookeeper的注册中心),在网上找了些按照示例 dubbo管理控制台开源部分主要包含: 提供者  路由规则  动态配置  访问控制  权重调节  负载均衡  负责人,等管理功能. 1.下载dubbo 我上传地址:http://download.csdn.net/detail/liweifengwf/7784901 官方地址:http://code.alibabatech.com/mvn/rel

  • dubbo新手学习之事件通知实践教程

    前言 今天主要给大家分享一下dubbo的事件通知机制. 先看下dubbo中文官网的示例解释:事件通知. 在调用之前.调用之后.出现异常时,会触发 oninvoke.onreturn.onthrow 三个事件,可以配置当事件发生时,通知哪个类的哪个方法. 实践 溪源目的是快速学习dubbo的相关机制,故定义的相同的接口和方法,采用分包的方式解耦合,便于后期维护. 先看服务接口 dubbo-demo-interface 目录如图 ** UserNotifyService ** /** * @auth

  • Python新手学习raise用法

    当程序出现错误时,系统会自动引发异常.除此之外,Python 也允许程序自行引发异常,自行引发异常使用 raise 语句来完成. 很多时候,系统是否要引发异常,可能需要根据应用的业务需求来决定,如果程序中的数据.执行与既定的业务需求不符,这就是一种异常.由于与业务需求不符而产生的异常,必须由程序员来决定引发,系统无法引发这种异常. 如果需要在程序中自行引发异常,则应使用 raise 语句.raise 语句有如下三种常用的用法: raise:单独一个 raise.该语句引发当前上下文中捕获的异常(

  • vue.js学习之UI组件开发教程

    本文主要给大家介绍了关于vue.js之UI组件开发的相关内容,分享出来供大家参考学习,下面来一起看看详细的介绍: 1. 新建组件: <script src="/public/javascripts/vue.js"></script> <style> #app1{background-color: red} #app2{background-color: blue} </style> <body> <div id=&quo

  • Java新手环境搭建 Tomcat安装配置教程

    安装 Tomcat 之前请一定先安装 Java ,然后才能安装 Tomcat . 安装 Java .环境变量 path 的设置以及 cmd 小技巧请看:Java新手环境搭建 JDK8安装配置教程 下载 Tomcat 首先到 Tomcat 的官方网站下载 Windows 版本的 Tomcat 最新版,根据我们所使用的操作系统,我们下载 64 位 Windows 的 zip 版本.不建议使用 Installer 版本. 我们以 apache-tomcat-9.0.0.M15-windows-x64.

  • 新手学习微服务SpringCloud项目架构搭建方法

    这篇文章主要介绍了新手学习微服务SpringCloud项目架构搭建方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring的微服务框架SpringCloud受到众多公司欢迎,给大家带来一篇框架搭建入门.本次采用的版本是Spring Cloud版本为Finchley.RELEASE. 一.SpringCloud项目简介 spring cloud: 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.

  • Python学习之sys模块使用教程详解

    sys模块 与 os包一样,也是对系统资源进行调用.功能同样也是非常丰富,接下来我们会对 sys模块的一些简单且常用的函数进行介绍,主要针对一些非功能性的函数与属性来认识一些不太常见的 Python 背后的事件. sys 中的常用方法 函数名 参数 介绍 举例 返回值 modules(属性) 无 将Python启动时加载的模块集合起来并返回一个列表 sys.modules 列表 path(属性) 无 返回当前Py的环境路径(当前py环境可以导入内置.第三方包与函数的所在路径) sys.path

  • Python爬虫学习之requests的使用教程

    目录 requests库简介 requests库安装 1.pip命令安装 2.下载代码进行安装 requests库的使用 发送请求 get请求 抓取二进制数据 post请求 POST请求的文件上传 利用requests返回响应状态码 requests库简介 requests 库是一个常用的用于 http 请求的模块,它使用 python 语言编写,可以方便的对网页进行爬取,是学习 python 爬虫的较好的http请求模块. 它基于 urllib 库,但比 urllib 方便很多,能完全满足我们

  • 新手学习前端之js模仿淘宝主页网站

    先给大家展示下效果图: 图片资源链接:http://pan.baidu.com/s/1jHAdLNg 密码:5uo1 html 代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href=&quo

  • 实现基于事件通知的.Net套接字

    以前学过MFC,我用过的它里面的包装Winsock的两个类CSocket和CAsyncSocket,我一直觉得它哪个事件通知的功能比较不错,特别是在连接的两方收发数据没有一定的规律的时候比较有用,虽然不用它的事件通知也可以实现功能,但是你需要循环检测套接字的状态或者阻塞等待,如果每次都要做这些琐碎的工作岂不是很麻烦,于是我就想对这些功能作一次封装.当然在.net里面采用delegate和event是最好的选择了.下面就是我实现的一些细节: 先讲一下思路:其实这个还是很简单了,估计高手们会不屑一顾

  • C++设置事件通知线程工作的方法

    本文实例讲述了C++设置事件通知线程工作的方法,其中主线程通过将事件状态设置为"受信"来通知工作线程工作.具体实现方法如下: 复制代码 代码如下: // eventDemo.cpp : 定义控制台应用程序的入口点.  //    #include "stdafx.h"  #include <Windows.h>  #include <process.h>  HANDLE g_event;    UINT __stdcall ThreadPro

随机推荐