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

  

Feign 客户端源码解析的更多相关文章

  1. FileZilla客户端源码解析

    FileZilla客户端源码解析 FTP是TCP/IP协议组的协议,有指令通路和数据通路两条通道.一般来说,FTP标准命令TCP端口号是21,Port方式数据传输端口是20. FileZilla作为p ...

  2. Netty5客户端源码解析

    Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...

  3. 深入理解Feign之源码解析

    转载请标明出处: 本文出自方志朋的博客 什么是Feign Feign是受到Retrofit,JAXRS-2.0和WebSocket的影响,它是一个jav的到http客户端绑定的开源项目. Feign的 ...

  4. Spring Cloud系列(四):Eureka源码解析之客户端

    一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...

  5. 第零章 dubbo源码解析目录

    第一章 第一个dubbo项目 第二章  dubbo内核之spi源码解析 2.1  jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...

  6. Feign源码解析

    1. Feign源码解析 1.1. 启动过程 1.1.1. 流程图 1.1.2. 解释说明 Feign解析过程依赖Spring的初始化,它通过实现ImportBeanDefinitionRegistr ...

  7. Feign源码解析系列-那些注解们

    开始 Feign在Spring Cloud体系中被整合进来作为web service客户端,使用HTTP请求远程服务时能就像调用本地方法,可见在未来一段时间内,大多数Spring Cloud架构的微服 ...

  8. Feign 系列(05)Spring Cloud OpenFeign 源码解析

    Feign 系列(05)Spring Cloud OpenFeign 源码解析 [TOC] Spring Cloud 系列目录(https://www.cnblogs.com/binarylei/p/ ...

  9. Fabric1.4源码解析:客户端安装链码

          看了看客户端安装链码的部分,感觉还是比较简单的,所以在这里记录一下.       还是先给出安装链码所使用的命令好了,这里就使用官方的安装链码的一个例子: #-n 指定mycc是由用户定义 ...

随机推荐

  1. echarts参数详解--散点图

    参考地址:http://www.cnblogs.com/weizhen/p/5907617.html <!-- 1.首先需要下载包echarts.js,然后引入该包 --> <!DO ...

  2. mybatis整合hikariCP(非spring)

    mybatis整合hikariCP(非spring) 一.配置hikariCP典型的配置文件hikariPool.properties jdbcUrl=jdbc:mysql://localhost:3 ...

  3. Gradle 打可执行jar包

    初次使用Gradle,想和maven一样,把gradle项目打成可执行jar包,具体步骤: 1.下载gradle 版本,并配置环境变量, 下载地址:https://gradle.org/release ...

  4. C# yield return; yield break;

    using System; using System.Collections; namespace YieldDemo { class Program { public static IEnumera ...

  5. sudo: unable to execute ./script.sh: no such file or directory

    I just had this exact problem, it turned out to be a text file encoding problem. For me to fix it wh ...

  6. const的位置问题

    来源:牛客网 下列哪两个是等同的 int b; 1.const int *a = &b; 2.const * int a = &b; 3.const int* const a = &a ...

  7. Mac 终端Terminal光标移动快捷键

    声明: 转载自: http://blog.csdn.net/lgm252008/article/details/8253519 在Mac系统中并没有Home.End等键,所以在使用时并不是特别的顺手, ...

  8. Linux系统时间同步方法小结

    在Windwos中,系统时间的设置很简单,界面操作,通俗易懂,而且设置后,重启,关机都没关系.系统时间会自动保存在BIOS时钟里面,启动计算机的时候,系统会自动在BIOS里面取硬件时间,以保证时间的不 ...

  9. python 遍历hadoop, 跟指定列表对比 包含列表中值的取出。

    import sys import tstree fname = 'high_freq_site.list' tree = tstree.TernarySearchTrie() tree.loadDa ...

  10. iOS开发之--单个页面禁止右滑返回操作

    禁止右滑: if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) ...