Spring-Cloud-OpenFeign源码解析-04-调用流程分析

在Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean分析到,通过@Autowired或者@Resource注入FeignClient实例的时候,实际上返回的是JDK动态代理对象,具体的实现逻辑在InvocationHandler的invoke方法中

回看ReflectiveFeign.newInstance()方法

public <T> T newInstance(Target<T> target) {//返回的是feign接口方法名和MethodHandler的对应mapMap<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);//存放feign接口方法和MethodHandler的对应mapMap<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();for (Method method : target.type().getMethods()) {if (method.getDeclaringClass() == Object.class) {continue;} else if (Util.isDefault(method)) {DefaultMethodHandler handler = new DefaultMethodHandler(method);defaultMethodHandlers.add(handler);methodToHandler.put(method, handler);} else {//key是方法,value是从nameToHandler取出来的MethodHandlermethodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));}}//这里创建的是FeignInvocationHandlerInvocationHandler handler = factory.create(target, methodToHandler);T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),new Class<?>[] {target.type()}, handler);for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {defaultMethodHandler.bindTo(proxy);}return proxy;}

targetToHandlersByName#apply()

public Map<String, MethodHandler> apply(Target target) {//拿到feign接口的所有属性集合List<MethodMetadata> metadata = contract.parseAndValidateMetadata(target.type());Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();for (MethodMetadata md : metadata) {......if (md.isIgnored()) {result.put(md.configKey(), args -> {throw new IllegalStateException(md.configKey() + " is not a method handled by feign");});} else {//key--TestFeign#test(),value--SynchronousMethodHandler对象result.put(md.configKey(),factory.create(target, md, buildTemplate, options, decoder, errorDecoder));}}return result;}}

在这里插入图片描述
在这里插入图片描述

FeignInvocationHandler#invoke()

  static class FeignInvocationHandler implements InvocationHandler {private final Target target;private final Map<Method, MethodHandler> dispatch;FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {this.target = checkNotNull(target, "target");this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if ("equals".equals(method.getName())) {try {Object otherHandler =args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;return equals(otherHandler);} catch (IllegalArgumentException e) {return false;}} else if ("hashCode".equals(method.getName())) {return hashCode();} else if ("toString".equals(method.getName())) {return toString();}//dispatch就是之前说到的methodToHandler的map集合	//这里通过method得到MethodHandler实际是SynchronousMethodHandler,再调用invoke方法return dispatch.get(method).invoke(args);}}

SynchronousMethodHandler#invoke()

  public Object invoke(Object[] argv) throws Throwable {//构建RequestTemplate对象,处理HTTP请求RequestTemplate template = buildTemplateFromArgs.create(argv);Options options = findOptions(argv);//创建重试对象RetryerRetryer retryer = this.retryer.clone();//循环重试调用while (true) {try {//实际调用方法return executeAndDecode(template, options);} catch (RetryableException e) {try {//处理重试retryer.continueOrPropagate(e);} catch (RetryableException th) {Throwable cause = th.getCause();if (propagationPolicy == UNWRAP && cause != null) {throw cause;} else {throw th;}}if (logLevel != Logger.Level.NONE) {logger.logRetry(metadata.configKey(), logLevel);}continue;}}}

SynchronousMethodHandler#executeAndDecode()

Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {Request request = targetRequest(template);Response response;long start = System.nanoTime();try {//实际调用execute方法执行调用请求response = client.execute(request, options);// ensure the request is set. TODO: remove in Feign 12response = response.toBuilder().request(request).requestTemplate(template).build();} catch (IOException e) {if (logLevel != Logger.Level.NONE) {logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));}throw errorExecuting(request, e);}}

调用execute方法时会通过FeignBlockingLoadBalancerClient完成负载均衡,找到对应的服务器,最后底层默认通过HttpURLConnection发起调用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/843684.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI大模型日报#0528:Greg专访 | 为什么OpenAI最先做出GPT-4、xAI获60亿美元融资、李飞飞经典对话Hinton

导读&#xff1a;AI大模型日报&#xff0c;爬虫LLM自动生成&#xff0c;一文览尽每日AI大模型要点资讯&#xff01;目前采用“文心一言”&#xff08;ERNIE 4.0&#xff09;、“零一万物”&#xff08;Yi-34B&#xff09;生成了今日要点以及每条资讯的摘要。欢迎阅读&#xff0…

YOLOv8/YOLOv7/YOLOv5+CRNN-车牌识别、车牌关键点定位、车牌检测(毕业设计)

目录 一、前言1、项目介绍2、图片测试效果展示 二、项目环境配置1、pytorch安装&#xff08;gpu版本和cpu版本的安装)2、pycocotools的安装3、其他包的安装 三、yolov8/yolov7/yolov5CRNN-中文车牌识别、车牌关键点定位、车牌检测算法1、yolov8算法介绍2、CRNN算法介绍3、算法流…

【加密与解密(第四版)】第十三章笔记

第十三章 HOOK技术 13.1 Hook概述 IAT HOOK&#xff08;改地址&#xff09; BOOL IAT_InstallHook(){BOOL bResult FALSE ;HMODULE hCurExe GetModuleHandle(NULL);PULONG_PTR pt ;ULONG_PTR OrginalAddr;bResult InstallModuleIATHook(hCurExe,"user32.dll",&qu…

韩顺平0基础学Java——第13天

p264-p284 安装IDEA&#xff0c;熟悉一下软件。 尴尬了&#xff0c;难道是这个版本的idea不支持jdk17&#xff0c;难受住了 成功了&#xff0c;顺便跑一下昨天的作业&#xff1a; 这都要跑2秒&#xff1f;是电脑的问题还是谁的问题&#xff1f;控制台里跑的好快的哦 设置id…

Thingsboard规则链:Message type switch节点详解

在物联网解决方案中&#xff0c;数据的高效处理与自动化决策流程是实现智能化管理的基础。Thingsboard&#xff0c;作为一个强大的开源物联网平台&#xff0c;通过其规则引擎为用户提供了一系列灵活的节点来定制复杂的业务逻辑。其中&#xff0c;Message Type Switch节点是构建…

BookxNote Pro 宝藏 PDF 笔记软件

一、简介 1、BookxNote Pro 是一款专为电子书阅读和学习笔记设计的软件&#xff0c;支持多种电子书格式&#xff0c;如PDF和EPUB&#xff0c;能够帮助用户高效地管理和阅读电子书籍&#xff0c;同时具备强大的笔记功能&#xff0c;允许用户对书籍内容进行标注、摘录和思维导图绘…

Springboot启动时报错Property ‘mapperLocations‘ was not specified.

这几天没整boot 晚上直接运行不了了 本想是在表现层写点代码测测接口的 localhost8080找半天 结果404 先考虑好久 是不是url输入错了 然后 就发现 结果boot都不能启动了 JUnit也测不出来 找了半天 结果是开关机导致数据库没开 手动打开服务 找到MySQL启动 IDEA连接数据…

ssm/springoot养老院问诊服务预约系统_96316老年人服务系统

2.管理员&#xff1a; &#xff08;1&#xff09;登入注册页面&#xff1a;管理员进行操作时需要是已注册登入的 &#xff08;2&#xff09;权限管理&#xff1a;管理员登入后可以运用权限进行相应的操作管理。 &#xff08;3&#xff09;用户管理&#xff1a;对用户进行删除、…

国产数据库替代加速 助力数字中国建设

5月24日&#xff0c;随着第七届数字中国建设峰会在福州的成功举办&#xff0c;释放数据要素价值、发展新质生产力成为当下热议的话题。 数据作为新型生产要素&#xff0c;是数字化、网络化、智能化的重要基础。北京人大金仓信息技术股份有限公司&#xff08;以下简称人大金仓&a…

OpenHarmony实战开发——宿舍全屋智能开发指南

项目说明 基于OpenAtom OpenHarmony&#xff08;以下简称“OpenHarmony”&#xff09;、数字管家开发宿舍全屋智能&#xff0c;实现碰一碰开门、碰一碰开灯、碰一碰开风扇以及烟感检测。因为各项目开发流程大体相似&#xff0c;本文主要以碰一碰开门为例介绍如何在现有OpenHar…

西储大学数据集学习

数据集下载地址&#xff1a;CWRU凯斯西储大学轴承数据数据集——附&#xff1a;下载链接_西储大学轴承数据集下载-CSDN博客 最近研究故障诊断&#xff0c;先对使用比较多的西储大学数据集研究。以资料【1】中的内容展开研究。 1、轴承的结构 轴承分为外圈、内圈、保持架和滚珠…

CC工具箱使用指南:【Word特定文本批量替换(BHM)】

一、简介 群友定制工具。 工具所要做的是批量更新Word模板中的特定文本。 输入参数为一个Word模板和Excel更新数据。 Word模板长这样&#xff1a; Word中需要更新的文本都用大括号及里内部的标签标注出来。 对应的Excel长这样&#xff1a; 第一行的标签和Word里的一一对应…

mysql 按区间统计 3 分钟维度

根据 UNIX_TIMESTAMP 去掉分钟后的的位数 思路如下select UNIX_TIMESTAMP(now()) 当前时间 秒,now() 当前时间,FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(CURRENT_TIMESTAMP) / (3 * 60)) * (3 * 60)) 3分钟为分隔去掉多余位数当前时间 秒 当前时间 3分钟为分隔去掉多余…

【招聘】易基因科技诚聘销售总监 虚位以待

&#x1f680; 关于我们 易基因拥有一支充满活力的科研服务团队&#xff0c;致力于以“引领表观遗传学科学研究与临床应用”为愿景&#xff0c;依托高通量测序技术和云数据分析平台&#xff0c;为医疗机构、科研机构、企事业单位等提供以表观遗传学技术为核心的多组学科研服务…

翻译《The Old New Thing》- What did MakeProcInstance do?

What did MakeProcInstance do? - The Old New Thing (microsoft.com)https://devblogs.microsoft.com/oldnewthing/20080207-00/?p23533 Raymond Chen 2008年02月07日 MakeProcInstance 做了什么&#xff1f; MakeProcInstance 宏实际上什么也不做。 #define MakeProcInst…

教师岗位等级划分标准

教师岗位等级的划分是否真的能够全面反映教师的专业能力和教学效果&#xff1f;晋升机制是否公正合理&#xff0c;能否真正激励教师持续进步&#xff1f; 教师岗位等级&#xff0c;其实就是对教师专业技能和教学经验的一种评价和激励。教师的岗位等级一般分为12个级别&#xff…

关于Profinet远程IO模块的超详细讲解

什么是Profinet远程IO模块 Profinet是新一代基于工业以太网技术的自动化总线标准&#xff0c;它为自动化通信领域提供了一个完整的网络解决方案&#xff0c;用于连接远程输入输出&#xff08;IO&#xff09;设备到Profinet网络。它可以通过以太网进行通信&#xff0c;并支持实…

I.MX6ULL主频和时钟配置实验

系列文章目录 I.MX6ULL主频和时钟配置实验 I.MX6ULL主频和时钟配置实验 系列文章目录一、前言二、I.MX6U 时钟系统详解三、硬件原理四、 7 路 PLL 时钟源五、时钟树简介六、内核时钟设置七、PFD 时钟设置八、AHB、IPG 和 PERCLK 根时钟设置九、实验程序编写十、编译下载10.1编写…

Java常用工具类、包装类

1、工具类的设计 一般地&#xff0c;把那些完成通用功能的方法分类存放到类中&#xff0c;这些类就叫工具类。 工具类起名&#xff1a;XxxUtil、XxxUtils、XxxTool、XxxTools等&#xff0c;其中Xxx表示一类事物&#xff0c;比如ArrayUtil、StringUtil、JdbcUtil。 工具类存放的…

JAVA GUI之自定义窗口

Java Gui的自定义窗口可以通过继承JFrame类来实现。下面是一个简单的例子来介绍如何创建一个自定义的Java Gui窗口: 导入必要的类库; 创建一个继承JFrame类的子类; 在子类的构造方法中设置窗口的属性;可以向窗口中添加组件&#xff0c;如按钮、标签等;最后&#xff0c;创建一个…