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

news/2024/7/14 19:22:27/文章来源:https://blog.csdn.net/Apandam/article/details/139244084

在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.luyixian.cn/news_show_1052116.aspx

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

相关文章

黑白按键-第13届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第67讲。 黑白按键&#xf…

酷黑简洁大气体育直播自适应模板赛事直播门户网站源码

源码名称&#xff1a;酷黑简洁大气体育直播自适应模板赛事直播门户网站源码 开发环境&#xff1a;帝国cms 7.5 安装环境&#xff1a;phpmysql 支持PC与手机端同步生成html&#xff08;多端同步生成插件&#xff09; 带软件采集&#xff0c;可以挂着自动采集发布&#xff0c;无…

安装HAP时提示“code:9568344 error: install parse profile prop check error”错误

问题现象 在启动调试或运行应用/服务时&#xff0c;安装HAP出现错误&#xff0c;提示“error: install parse profile prop check error”错误信息。 解决措施 该问题可能是由于应用使用了应用特权&#xff0c;但应用的签名文件发生变化后未将新的签名指纹重新配置到设备的特…

网络攻防概述(基础概念)

文章目录 APTAPT概念APT攻击过程 网络空间与网络空间安全网络空间(Cyberspace)网络空间安全(Cyberspace Security) 网络安全属性机密性(Confidentiality或Security)完整性(Integrity)可用性&#xff08;Availability&#xff09;不可否认性&#xff08;Non-repudiation&#xf…

基于51单片机的函数发生器设计

一.硬件方案 此函数信号发生器是基于单片机AT89C51设计而成的&#xff0c;能够产生频率范围在0Hz—535Hz的锯齿波、正弦波、三角波、矩形波四种波形&#xff0c;并且能够通过液晶屏1602显示各自的波形类型以及频率数值。电路主要由51单片机最小系统DA0832模数转换模块运放模块…

山东大学软件学院项目实训-创新实训-基于大模型的旅游平台(十六)- JUC(2)

目录 同步 两阶段终止模式 守护线程 线程状态 五种(操作系统角度) 六种(Java API角度) 烧水案例 共享模型之管程 临界区 竞态条件 同步 Slf4j(topic "c.TestJoin")public class TestJoin {static int r 0;static int r1 0;static int r2 0;​public sta…

【Linux】centos7下载安装Python3.10,下载安装openssl1.1.1

目录 centos7下载安装Python&#xff08;版本3.10.14&#xff09; &#xff08;1&#xff09;网页下载python压缩包&#xff0c;并解压缩 &#xff08;2&#xff09;编译安装 Python在make altinstall时&#xff0c;报错及解决 &#xff08;3&#xff09;将安装目录和可执…

C数据结构:二叉树

目录 二叉树的数据结构 前序遍历 中序遍历 后序遍历 二叉树的创建 二叉树的销毁 二叉树的节点个数 二叉树叶子节点个数 二叉树第K层节点个数 二叉树的查找 层序遍历 判断二叉树是否为完全二叉树 完整代码 二叉树的数据结构 typedef char BTDataType; typedef str…

【STL简单源码剖析】vector的实现

收灯庭院迟迟月 落索秋千翦翦风 目录 vector 简单概述 vector 代码摘要 vector 的迭代器 vector 成员变量 vector 构造析构 获取当前元素个数 获取当前容器容量 operator[]的运算符重载 vector 空间预留 push_back() 的实现 迭代器失效的简单讲解 pop_back() 的实现 insert…

驾考学法减分拍照搜题模拟考试小程序开发

驾考学法减分拍照搜题模拟考试小程序开发 项目介绍 驾考搜题&#xff0c;一款专为驾考学员设计的智能搜题助手&#xff0c;集合了海量题库与实战模拟&#xff0c;助力学员快速掌握驾考知识&#xff0c;轻松应对各类考试。 主要功能特点 智能搜题 通过关键词、拍照搜索&#xf…

【程序员如何送外卖】

嘿&#xff0c;咱程序员要在美团送外卖&#xff0c;那还真有一番说道呢。 先说说优势哈&#xff0c;咱程序员那逻辑思维可不是盖的&#xff0c;规划送餐路线什么的&#xff0c;简直小菜一碟。就像敲代码找最优解一样&#xff0c;能迅速算出怎么送最省时间最有效率。而且咱平时…

win10/win11 优先调用大核的电源计划性能设置

前言 大小核&#xff0c;即Intel 12代开始的P-core&#xff08;性能核&#xff0c;一般叫大核&#xff09;和E-core&#xff08;能效核&#xff0c;一般叫小核&#xff09;异核架构。说下个人理解&#xff0c;就是英特尔为了增加cpu性能&#xff0c;但是又因为架构和功耗的限制…

C++

定义自己的命名空间my_sapce&#xff0c;在my_sapce中定义string类型的变量s1&#xff0c;再定义一个函数完成对字符串的逆置。

YOLOv8+PyQt5面部表情检测系统完整资源集合(yolov8模型,从图像、视频和摄像头三种路径识别检测,包含登陆页面、注册页面和检测页面)

1.资源包含可视化的面部表情检测系统&#xff0c;基于最新的YOLOv8训练的面部表情检测模型&#xff0c;和基于PyQt5制作的可视化面部表情检测系统&#xff0c;包含登陆页面、注册页面和检测页面&#xff0c;该系统可自动检测和识别图片或视频当中出现的八类面部表情&#xff1a…

机器人系统ros2-开发学习实践15-模拟用 URDF 建模 步行机器人行走示例

目标&#xff1a; 本教程将向您展示如何建模行走机器人、将状态发布为tf2消息并在 Rviz 中查看模拟。首先&#xff0c;我们创建描述机器人组件的 URDF 模型。接下来&#xff0c;我们编写一个节点来模拟运动并发布 JointState 和变换。然后我们使用robot_state_publisher将整个…

STM32H743+USBHID+CubeMX配置

一、环境准备 电脑系统&#xff1a;Windows 10 专业版 20H2 IDE&#xff1a;Keil v5.35、STM32CubeMX v6.5.0 测试硬件&#xff1a;正点原子阿波罗STM32H743 二、测试步骤 1、使用用例工程 配置STM32H743定时器功能-CSDN博客https://blog.csdn.net/horse_2007s/article/d…

如何在Mac上恢复未保存的Excel文件

您是否不小心关闭了 Excel&#xff0c;而没有将工作保存在 Mac 上&#xff1f;不要惊慌&#xff01;本指南概述了帮助您在 Mac 上恢复未保存的 Excel 文件的简单方法。 由于断电、系统崩溃或关闭它而不保存而意外丢失您的 Excel 文件可能会造成挫败感&#xff0c;因为您可能在…

vue 引入 emoji 表情包

vue 引入 emoji 表情包 一、安装二、组件内使用 一、安装 npm install --save emoji-mart-vue二、组件内使用 import { Picker } from "emoji-mart-vue"; //引入组件<picker :include"[people,Smileys]" :showSearch"false" :showPreview&q…

利用ArcGIS Python批量拼接遥感影像(arcpy batch processing)

本篇文章将说明如何利用ArcGIS 10.1自带的Python IDLE进行遥感影像的批量拼接与裁剪。 1.运行环境&#xff1a;ArcGIS10.1 (安装传送门)、Python IDLE 2.数据来源&#xff1a;地理空间数据云 GDEMV2 30M分辨率数字高程数据 3.解决问题&#xff1a;制作山西省的DEM影像 如下…

小白不知道怎么投稿?记住这个好方法

作为一名单位信息宣传员,我最初踏上这条道路时,满心憧憬着通过文字传递我们单位的精彩瞬间,让社会听见我们的声音。然而,理想与现实之间的距离,却在一次次邮箱投稿的石沉大海中渐渐清晰。那时的我,像所有“小白”一样,以为只要用心撰写稿件,通过电子邮件发给各大媒体,就能收获满…