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的对应map
    Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
    //存放feign接口方法和MethodHandler的对应map
    Map<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取出来的MethodHandler
        methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
      }
    }
    //这里创建的是FeignInvocationHandler
    InvocationHandler 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);
    }

    @Override
    public 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);
    //创建重试对象Retryer
    Retryer 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 12
      response = 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发起调用。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值