zoukankan      html  css  js  c++  java
  • Feign 客户端源码解析

    Feign的使用非常简单,增加如下配置之后,便可以使用Feign进行调用。非常简单是不是。主要的工作由Feign框架完成。业务代码只提供了一个Interface, 然后由Feign动态生成代理类来实现整个的调用过程。

    @Configuration
    public class FeignConfig {
    
      @Bean(name = "myCient")
      public MyClient myClient() {
        return Feign.builder().requestInterceptor(new MyRequestInterceptor()).retryer(Retryer.NEVER_RETRY).logLevel(Logger.Level.BASIC).logger(new Slf4jLogger())
                    .encoder(new JacksonEncoder()).decoder(new JacksonDecoder()).
            errorDecoder(new MyResultDecoder()).target(MyClient.class, "serviceUrl");
      }
    }
    

      

    框架相关代码:

    Feign.java

    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);
        }
    

    ReflectiveFeign.java

    @SuppressWarnings("unchecked")
      @Override
      public <T> T newInstance(Target<T> target) {
        Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target); // 这个方法是重点,生成了代理类具体实现。具体参考SynchronousMethodHandler。
        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 {
            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;
      }
    

      

    SynchronousMethodHandler.java

    final class SynchronousMethodHandler implements MethodHandler{
    
    ...
    //具体实现逻辑,代理类的InvokeHandler的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;
          }
        }
      }
    ...
    
    }
    

      

  • 相关阅读:
    python简单的运算
    Typora的基本格式使用
    在Eclipse中在线安装Emmet和图文使用教程
    6月末的总结
    TF-IDF学习笔记
    idea调试SpringMvc, 出现:”Can't find catalina.jar"错误的解决方法
    idea调试SpringMvc, 出现:”javax.servlet.ServletException: java.lang.IllegalStateException: Cannot create a session after the response has been committed"错误的解决方法
    idea调试SpringMvc, 出现:”通配符的匹配很全面, 但无法找到元素 'mvc:annotation-driven' 的声明“错误的解决方法
    idea调试SpringMvc, 出现:java.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener错误的解决办法
    Zabbix 漏洞分析
  • 原文地址:https://www.cnblogs.com/lzmrex/p/9466886.html
Copyright © 2011-2022 走看看