Feign的Contract

王守钰 2020-12-08 18:12:49

Contract.Default

Contract.Default在实例化的时候注册了许多注解处理器。Contract继承了DeclarativeContract抽象类。

public Default() {
  // 注册类上的@Headers注解
  super.registerClassAnnotation(Headers.class, (header, data) -> {
    // 获取@Headers注解的值信息。eg:@Headers({"xxx:xxx","yyy:yyy"})
    final String[] headersOnType = header.value();
    // 校验header内容是否为空
    checkState(headersOnType.length > 0, "Headers annotation was empty on type %s.",
        data.configKey());
    // 转换注解内容信息
    final Map<String, Collection<String>> headers = toMap(headersOnType);
    // 添加默认的header信息
    headers.putAll(data.template().headers());
    // 清空原有的header信息
    data.template().headers(null); // to clear
    // 设置RequestTemplate 的header信息
    data.template().headers(headers);
  });
  // 注册方法上的@RequestLine注解
  super.registerMethodAnnotation(RequestLine.class, (ann, data) -> {
    // 获取@RequestLine注解上的值。eg:@RequestLine("GET /resource/{id}")
    final String requestLine = ann.value();
    // 校验请求信息是否为空
    checkState(emptyToNull(requestLine) != null,
        "RequestLine annotation was empty on method %s.", data.configKey());
    // 正则匹配是否有大写字母A到Z开头中间空格的数据
    final Matcher requestLineMatcher = REQUEST_LINE_PATTERN.matcher(requestLine);
    // 正则匹配失败不符合规则
    if (!requestLineMatcher.find()) {
      throw new IllegalStateException(String.format(
          "RequestLine annotation didn't start with an HTTP verb on method %s",
          data.configKey()));
    } else {
      // 设置Http请求方式  GET, HEAD, POST, PUT, DELETE, CONNECT, OPTIONS, TRACE, PATCH
      data.template().method(HttpMethod.valueOf(requestLineMatcher.group(1)));
      // 设置请求地址
      data.template().uri(requestLineMatcher.group(2));
    }
    // 设置是否斜线处理
    data.template().decodeSlash(ann.decodeSlash());
    // 设置集合处理方式
    data.template()
        .collectionFormat(ann.collectionFormat());
  });
  // 注册方法上的@Body注解
  super.registerMethodAnnotation(Body.class, (ann, data) -> {
    // 获取@Body注解的值信息。eg:@Body("{body}")
    final String body = ann.value();
    // 校验body是否为空
    checkState(emptyToNull(body) != null, "Body annotation was empty on method %s.",
        data.configKey());
    // 校验body内容是否包含{
    if (body.indexOf('{') == -1) {
      // 不包含直接设置body
      data.template().body(body);
    } else {
      // 包含设置bodyTemplate
      data.template().bodyTemplate(body);
    }
  });
  // 注册方法上的@Headers注解
  super.registerMethodAnnotation(Headers.class, (header, data) -> {
    // 获取@Headers注解的值信息。eg:@Headers("xxx:xxx")
    final String[] headersOnMethod = header.value();
    // 校验header是否为空
    checkState(headersOnMethod.length > 0, "Headers annotation was empty on method %s.",
        data.configKey());
    // 设置当前请求的header信息
    data.template().headers(toMap(headersOnMethod));
  });
  // 注册参数上的@Param注解
  super.registerParameterAnnotation(Param.class, (paramAnnotation, data, paramIndex) -> {
    // 获取注解@Param的值信息。eg:@Param("a=a")
    final String name = paramAnnotation.value();
    // 校验参数值信息是否为空
    checkState(emptyToNull(name) != null, "Param annotation was empty on param %s.",
        paramIndex);
    // 解析param
    nameParam(data, name, paramIndex);
    // 获取参数增强器
    final Class<? extends Param.Expander> expander = paramAnnotation.expander();
    // 判断增强器是否为ToStringExpander
    if (expander != Param.ToStringExpander.class) {
      // 设置当前索引位置的增强器
      data.indexToExpanderClass().put(paramIndex, expander);
    }
    // 校验是否包含请求参数,不包含设置form请求参数
    if (!data.template().hasRequestVariable(name)) {
      data.formParams().add(name);
    }
  });
  // 注册参数上的@QueryMap注解
  super.registerParameterAnnotation(QueryMap.class, (queryMap, data, paramIndex) -> {
    // 校验索引信息是否为空
    checkState(data.queryMapIndex() == null,
        "QueryMap annotation was present on multiple parameters.");
    // 设置索引位置信息
    data.queryMapIndex(paramIndex);
    // 设置是否需要Encoded
    data.queryMapEncoded(queryMap.encoded());
  });
  // 注册参数上的@HeaderMap注解
  super.registerParameterAnnotation(HeaderMap.class, (queryMap, data, paramIndex) -> {
    // 校验索引位置是否为空
    checkState(data.headerMapIndex() == null,
        "HeaderMap annotation was present on multiple parameters.");
    // 设置索引位置
    data.headerMapIndex(paramIndex);
  });
}

DeclarativeContract

public abstract class DeclarativeContract extends BaseContract {

  // 类上的注解处理器
  private final List<GuardedAnnotationProcessor> classAnnotationProcessors = new ArrayList<>();
  // 方法上的注解处理器
  private final List<GuardedAnnotationProcessor> methodAnnotationProcessors = new ArrayList<>();
  // 参数上的注解处理器
  private final Map<Class<Annotation>, DeclarativeContract.ParameterAnnotationProcessor<Annotation>> parameterAnnotationProcessors =
      new HashMap<>();
  
  // 转换并校验,实际逻辑在父类中。    
  @Override
  public final List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
    // any implementations must register processors
    return super.parseAndValidateMetadata(targetType);
  }
      
  // 类上注解处理
  @Override
  protected final void processAnnotationOnClass(MethodMetadata data, Class<?> targetType) {
    // 过滤在类上的注解处理器
    final List<GuardedAnnotationProcessor> processors = Arrays.stream(targetType.getAnnotations())
        .flatMap(annotation -> classAnnotationProcessors.stream()
            .filter(processor -> processor.test(annotation)))
        .collect(Collectors.toList());
    // 校验处理器是否为空
    if (!processors.isEmpty()) {
      // 不为空循环过滤处理
      Arrays.stream(targetType.getAnnotations())
          .forEach(annotation -> processors.stream()
              .filter(processor -> processor.test(annotation))
              .forEach(processor -> processor.process(annotation, data)));
    } else {
      // 处理器为空,注解为空,抛出警告
      if (targetType.getAnnotations().length == 0) {
        data.addWarning(String.format(
            "Class %s has no annotations, it may affect contract %s",
            targetType.getSimpleName(),
            getClass().getSimpleName()));
      } else {
        // 注解不为空,抛出警告
        data.addWarning(String.format(
            "Class %s has annotations %s that are not used by contract %s",
            targetType.getSimpleName(),
            Arrays.stream(targetType.getAnnotations())
                .map(annotation -> annotation.annotationType()
                    .getSimpleName())
                .collect(Collectors.toList()),
            getClass().getSimpleName()));
      }
    }
  }

  // 方法注解处理
  @Override
  protected final void processAnnotationOnMethod(MethodMetadata data,
                                                 Annotation annotation,
                                                 Method method) {
    // 获取过滤方法注解处理器
    List<GuardedAnnotationProcessor> processors = methodAnnotationProcessors.stream()
        .filter(processor -> processor.test(annotation))
        .collect(Collectors.toList());
    // 校验处理器是否为空
    if (!processors.isEmpty()) {
      // 调用处理器进行处理
      processors.forEach(processor -> processor.process(annotation, data));
    } else {
      // 处理器为空 添加警告
      data.addWarning(String.format(
          "Method %s has an annotation %s that is not used by contract %s",
          method.getName(),
          annotation.annotationType()
              .getSimpleName(),
          getClass().getSimpleName()));
    }
  }


  // 参数注解处理
  @Override
  protected final boolean processAnnotationsOnParameter(MethodMetadata data,
                                                        Annotation[] annotations,
                                                        int paramIndex) {
    // 过滤参数注解处理器
    List<Annotation> matchingAnnotations = Arrays.stream(annotations)
        .filter(
            annotation -> parameterAnnotationProcessors.containsKey(annotation.annotationType()))
        .collect(Collectors.toList());
    // 判断是否为空
    if (!matchingAnnotations.isEmpty()) {
      // 循环处理注解信息
      matchingAnnotations.forEach(annotation -> parameterAnnotationProcessors
          .getOrDefault(annotation.annotationType(), ParameterAnnotationProcessor.DO_NOTHING)
          .process(annotation, data, paramIndex));

    } else {
      // 获取方法上的参数
      final Parameter parameter = data.method().getParameters()[paramIndex];
      // 获取参数名
      String parameterName = parameter.isNamePresent()
          ? parameter.getName()
          : parameter.getType().getSimpleName();
      // 判断是否有注解
      if (annotations.length == 0) {
        data.addWarning(String.format(
            "Parameter %s has no annotations, it may affect contract %s",
            parameterName,
            getClass().getSimpleName()));
      } else {
        data.addWarning(String.format(
            "Parameter %s has annotations %s that are not used by contract %s",
            parameterName,
            Arrays.stream(annotations)
                .map(annotation -> annotation.annotationType()
                    .getSimpleName())
                .collect(Collectors.toList()),
            getClass().getSimpleName()));
      }
    }
    return false;
  }

  // 注册类上注解处理器
  protected <E extends Annotation> void registerClassAnnotation(Class<E> annotationType,
                                                                DeclarativeContract.AnnotationProcessor<E> processor) {
    // 注册类上注解处理器
    registerClassAnnotation(
        annotation -> annotation.annotationType().equals(annotationType),
        processor);
  }

  // 注册类上注解处理器
  protected <E extends Annotation> void registerClassAnnotation(Predicate<E> predicate,
                                                                DeclarativeContract.AnnotationProcessor<E> processor) {
    // 添加到类上注解处理器集合
    this.classAnnotationProcessors.add(new GuardedAnnotationProcessor(predicate, processor));
  }

  // 注册方法注解处理器
  protected <E extends Annotation> void registerMethodAnnotation(Class<E> annotationType,
                                                                 DeclarativeContract.AnnotationProcessor<E> processor) {
    // 注册方法上注解处理器
    registerMethodAnnotation(
        annotation -> annotation.annotationType().equals(annotationType),
        processor);
  }

  // 注册方法注解处理器
  protected <E extends Annotation> void registerMethodAnnotation(Predicate<E> predicate,
                                                                 DeclarativeContract.AnnotationProcessor<E> processor) {
    // 添加到方法注解处理器
    this.methodAnnotationProcessors.add(new GuardedAnnotationProcessor(predicate, processor));
  }

  // 注册参数注解处理器
  protected <E extends Annotation> void registerParameterAnnotation(Class<E> annotation,
                                                                    DeclarativeContract.ParameterAnnotationProcessor<E> processor) {
    // 添加参数注解处理器
    this.parameterAnnotationProcessors.put((Class) annotation,
        (DeclarativeContract.ParameterAnnotationProcessor) processor);
  }
}

BaseContract

abstract class BaseContract implements Contract {

    // 转换并且校验
    @Override
    public List<MethodMetadata> parseAndValidateMetadata(Class<?> targetType) {
      // 校验当前class 是否为泛型类,不支持泛型类
      checkState(targetType.getTypeParameters().length == 0, "Parameterized types unsupported: %s",
          targetType.getSimpleName());
      // 实现的接口不能超过1个
      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());
      }
      final Map<String, MethodMetadata> result = new LinkedHashMap<String, MethodMetadata>();
      // 获取所有方法,排除Object方法、静态方法、接口默认方法
      for (final Method method : targetType.getMethods()) {
        if (method.getDeclaringClass() == Object.class ||
            (method.getModifiers() & Modifier.STATIC) != 0 ||
            Util.isDefault(method)) {
          continue;
        }
        // 转换并验证metadata
        final MethodMetadata metadata = parseAndValidateMetadata(targetType, method);
        // 校验metadata属性
        checkState(!result.containsKey(metadata.configKey()), "Overrides unsupported: %s",
            metadata.configKey());
        // 设置map key=类#方法(参数1,参数2,……参数n) value=当前metadata
        result.put(metadata.configKey(), metadata);
      }
      return new ArrayList<>(result.values());
    }

    // 转换并校验
    @Deprecated
    public MethodMetadata parseAndValidateMetadata(Method method) {
      return parseAndValidateMetadata(method.getDeclaringClass(), method);
    }

    // 转换并校验
    protected MethodMetadata parseAndValidateMetadata(Class<?> targetType, Method method) {
      // 创建metadata对象
      final MethodMetadata data = new MethodMetadata();
      // 设置target
      data.targetType(targetType);
      // 设置当前方法
      data.method(method);
      // 设置返回类型
      data.returnType(Types.resolve(targetType, targetType, method.getGenericReturnType()));
      // 设置ConfigKey
      data.configKey(Feign.configKey(targetType, method));
      // 判断是否实现了接口
      if (targetType.getInterfaces().length == 1) {
        // 处理在实现接口上的注解信息
        processAnnotationOnClass(data, targetType.getInterfaces()[0]);
      }
      // 处理在类上的注解
      processAnnotationOnClass(data, targetType);
      // 循环方法上的注解
      for (final Annotation methodAnnotation : method.getAnnotations()) {
        // 处理方法上的注解
        processAnnotationOnMethod(data, methodAnnotation, method);
      }
      // 是否忽略
      if (data.isIgnored()) {
        return data;
      }
      // 获取方法的请求方式,校验是否为合法的请求方式
      checkState(data.template().method() != null,
          "Method %s not annotated with HTTP method type (ex. GET, POST)%s",
          data.configKey(), data.warnings());
      // 获取参数类
      final Class<?>[] parameterTypes = method.getParameterTypes();
      // 获取参数类型
      final Type[] genericParameterTypes = method.getGenericParameterTypes();
      // 获取参数上的注解
      final Annotation[][] parameterAnnotations = method.getParameterAnnotations();
      // 获取参数注解
      final int count = parameterAnnotations.length;
      // 循环参数注解
      for (int i = 0; i < count; i++) {
        // 定义非http注解
        boolean isHttpAnnotation = false;
        // 校验参数是否为空
        if (parameterAnnotations[i] != null) {
          // 处理参数上的注解信息
          isHttpAnnotation = processAnnotationsOnParameter(data, parameterAnnotations[i], i);
        }
        // 如果是http注解
        if (isHttpAnnotation) {
          // 忽略参数信息
          data.ignoreParamater(i);
        }
        // 判断是否是URI类
        if (parameterTypes[i] == URI.class) {
          // 如果是的话设置url索引位置
          data.urlIndex(i);
          // 判断是否是http注解,并且参数类型不是Options
        } else if (!isHttpAnnotation && parameterTypes[i] != Request.Options.class) {
          // 判断参数是否已经处理
          if (data.isAlreadyProcessed(i)) {
            checkState(data.formParams().isEmpty() || data.bodyIndex() == null,
                "Body parameters cannot be used with form parameters.%s", data.warnings());
          } else {
            // 校验form表单参数是否为空
            checkState(data.formParams().isEmpty(),
                "Body parameters cannot be used with form parameters.%s", data.warnings());
            // 校验索引位置是否为空
            checkState(data.bodyIndex() == null,
                "Method has too many Body parameters: %s%s", method, data.warnings());
            // 设置索引位置
            data.bodyIndex(i);
            // 设置body类型
            data.bodyType(Types.resolve(targetType, targetType, genericParameterTypes[i]));
          }
        }
      }
      // 判断头map里面是否有数据
      if (data.headerMapIndex() != null) {
        checkMapString("HeaderMap", parameterTypes[data.headerMapIndex()],
            genericParameterTypes[data.headerMapIndex()]);
      }
      // 校验查询map里面是否有属性
      if (data.queryMapIndex() != null) {
        if (Map.class.isAssignableFrom(parameterTypes[data.queryMapIndex()])) {
          checkMapKeys("QueryMap", genericParameterTypes[data.queryMapIndex()]);
        }
      }
      // 返回data
      return data;
    }

    // 校验map
    private static void checkMapString(String name, Class<?> type, Type genericType) {
      checkState(Map.class.isAssignableFrom(type),
          "%s parameter must be a Map: %s", name, type);
      checkMapKeys(name, genericType);
    }

    private static void checkMapKeys(String name, Type genericType) {
      Class<?> keyClass = null;

      // assume our type parameterized
      if (ParameterizedType.class.isAssignableFrom(genericType.getClass())) {
        final Type[] parameterTypes = ((ParameterizedType) genericType).getActualTypeArguments();
        keyClass = (Class<?>) parameterTypes[0];
      } else if (genericType instanceof Class<?>) {
        // raw class, type parameters cannot be inferred directly, but we can scan any extended
        // interfaces looking for any explict types
        final Type[] interfaces = ((Class) genericType).getGenericInterfaces();
        if (interfaces != null) {
          for (final Type extended : interfaces) {
            if (ParameterizedType.class.isAssignableFrom(extended.getClass())) {
              // use the first extended interface we find.
              final Type[] parameterTypes = ((ParameterizedType) extended).getActualTypeArguments();
              keyClass = (Class<?>) parameterTypes[0];
              break;
            }
          }
        }
      }

      if (keyClass != null) {
        checkState(String.class.equals(keyClass),
            "%s key must be a String: %s", name, keyClass.getSimpleName());
      }
    }

   
    protected abstract void processAnnotationOnClass(MethodMetadata data, Class<?> clz);
   
    protected abstract void processAnnotationOnMethod(MethodMetadata data,
                                                      Annotation annotation,
                                                      Method method);

    protected abstract boolean processAnnotationsOnParameter(MethodMetadata data,
                                                             Annotation[] annotations,
                                                             int paramIndex);

    // name参数
    protected void nameParam(MethodMetadata data, String name, int i) {
      // 判断参数是否包含属性信息,包含返回当前参数值列表,不包含返回创建一个集合信息。
      final Collection<String> names =
          data.indexToName().containsKey(i) ? data.indexToName().get(i) : new ArrayList<String>();
      // 添加到值信息列表中
      names.add(name);
      // 设置索引和name的关系
      data.indexToName().put(i, names);
    }
}