abstract class BaseContract implements Contract {
List<MethodMetadata> parseAndValidatateMetadata(Class<?> var1);
@Override
public List<MethodMetadata> parseAndValidatateMetadata(Class<?> targetType) {checkState(targetType.getTypeParameters().length == 0, "Parameterized types unsupported: %s",targetType.getSimpleName());checkState(targetType.getInterfaces().length <= 1, "Only single inheritance supported: %s",targetType.getSimpleName());if (targetType.getInterfaces().length == 1) {checkState(targetType.getInterfaces()[0].getInterfaces().length == 0,"Only single-level inheritance supported: %s",targetType.getSimpleName());}Map<String, MethodMetadata> result = new LinkedHashMap<String, MethodMetadata>();for (Method method : targetType.getMethods()) {if (method.getDeclaringClass() == Object.class ||(method.getModifiers() & Modifier.STATIC) != 0 ||Util.isDefault(method)) {continue;}MethodMetadata metadata = parseAndValidateMetadata(targetType, method);checkState(!result.containsKey(metadata.configKey()), "Overrides unsupported: %s",metadata.configKey());result.put(metadata.configKey(), metadata);}return new ArrayList<>(result.values());
}
public interface List<E> extends Collection<E> {
  public static boolean isDefault(Method method) {// Default methods are public non-abstract, non-synthetic, and non-static instance methods// declared in an interface.// method.isDefault() is not sufficient for our usage as it does not check// for synthetic methods. As a result, it picks up overridden methods as well as actual default// methods.final int SYNTHETIC = 0x00001000;return ((method.getModifiers()& (Modifier.ABSTRACT | Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC)) == Modifier.PUBLIC)&& method.getDeclaringClass().isInterface();}
protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {MethodMetadata data = new MethodMetadata();data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));data.configKey(Feign.configKey(targetType, method));if (targetType.getInterfaces().length == 1) {processAnnotationOnClass(data, targetType.getInterfaces()[0]);}processAnnotationOnClass(data, targetType);for (Annotation methodAnnotation : method.getAnnotations()) {processAnnotationOnMethod(data, methodAnnotation, method);}checkState(data.template().method() != null,"Method %s not annotated with HTTP method type (ex. GET, POST)",method.getName());Class<?>[] parameterTypes = method.getParameterTypes();Type[] genericParameterTypes = method.getGenericParameterTypes();Annotation[][] parameterAnnotations = method.getParameterAnnotations();int count = parameterAnnotations.length;for (int i = 0; i < count; i++) {boolean isHttpAnnotation = false;if (parameterAnnotations[i] != null) {isHttpAnnotation = processAnnotationsOnParameter(data, parameterAnnotations[i], i);}if (parameterTypes[i] == URI.class) {data.urlIndex(i);} else if (!isHttpAnnotation) {checkState(data.formParams().isEmpty(),"Body parameters cannot be used with form parameters.");checkState(data.bodyIndex() == null, "Method has too many Body parameters: %s", method);data.bodyIndex(i);data.bodyType(Types.resolve(targetType, targetType, genericParameterTypes[i]));}}if (data.headerMapIndex() != null) {checkMapString("HeaderMap", parameterTypes[data.headerMapIndex()],genericParameterTypes[data.headerMapIndex()]);}if (data.queryMapIndex() != null) {if (Map.class.isAssignableFrom(parameterTypes[data.queryMapIndex()])) {checkMapKeys("QueryMap", genericParameterTypes[data.queryMapIndex()]);}}return data;
}
@Override
protected void processAnnotationOnClass(MethodMetadata data, Class<?> clz) {if (clz.getInterfaces().length == 0) {RequestMapping classAnnotation = findMergedAnnotation(clz,RequestMapping.class);if (classAnnotation != null) {// Prepend path from class annotation if specifiedif (classAnnotation.value().length > 0) {String pathValue = emptyToNull(classAnnotation.value()[0]);pathValue = resolve(pathValue);if (!pathValue.startsWith("/")) {pathValue = "/" + pathValue;}data.template().uri(pathValue);}}}
}
@Override
protected void processAnnotationOnMethod(MethodMetadata data,Annotation methodAnnotation, Method method) {if (!RequestMapping.class.isInstance(methodAnnotation) && !methodAnnotation.annotationType().isAnnotationPresent(RequestMapping.class)) {return;}RequestMapping methodMapping = findMergedAnnotation(method, RequestMapping.class);// HTTP MethodRequestMethod[] methods = methodMapping.method();if (methods.length == 0) {methods = new RequestMethod[] { RequestMethod.GET };}checkOne(method, methods, "method");data.template().method(Request.HttpMethod.valueOf(methods[0].name()));// pathcheckAtMostOne(method, methodMapping.value(), "value");if (methodMapping.value().length > 0) {String pathValue = emptyToNull(methodMapping.value()[0]);if (pathValue != null) {pathValue = resolve(pathValue);// Append path from @RequestMapping if value is present on methodif (!pathValue.startsWith("/") && !data.template().path().endsWith("/")) {pathValue = "/" + pathValue;}data.template().uri(pathValue, true);}}// producesparseProduces(data, method, methodMapping);// consumesparseConsumes(data, method, methodMapping);// headersparseHeaders(data, method, methodMapping);data.indexToExpander(new LinkedHashMap<Integer, Param.Expander>());
}
@RequestMapping(method = RequestMethod.GET)
public @interface GetMapping {
private void checkOne(Method method, Object[] values, String fieldName) {checkState(values != null && values.length == 1,"Method %s can only contain 1 %s field. Found: %s", method.getName(),fieldName, values == null ? null : Arrays.asList(values));
}
private void checkAtMostOne(Method method, Object[] values, String fieldName) {checkState(values != null && (values.length == 0 || values.length == 1),"Method %s can only contain at most 1 %s field. Found: %s",method.getName(), fieldName,values == null ? null : Arrays.asList(values));
}
private String resolve(String value) {if (StringUtils.hasText(value)&& this.resourceLoader instanceof ConfigurableApplicationContext) {return ((ConfigurableApplicationContext) this.resourceLoader).getEnvironment().resolvePlaceholders(value);}return value;
}
private void parseProduces(MethodMetadata md, Method method,RequestMapping annotation) {String[] serverProduces = annotation.produces();String clientAccepts = serverProduces.length == 0 ? null: emptyToNull(serverProduces[0]);if (clientAccepts != null) {md.template().header(ACCEPT, clientAccepts);}
}
private void parseConsumes(MethodMetadata md, Method method,RequestMapping annotation) {String[] serverConsumes = annotation.consumes();String clientProduces = serverConsumes.length == 0 ? null: emptyToNull(serverConsumes[0]);if (clientProduces != null) {md.template().header(CONTENT_TYPE, clientProduces);}
}
private void parseHeaders(MethodMetadata md, Method method,RequestMapping annotation) {// TODO: only supports one header value per keyif (annotation.headers() != null && annotation.headers().length > 0) {for (String header : annotation.headers()) {int index = header.indexOf('=');if (!header.contains("!=") && index >= 0) {md.template().header(resolve(header.substring(0, index)),resolve(header.substring(index + 1).trim()));}}}
}

【源码品读】深入了解FeignContract协议解析过程相关推荐

  1. 英雄远征Erlang源码分析(5)-协议解析与玩家登录处理

    现在,客户端与服务器的连接算是正式建立了,此时用户需要做的第一件事就是登陆.不过在登录之前,我们要先研究下前后端通信的协议. 客户端与服务端建立连接后,通过提前制定好的协议进行交互.具体的协议文档在d ...

  2. Uboot中start.S源码的指令级的详尽解析 在线版

    http://bbs.chinaunix.net/thread-2312785-1-1.html 以后所有内容更新,都放在这里: Uboot中start.S源码的指令级的详尽解析 在线版 Uboot ...

  3. Uboot中start.S源码的指令级的详尽解析(转)

    Uboot中start.S源码的指令级的详尽解析 转载于:https://www.cnblogs.com/LittleTiger/p/10877516.html

  4. php tire树,Immutable.js源码之List 类型的详细解析(附示例)

    本篇文章给大家带来的内容是关于Immutable.js源码之List 类型的详细解析(附示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 一.存储图解 我以下面这段代码为例子,画 ...

  5. 什么是php的ast结构,什么是AST?Vue源码中AST语法树的解析

    这篇文章给大家介绍的内容是关于什么是AST?Vue源码中AST语法树的解析,有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助. 什么是AST AST是指抽象语法树(abstract syn ...

  6. Uboot中start.S源码的指令级的详尽解析

    Uboot中start.S源码的指令级的详尽解析 版本:v1.9 Crifan Li 摘要 本文对Uboot中的Start.S的源码的几乎每一行,都进行了详细的解析 本文提供多种格式供: 在线阅读 H ...

  7. Spectacle源码及分析3 —— Main.cpp解析2

    接前一篇文章<Spectacle源码及分析2 -- Main.cpp解析1>: Spectacle源码及分析2 -- Main.cpp解析1_蓝天居士的博客-CSDN博客 继续深入分析Ma ...

  8. 找一个网页,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点——python学习笔记

    1. 题目: 找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议 ...

  9. Spring AOP 源码分析 - 拦截器链的执行过程

    1.简介 本篇文章是 AOP 源码分析系列文章的最后一篇文章,在前面的两篇文章中,我分别介绍了 Spring AOP 是如何为目标 bean 筛选合适的通知器,以及如何创建代理对象的过程.现在我们的得 ...

最新文章

  1. HTMLButton控件下的Confirm()
  2. buu [HDCTF2019]basic rsa
  3. OpenGL shader normals法线贴图的实例
  4. devexpress能开发出html,DevExpress推出HTML5 JavaScript控件集
  5. 在网页中使用react
  6. 开始你的api:NetApiStarter
  7. 7 centos 时钟跟物理机同步_centos7上使用chrony自动同步时间
  8. Java进阶 | IO流核心模块与基本原理
  9. 阿里云十年新战略发布!达摩院加持,阿里技术全部开放,20亿补贴小程序
  10. 洛谷P1589 泥泞路
  11. springboot2集成hbase2环境搭建
  12. DOS7.1安装与学习
  13. 力软敏捷开发平台7.0.6旗舰版功能更新介绍
  14. FFmpeg学习之 一 (音视频理论知识)
  15. 思科路由器 密码设置和恢复
  16. 植物大战僵尸辅助C/C++版
  17. 从3D ToF到智能座舱系统方案,英飞凌如何赋能未来出行?
  18. 最小费用流算法不完全指南-2017华为软件精英挑战赛
  19. php echarts 嵌套饼图,echarts绘制嵌套环形图/ 双饼图
  20. Project Server 2016 部署

热门文章

  1. RDS使用只读副本和多AZ的区别在于数据复制的机制
  2. 【UOJ 276】无向图最小环
  3. 星尘小组第八周翻译-数据页和数据行
  4. 上传第三方jar包到nexus
  5. grunt -- javascript自动化工具
  6. Struts2之路第一天
  7. 【Hibernate】hibernate实体关系映射——单边的多对多关系
  8. 《App后台开发运维与架构实践》第4章 Linux系统
  9. 飞利浦弃意已决 冠捷顺势接手
  10. Codeforces 140D - New Year Contest