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<RestOut>() {});
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<Method, RpcMethodHandler> 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)]