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

 更新时间:2020年09月14日 09:28:59   作者:溪~源  
这篇文章主要给大家介绍了关于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事件通知内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 基于strict-origin-when-cross-origin问题的解决

    基于strict-origin-when-cross-origin问题的解决

    这篇文章主要介绍了基于strict-origin-when-cross-origin问题的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • Java 生成随机单据号的实现示例

    Java 生成随机单据号的实现示例

    本文主要介绍了Java 生成随机单据号的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-09-09
  • kaptcha验证码使用方法详解

    kaptcha验证码使用方法详解

    这篇文章主要为大家详细介绍了kaptcha验证码的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • Spring JPA之save方法示例详解

    Spring JPA之save方法示例详解

    这篇文章主要为大家介绍了Spring JPA之save方法示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • Java操作excel的三种常见方法实例

    Java操作excel的三种常见方法实例

    这篇文章主要给大家介绍了关于Java操作excel的三种常见方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • spring schedule实现动态配置执行时间

    spring schedule实现动态配置执行时间

    这篇文章主要介绍了spring schedule实现动态配置执行时间,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-11-11
  • Mybatis pagehelper分页插件使用过程解析

    Mybatis pagehelper分页插件使用过程解析

    这篇文章主要介绍了mybatis pagehelper分页插件使用过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-02-02
  • Java正则匹配中文的方法实例分析

    Java正则匹配中文的方法实例分析

    这篇文章主要介绍了Java正则匹配中文的方法,结合实例形式分析了Java针对中文、标点及引号等匹配操作相关技巧,需要的朋友可以参考下
    2017-03-03
  • maven如何打包动态环境变量(包括启动脚本)

    maven如何打包动态环境变量(包括启动脚本)

    这篇文章主要介绍了maven如何打包动态环境变量(包括启动脚本)问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04
  • 剑指Offer之Java算法习题精讲数组与字符串

    剑指Offer之Java算法习题精讲数组与字符串

    跟着思路走,之后从简单题入手,反复去看,做过之后可能会忘记,之后再做一次,记不住就反复做,反复寻求思路和规律,慢慢积累就会发现质的变化
    2022-03-03

最新评论