当前位置: 首页 > news >正文

【OpenFeign】【源码+图解】【六】创建FeignClient接口的代理(下)

【OpenFeign】【源码+图解】【五】创建FeignClient接口的代理(上)

目录

    • 6.2 RequestTemplate.Factory
    • 6.3 创建SynchronousMethodHandler
    • 6.4 创建FeignInvocationHandler
  • 7. FeignInvocationHandler处理HTTP请求

6.2 RequestTemplate.Factory

先看下类图

在这里插入图片描述

从类图中可以看出RequestTemplate.Factory的作用主要是创建RequestTemplate的,再看看源码如何创建RequestTemplate.Factory

static final class ParseHandlersByName {
    public Map<String, MethodHandler> apply(Target target) {
        List<MethodMetadata> metadata = contract.parseAndValidateMetadata(target.type());
        Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();
        for (MethodMetadata md : metadata) {
            BuildTemplateByResolvingArgs buildTemplate;
            // 2、创建RequestTemplate.Factory
            if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
                // 没有@PathVariable、@RequestPart且非DeclarativeContract
                buildTemplate =
                    new BuildFormEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
            } else if (md.bodyIndex() != null || md.alwaysEncodeBody()) {
                // 满足以下情况:
                //  1、 参数类型不是URI, Request.Options类型
                //  2、 没有@RequestHeader, @RequestParam, @RequestPart, @SpringQueryMap, @CookieValue, @MatrixVariable, @PathVariable
                //  3、 使用的Contract不是AlwaysEncodeBodyContract类
                buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder, queryMapEncoder, target);
            } else {
                // 默认
                buildTemplate = new BuildTemplateByResolvingArgs(md, queryMapEncoder, target);
            }
            ......
        }
        return result;
    }
}

6.3 创建SynchronousMethodHandler

static final class ParseHandlersByName {
    public Map<String, MethodHandler> apply(Target target) {
        List<MethodMetadata> metadata = contract.parseAndValidateMetadata(target.type());
        Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();
        for (MethodMetadata md : metadata) {
            // ......
                result.put(md.configKey(),
                           // 创建SynchronousMethodHandler
                           factory.create(target, md(6.1), buildTemplate(6.2), options, decoder, errorDecoder));
        }
        return result;
    }
}

static class Factory {
    public MethodHandler create(Target<?> target,
                                MethodMetadata md,
                                RequestTemplate.Factory buildTemplateFromArgs,
                                Options options,
                                Decoder decoder,
                                ErrorDecoder errorDecoder) {
        // 只是简单赋值,不再详细探究。其作用见后文
        return new SynchronousMethodHandler(target, client, retryer, requestInterceptors,
                                            responseInterceptor, logger, logLevel, md, buildTemplateFromArgs, options, decoder,
                                            errorDecoder, dismiss404, closeAfterDecode, propagationPolicy, forceDecoding);
    }
}

6.4 创建FeignInvocationHandler

public class ReflectiveFeign extends Feign {
    @Override
  public <T> T newInstance(Target<T> target) {
    ......
    // factory为InvocationHandlerFactory.Default
    InvocationHandler handler = factory.create(target, methodToHandler);
    ......
    return proxy;
  }
}

static final class Default implements InvocationHandlerFactory {

    @Override
    public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
        // 创建类型为FeignInvocationHandler的InvocationHandler
        return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
    }
}

FeignInvocationHandler创建好后,当http请求进来时会由其invoke方法处理。

7. FeignInvocationHandler处理HTTP请求

前面四个步骤都是创建FeignClient的代理,代理创建好后就可以使用了,当发起请求时代理接受到请求并交由FeignInvocationHandler处理

FeignInvocationHandler.invoke(…)

static class FeignInvocationHandler implements InvocationHandler {
      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
          ......
          // dispatch.get(method)获取method对应的处理器SynchronousMethodHandler
          // invoke(args):调用SynchronousMethodHandler.invoke(args)
          return dispatch.get(method).invoke(args);
      }
}

下一节再讲SynchronousMethodHandler是如何处理请求的。

相关文章:

  • Minecraft(我的世界) Fabric 1.19.3 服务器搭建教程
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • 汽车OTA概述
  • 基于Java+Swing+mysql餐厅点餐管理系统
  • 店铺如何快速实现数字化管理?不妨参考一下管理系统
  • 修改后的代码只进行了git add操作不小心给他恢复了怎么找回来
  • JUC(一):线程池
  • org.springframework.jdbc.BadSqlGrammarException: Error updating database
  • 熟人服务器被黑,五种实战方法强化linux服务器安全性!
  • RabbitMQ总结
  • 【每日一题Day67】LC1739放置盒子 | 找规律+贪心 二分查找
  • 【Linux】Linux项目自动化构建工具——make/Makefile
  • <Linux线程同步>——《Linux》
  • 【Array数组】面试前基础知识点深度记忆总结
  • 20221226编译Toybrick的TB-RK3588X开发板的Android12系统1-编译环境配置
  • 002-读书笔记-JavaScript高级程序设计 在HTML中使用JavaScript
  • electron原来这么简单----打包你的react、VUE桌面应用程序
  • Golang-长连接-状态推送
  • open-falcon 开发笔记(一):从零开始搭建虚拟服务器和监测环境
  • PHP那些事儿
  • Redash本地开发环境搭建
  • tweak 支持第三方库
  • vue 配置sass、scss全局变量
  • vuex 学习笔记 01
  • yii2权限控制rbac之rule详细讲解
  • 测试开发系类之接口自动化测试
  • 入门到放弃node系列之Hello Word篇
  • 探索 JS 中的模块化
  • 腾讯优测优分享 | 你是否体验过Android手机插入耳机后仍外放的尴尬?
  • 这几个编码小技巧将令你 PHP 代码更加简洁
  • zabbix3.2监控linux磁盘IO
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​LeetCode解法汇总1410. HTML 实体解析器
  • !$boo在php中什么意思,php前戏
  • #HarmonyOS:Web组件的使用
  • (70min)字节暑假实习二面(已挂)
  • (二)fiber的基本认识
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (力扣)循环队列的实现与详解(C语言)
  • (转)EOS中账户、钱包和密钥的关系
  • (转)nsfocus-绿盟科技笔试题目
  • *++p:p先自+,然后*p,最终为3 ++*p:先*p,即arr[0]=1,然后再++,最终为2 *p++:值为arr[0],即1,该语句执行完毕后,p指向arr[1]
  • *ST京蓝入股力合节能 着力绿色智慧城市服务
  • .dat文件写入byte类型数组_用Python从Abaqus导出txt、dat数据
  • .md即markdown文件的基本常用编写语法
  • .net core 6 集成 elasticsearch 并 使用分词器
  • .net web项目 调用webService
  • .Net Winform开发笔记(一)
  • .net 验证控件和javaScript的冲突问题
  • .net程序集学习心得
  • @ComponentScan比较
  • @Resource和@Autowired的区别
  • [\u4e00-\u9fa5] //匹配中文字符
  • [ACL2022] Text Smoothing: 一种在文本分类任务上的数据增强方法
  • [bug总结]: Feign调用GET请求找不到请求体实体类