dubbo新手学习之事件通知实践教程
前言
今天主要给大家分享一下dubbo的事件通知机制。
先看下dubbo中文官网的示例解释:事件通知。
在调用之前、调用之后、出现异常时,会触发oninvoke、onreturn、onthrow三个事件,可以配置当事件发生时,通知哪个类的哪个方法.
实践
溪源目的是快速学习dubbo的相关机制,故定义的相同的接口和方法,采用分包的方式解耦合,便于后期维护。
先看服务接口
dubbo-demo-interface
目录如图
/** *@authorwx *@date2020/9/81:44下午 *测试事件通知 */ publicinterfaceUserNotifyService{ /** *获取用户名字 *@paramuserId *@return */ StringgetUserName(StringuserId); }
定义一个新的配置文件,用于配置事件通知相关bean。
UserNotifyServiceImpl
/** *@authorwx *@date2020/9/81:46下午 */ @Service publicclassUserNotifyServiceImplimplementsUserNotifyService{ privatestaticfinalStringUSER_ID="1503892"; @Override publicStringgetUserName(StringuserId){ if(StringUtils.isBlank(userId)){ thrownewRpcException("userIdisnull"); } returnUSER_ID.equals(userId)?"溪~源":""; } }
ProviderApplication
/** *事件通知 *@throwsIOException */ privatestaticvoidnotifyTest()throwsIOException{ ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("spring/notify-provider.xml"); context.start(); System.in.read(); }
dubbo-demo-xml-consumer目录如下
扩展点
1.oninvoke方法:
必须具有与真实的被调用方法sayHello相同的入参列表:例如,oninvoke(Stringname)
2.onreturn方法:
2.1至少要有一个入参且第一个入参必须与getUserName的返回类型相同,接收返回结果:例如,onReturnWithoutParam(Stringresult);
2.2可以有多个参数,多个参数的情况下,第一个后边的所有参数都是用来接收getUserName入参的:例如,onreturn(Stringresult,Stringname)
3.onthrow方法:
3.1至少要有一个入参且第一个入参类型为Throwable或其子类,接收返回结果;例如,onthrow(Throwableex);
3.2可以有多个参数,多个参数的情况下,第一个后边的所有参数都是用来接收getUserName入参的:例如,onthrow(Throwableex,Stringname);
4.如果是consumer在调用provider的过程中,出现异常时不会走onthrow方法的,onthrow方法只会在provider返回的RpcResult中含有Exception对象时,才会执行。(dubbo中下层服务的Exception会被放在响应RpcResult的exception对象中传递给上层服务)
对于上面的解释,大家可能会存在疑惑,部分方法要求第一个参数为服务接口的返回值类型???约定大于配置???揭开迷底的方法就是debug源码设计实现逻辑~
源代码:
/** *@authorwx *@date2020/9/81:53下午 */ publicinterfaceConsumerNotifyService{ /** *调用之前 *@paramname */ voidonInvoke(Stringname); /** *无参数:调用之后 *@paramresult参数用于接收[事件通知]服务接口的方法返回值类型保持一致 */ voidonReturnWithoutParam(Stringresult); /** *有参数:调用之后 *@paramresult第一个参数接收[事件通知]服务接口的方法返回值类型保持一致 *@paramname第二个或者之后,与[事件通知]服务接口的方法入参保持一致 */ voidonReturn(Stringresult,Stringname); /** *抛异常 *@paramex *@paramname */ voidonThrow(Throwableex,Stringname); }
ConsumerNotifyServiceImpl
/** *@authorwx *@date2020/9/81:59下午 */ @Service publicclassConsumerNotifyServiceImplimplementsConsumerNotifyService{ @Override publicvoidonInvoke(Stringname){ System.out.println("[事件通知]执行onInvoke方法,参数:"+name); } @Override publicvoidonReturnWithoutParam(Stringresult){ System.out.println("[事件通知]执行onReturnWithoutParam方法,返回结果:"+result); } @Override publicvoidonReturn(Stringresult,Stringname){ System.out.println("[事件通知]执行onReturn方法,参数:"+name+",返回结果:"+result); } @Override publicvoidonThrow(Throwableex,Stringname){ System.out.println("[事件通知]执行onThrow方法,参数:"+name+",异常信息:"+ex.getMessage()); } }
notify-consumer.xml
同理,消费者端也新建notify-consumer.xml文件,具体配置如图:
ConsumerApplication
privatestaticvoidnotifyTest(){ ClassPathXmlApplicationContextcontext=newClassPathXmlApplicationContext("spring/notify-consumer.xml"); UserNotifyServicenotifyService=context.getBean(UserNotifyService.class); StringuserName=notifyService.getUserName("1503892"); System.out.println(userName); }
运行
分别启动生产者和消费者,运行结果如图:
分别执行了onInvoke方法和onReturn方法
源码
关于dubbo的事件通知机制,源码实现基本上位于FutureFilter类中,先给大家贴一下类方法目录:
privatevoidfireReturnCallback(finalInvoker>invoker,finalInvocationinvocation,finalObjectresult){ ....//省略部分代码 Object[]params; //获取方法参数类型 Class>[]rParaTypes=onReturnMethod.getParameterTypes(); if(rParaTypes.length>1){ //两个参数:第一个参数与真实方法getUserName方法返回结果类型相同,第二个接收所有的真实请求参数 if(rParaTypes.length==2&&rParaTypes[1].isAssignableFrom(Object[].class)){ params=newObject[2]; //真实方法的返回结果 params[0]=result; //执行方法入参 params[1]=args; }else{ //多个参数:第一个参数与真实方法getUserName结果类型相同,后边几个接收所有的真实请求参数 params=newObject[args.length+1]; params[0]=result; System.arraycopy(args,0,params,1,args.length); } }else{ //只有一个参数:接收返回执行结果 params=newObject[]{result}; } try{ onReturnMethod.invoke(onReturnInst,params); }catch(InvocationTargetExceptione){ fireThrowCallback(invoker,invocation,e.getTargetException()); }catch(Throwablee){ fireThrowCallback(invoker,invocation,e); } }
溪源初次接触dubbo本地存根机制,如文中存在错误之处,希望大家及时指正!
源码传送门:https://github.com/stream-source/dubbo/tree/master/dubbo-demo
总结
到此这篇关于dubbo新手学习之事件通知实践教程的文章就介绍到这了,更多相关dubbo事件通知内容请搜索毛票票以前的文章或继续浏览下面的相关文章希望大家以后多多支持毛票票!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。