Feign源代码粗读

Feign使用简单示例

定义好一个接口,用@RequestLine注解

public interface WxCorpDepartmentClient {
    @RequestLine("POST /cgi-bin/department/list?access_token={accessToken}")
    public DepartmentResult departments(@Param("accessToken") String accessToken);
}

实际发起请求的代码:

@Component
public class WxCorpPermanentCodeClientImpl extends BaseWxCorpClient implements WxCorpPermanentCodeClient {
    @Override
    public PermanentCodeResult corpPermanentCode(String suiteAccessToken, PermanentCodeRequest permanentCodeRequest) {
        return getFeignClient(WxCorpPermanentCodeClient.class).corpPermanentCode(suiteAccessToken, permanentCodeRequest);
    }
}

public class BaseWxCorpClient {
    public T getFeignClient(Class clazz) {
        return Feign.builder()
                .encoder(new GsonEncoder())
                .decoder(new GsonDecoder()).target(clazz, "https://qyapi.weixin.qq.com");
    }
}

源代码解析

核心类类图

Feign源代码粗读_第1张图片
image

由类图可知,Feign的实例的Class为 feign.ReflectiveFeign

ReflectiveFeign的创建过程

该实例采用Builder模式进行创建,在通常的使用中,我们写如下代码即可创建ReflectiveFeign的实例。

Feign.builder().encoder(new GsonEncoder()).decoder(new GsonDecoder()).target(clazz, "https://qyapi.weixin.qq.com")

Feign.builder()

通过Feign.builder()创建出Feign的构造器实例。在Builder的属性中,可以看到包括 Client、Retryer、Logger、Encoder、Decoder、Contract、Logger.Level等都是可以进行定义的。不过在builder中也对这些属性做了默认的配置。

    private Logger.Level logLevel = Logger.Level.NONE;
    private Contract contract = new Contract.Default();
    private Client client = new Client.Default(null, null);
    private Retryer retryer = new Retryer.Default();
    private Logger logger = new NoOpLogger();
    private Encoder encoder = new Encoder.Default();
    private Decoder decoder = new Decoder.Default();
    private ErrorDecoder errorDecoder = new ErrorDecoder.Default();

Builder.target(Class, String)

public  T target(Class apiType, String url) {
      return target(new HardCodedTarget(apiType, url));
}

public  T target(Target target) {
  return build().newInstance(target);
}

public Feign build() {
  SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
      new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
                                           logLevel, decode404);
  ParseHandlersByName handlersByName =
      new ParseHandlersByName(contract, options, encoder, decoder,
                              errorDecoder, synchronousMethodHandlerFactory);
  return new ReflectiveFeign(handlersByName, invocationHandlerFactory);
}

通过Builder.build()方法,最后创建出ReflectiveFeign的实例。

Feign源代码粗读_第2张图片
image

ReflectiveFeign的两个属性,一个是ParseHandlersByName 另一个是InvocationHandlerFactory。

Feign.newInstance(Target)

在ReflectiveFeign中对newInstance方法的实现为:

  public  T newInstance(Target target) {
    // 将Target包装的实际的对象的方法进行分析后,封装在map里.key就是方法的签名.
    Map nameToHandler = targetToHandlersByName.apply(target);
    Map methodToHandler = new LinkedHashMap();
    List defaultMethodHandlers = new LinkedList();

    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 {
        methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
      }
    }
    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;
  }

对应的nameToHanlder在内存中的调试结果为:

Feign源代码粗读_第3张图片
image

Feign对我们的接口做了代理,具体的实现是在 feign.ReflectiveFeign.FeignInvocationHandler 这个类中。

static class FeignInvocationHandler implements InvocationHandler {

    private final Target target;
    private final Map dispatch;

    FeignInvocationHandler(Target target, Map 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();
      }
      return dispatch.get(method).invoke(args);
    }
  }

由代理对象的invoke可知,我们在实际调用接口方法的时候,会调用其invoke方法。

invoke方法中,根据方法获取到对应的MethodHandler,由调试的内存结果,我们看到是由SynchronousMethodHandler来进行处理的。下面是对应的invoke的处理逻辑。

  @Override
  public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
        return executeAndDecode(template);
      } catch (RetryableException e) {
        retryer.continueOrPropagate(e);
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }

你可能感兴趣的:(Feign源代码粗读)