SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现 您所在的位置:网站首页 spring远程调用 SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现

SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现

2024-07-11 21:10| 来源: 网络整理| 查看: 265

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所示。

SpringCloudRPC远程调用核心原理:模拟Feign RPC动态代理的实现

图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开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。 img img img img img img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java) img

Java面试核心知识点笔记

其中囊括了JVM、锁、并发、Java反射、Spring原理、微服务、Zookeeper、数据库、数据结构等大量知识点。

蚂蚁金服(Java研发岗),26岁小伙斩获三面,收获Offer定级P6

Java中高级面试高频考点整理

蚂蚁金服(Java研发岗),26岁小伙斩获三面,收获Offer定级P6

蚂蚁金服(Java研发岗),26岁小伙斩获三面,收获Offer定级P6

最后分享Java进阶学习及面试必备的视频教学

蚂蚁金服(Java研发岗),26岁小伙斩获三面,收获Offer定级P6

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长! img

080)]

Java中高级面试高频考点整理

[外链图片转存中…(img-xYUXR51V-1712766285080)]

[外链图片转存中…(img-ernuYb45-1712766285080)]

最后分享Java进阶学习及面试必备的视频教学

[外链图片转存中…(img-UcgiPkxQ-1712766285080)]

一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长! [外链图片转存中…(img-Wz0KPvk6-1712766285081)]



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有