Feign的调用是对接口代理实现的调用,根据上文知道Feign的Bean注册是通过FactoryBean的方式实现FeignClientFactoryBean,其实现方式和mybatis的mapper接口代理实现完全一样。

    该代理对象在Feign中得以创建

    1. public class ReflectiveFeign extends Feign {
    2. private final ParseHandlersByName targetToHandlersByName;
    3. private final InvocationHandlerFactory factory;
    4. ReflectiveFeign(ParseHandlersByName targetToHandlersByName, InvocationHandlerFactory factory) {
    5. this.targetToHandlersByName = targetToHandlersByName;
    6. this.factory = factory;
    7. }
    8. @Override
    9. public <T> T newInstance(Target<T> target) {
    10. Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
    11. Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
    12. List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
    13. for (Method method : target.type().getMethods()) {
    14. if (method.getDeclaringClass() == Object.class) {
    15. continue;
    16. } else if(Util.isDefault(method)) {
    17. // defaultl方法封装为DefaultMethodHandler去处理
    18. DefaultMethodHandler handler = new DefaultMethodHandler(method);
    19. defaultMethodHandlers.add(handler);
    20. methodToHandler.put(method, handler);
    21. } else {
    22. // 接口方法封装为
    23. methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
    24. }
    25. }
    26. // 代理对象的创建
    27. // 1.invocationHandler对象
    28. InvocationHandler handler = factory.create(target, methodToHandler);
    29. // 代理对象
    30. T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);
    31. for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
    32. defaultMethodHandler.bindTo(proxy);
    33. }
    34. return proxy;
    35. }
    36. }

    InvocationHandler的实现是

    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();
            }
            // 最终执行的方法MethodHandler#invoke(args)
            return dispatch.get(method).invoke(args);
        }
    }
    

    MethodHandler的实现如下图

    一般情况,非default方法是封装为SynchronousMethodHandler

    final class SynchronousMethodHandler implements MethodHandler {
    
        private static final long MAX_RESPONSE_BUFFER_SIZE = 8192L;
        // feign配置信息
        private final MethodMetadata metadata;
        private final Target<?> target;
        private final Client client;// http客户端实现
        private final Retryer retryer;// 重试机制
        private final List<RequestInterceptor> requestInterceptors;// 拦截器
        private final Logger logger;// 日志
        private final Logger.Level logLevel;// 日志级别
        private final RequestTemplate.Factory buildTemplateFromArgs;
        private final Options options;// 超时选项配置等
        private final Decoder decoder;// 解码
        private final ErrorDecoder errorDecoder;
        private final boolean decode404;
    
        @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;
                }
            }
        }
        // do执行
        Object executeAndDecode(RequestTemplate template) throws Throwable {
            Request request = targetRequest(template);
            // 日志的打印
            if (logLevel != Logger.Level.NONE) {
                logger.logRequest(metadata.configKey(), logLevel, request);
            }
    
            Response response;
            long start = System.nanoTime();
            try {
                // 执行请求,可能是httpClient或okhttp之类,亦或者是ribbon封装的负载均衡客户端等等
                response = client.execute(request, options);
                // ensure the request is set. TODO: remove in Feign 10
                response.toBuilder().request(request).build();
            } catch (IOException e) {
                if (logLevel != Logger.Level.NONE) {
                    logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
                }
                throw errorExecuting(request, e);
            }
            long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
    
            boolean shouldClose = true;
            try {
                if (logLevel != Logger.Level.NONE) {
                    response =
                        logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
                    // ensure the request is set. TODO: remove in Feign 10
                    response.toBuilder().request(request).build();
                }
                if (Response.class == metadata.returnType()) {
                    if (response.body() == null) {
                        return response;
                    }
                    if (response.body().length() == null ||
                        response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
                        shouldClose = false;
                        return response;
                    }
                    // Ensure the response body is disconnected
                    // 响应字节流
                    byte[] bodyData = Util.toByteArray(response.body().asInputStream());
                    return response.toBuilder().body(bodyData).build();
                }
                if (response.status() >= 200 && response.status() < 300) {
                    if (void.class == metadata.returnType()) {
                        return null;
                    } else {
                        // 解码
                        return decode(response);
                    }
                } else if (decode404 && response.status() == 404) {
                    return decode(response);
                } else {
                    throw errorDecoder.decode(metadata.configKey(), response);
                }
            } catch (IOException e) {
                if (logLevel != Logger.Level.NONE) {
                    logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);
                }
                throw errorReading(request, response, e);
            } finally {
                if (shouldClose) {
                    ensureClosed(response.body());
                }
            }
        }
        // 调用解码工具解码
        Object decode(Response response) throws Throwable {
            try {
                return decoder.decode(response, metadata.returnType());
            } catch (FeignException e) {
                throw e;
            } catch (RuntimeException e) {
                throw new DecodeException(e.getMessage(), e);
            }
        }
    }
    

    SynchronousMethodHandler的主要功能就是执行Feign定义的流程,对请求编码,使用配置的http客户端发起请求,对响应进行解码,以及失败重试等等操作。