SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现 | 您所在的位置:网站首页 › spring远程调用 › SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现 |
final String contextPath; /** *REST URL的前面部分来自于远程调用Feign接口的方法级别的注解 *如 “api/demo/hello/v1”; */ final String url; public MockRpcMethodHandler(String contextPath, String url) { this.contextPath = contextPath; this.url = url; } /** *功能:组装URL,完成REST RPC远程调用,并且返回JSON结果 *@param argv RPC方法的参数 *@return REST接口的响应结果 *@throws Throwable异常 */ @Override public Object invoke(Object[] argv) throws Throwable { /** *组装REST接口URL */ String restUrl = contextPath + MessageFormat.format(url, argv); log.info(“restUrl={}”, restUrl); /** *通过HttpClient组件调用REST接口 */ String responseData = HttpRequestUtil.simpleGet(restUrl); /** *解析REST接口的响应结果,解析成JSON对象并且返回 */ RestOut result = JsonUtil.jsonToPojo(responseData, new TypeReference() {}); return result; } } 在模拟方法处理器实现类MockRpcMethodHandler的invoke(Object[])完成了以下3个工作: (1)组装URL,将来自RPC的请求上下文路径(一般来自RPC客户端类级别注解)和远程调用的方法级别的URI路径拼接在一起,组成完整的URL路径。 (2)通过HttpClient组件(也可以是其他组件)发起HTTP请求,调用服务端的REST接口。 (3)解析REST接口的响应结果,解析成POJO对象(这里是JSON对象)并且返回。 模拟Feign的调用处理器InvocationHandler ============================== 调用处理器FeignInvocationHandler是一个相对简单的类,拥有一个非常重要的Map类型的成员dispatch,保存着RPC方法反射实例到其MethodHandler方法处理器的映射。 这里设计了一个模拟调用处理器MockInvocationHandler,用于模拟FeignInvocationHandler调用处理器,模拟调用处理器同样拥有一个Map类型的成员dispatch,负责保存RPC方法反射实例到模拟方法处理器MockRpcMethodHandler之间的映射。一个运行时MockInvocationHandler模拟调用处理器实例的dispatch成员的内存结构图如图3-7所示。 图3-7 一个运行时MockInvocationHandler的dispatch成员的内存结构 MockInvocationHandler通过Java反射扫描模拟RPC远程调用接口MockDemoClient中的每一个方法的反射注解,组装出一个对应的Map映射实例,它的key值为RPC方法的反射实例,value值为MockRpcMethodHandler方法的处理器实例。 MockInvocationHandler的源代码如下:package com.crazymaker.demo.proxy.FeignMock; //省略import class MockInvocationHandler implements InvocationHandler { /** *远程调用的分发映射:根据方法名称分发方法处理器 *key:远程调用接口的方法反射实例 *value:模拟的方法处理器实例 */ private Map dispatch; /** *功能:代理对象的创建 *@param clazz被代理的接口类型 *@return代理对象 */ public static T newInstance(Class clazz) { /** *从远程调用接口的类级别注解中获取REST地址的contextPath部分 */ Annotation controllerAnno = clazz.getAnnotation (RestController.class); if (controllerAnno == null) { return null; } String contextPath = ((RestController) controllerAnno).value(); //创建一个调用处理器实例 MockInvocationHandler invokeHandler = new MockInvocationHandler(); invokeHandler.dispatch = new LinkedHashMap(); /** *通过反射迭代远程调用接口的每一个方法,组装MockRpcMethodHandler处理器 */ for (Method method : clazz.getMethods()) { Annotation methodAnnotation = method.getAnnotation (GetMapping.class); if (methodAnnotation == null) { continue; } /** *从远程调用接口的方法级别注解中获取REST地址的URI部分 */ String uri = ((GetMapping)methodAnnotation).name(); /** *组装MockRpcMethodHandler模拟方法处理器 *注入REST地址的contextPath部分和URI部分 */ MockRpcMethodHandler handler = new MockRpcMethodHandler (contextPath, uri); /** *重点:将模拟方法处理器handler实例缓存到dispatch映射中 *key为方法反射实例,value为方法处理器 */ invokeHandler.dispatch.put(method, handler); } //创建代理对象 T proxy = (T) Proxy.newProxyInstance(clazz.getClassLoader(), new Class[]{clazz}, invokeHandler); return proxy; } /** *功能:动态代理实例的方法调用 *@param proxy 动态代理实例 *@param method 待调用的方法 *@param args 方法实参 *@return 返回值 *@throws Throwable 抛出的异常 */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (“equals”.equals(method.getName())) { Object other = args.length > 0 && args[0] != null ? args[0] : null; return equals(other); } else if (“hashCode”.equals(method.getName())) { return hashCode(); } else if (“toString”.equals(method.getName())) { return toString(); } /** *从dispatch映射中根据方法反射实例获取方法处理器 */ RpcMethodHandler rpcMethodHandler = dispatch.get(method); /** 自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。 深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。 既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化! 由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新 如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java) Java面试核心知识点笔记 其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。 Java中高级面试高频考点整理 最后分享Java进阶学习及面试必备的视频教学 一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长! 080)] Java中高级面试高频考点整理 [外链图片转存中…(img-xYUXR51V-1712766285080)] [外链图片转存中…(img-ernuYb45-1712766285080)] 最后分享Java进阶学习及面试必备的视频教学 [外链图片转存中…(img-UcgiPkxQ-1712766285080)] 一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长! [外链图片转存中…(img-Wz0KPvk6-1712766285081)] |
CopyRight 2018-2019 实验室设备网 版权所有 |