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事件通知内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • java从命令行获取数据的三种方式代码实例

    java从命令行获取数据的三种方式代码实例

    这篇文章主要介绍了java从命令行获取数据的三种方式代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-12-12
  • SpringMVC使用第三方组件实现文件上传

    SpringMVC使用第三方组件实现文件上传

    这篇文章主要介绍了SpringMVC使用第三方组件实现文件上传,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-08-08
  • Java Swing组件单选框JRadioButton用法示例

    Java Swing组件单选框JRadioButton用法示例

    这篇文章主要介绍了Java Swing组件单选框JRadioButton用法,结合具体实例形式分析了Swing单选框JRadioButton的使用方法及相关操作注意事项,需要的朋友可以参考下
    2017-11-11
  • SpringBoot 集成Kaptcha实现验证码功能实例详解

    SpringBoot 集成Kaptcha实现验证码功能实例详解

    在一个web应用中验证码是一个常见的元素。今天给大家介绍一下kaptcha的和springboot一起使用的简单例子。感兴趣的朋友参考下吧
    2017-08-08
  • 微信开发之使用java获取签名signature

    微信开发之使用java获取签名signature

    这篇文章主要为大家详细介绍了微信开发之使用java获取签名signature,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • Java this、final等关键字总结

    Java this、final等关键字总结

    这篇文章主要对java中this、final等关键字进行了总结,需要的朋友可以参考下
    2017-04-04
  • jfreechart画折线图的方法

    jfreechart画折线图的方法

    这篇文章主要为大家详细介绍了jfreechart画折线图的方法,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-06-06
  • java控制台输出图书馆管理系统

    java控制台输出图书馆管理系统

    这篇文章主要为大家详细介绍了java控制台输出图书馆管理系统,只用java代码不用数据库和GUI等,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-10-10
  • Java数据库连接PreparedStatement的使用详解

    Java数据库连接PreparedStatement的使用详解

    这篇文章主要介绍了Java数据库连接PreparedStatement的使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-08-08
  • Java Bigdecimal使用原理详解

    Java Bigdecimal使用原理详解

    这篇文章主要介绍了Java Bigdecimal使用原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03

最新评论