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;
}
}
}
... }
Feign 客户端源码解析的更多相关文章
- FileZilla客户端源码解析
FileZilla客户端源码解析 FTP是TCP/IP协议组的协议,有指令通路和数据通路两条通道.一般来说,FTP标准命令TCP端口号是21,Port方式数据传输端口是20. FileZilla作为p ...
- Netty5客户端源码解析
Netty5客户端源码解析 今天来分析下netty5的客户端源码,示例代码如下: import io.netty.bootstrap.Bootstrap; import io.netty.channe ...
- 深入理解Feign之源码解析
转载请标明出处: 本文出自方志朋的博客 什么是Feign Feign是受到Retrofit,JAXRS-2.0和WebSocket的影响,它是一个jav的到http客户端绑定的开源项目. Feign的 ...
- Spring Cloud系列(四):Eureka源码解析之客户端
一.自动装配 1.根据自动装配原理(详见:Spring Boot系列(二):Spring Boot自动装配原理解析),找到spring-cloud-netflix-eureka-client.jar的 ...
- 第零章 dubbo源码解析目录
第一章 第一个dubbo项目 第二章 dubbo内核之spi源码解析 2.1 jdk-spi的实现原理 2.2 dubbo-spi源码解析 第三章 dubbo内核之ioc源码解析 第四章 dubb ...
- Feign源码解析
1. Feign源码解析 1.1. 启动过程 1.1.1. 流程图 1.1.2. 解释说明 Feign解析过程依赖Spring的初始化,它通过实现ImportBeanDefinitionRegistr ...
- Feign源码解析系列-那些注解们
开始 Feign在Spring Cloud体系中被整合进来作为web service客户端,使用HTTP请求远程服务时能就像调用本地方法,可见在未来一段时间内,大多数Spring Cloud架构的微服 ...
- Feign 系列(05)Spring Cloud OpenFeign 源码解析
Feign 系列(05)Spring Cloud OpenFeign 源码解析 [TOC] Spring Cloud 系列目录(https://www.cnblogs.com/binarylei/p/ ...
- Fabric1.4源码解析:客户端安装链码
看了看客户端安装链码的部分,感觉还是比较简单的,所以在这里记录一下. 还是先给出安装链码所使用的命令好了,这里就使用官方的安装链码的一个例子: #-n 指定mycc是由用户定义 ...
随机推荐
- 微信小程序tab切换,可滑动切换,导航栏跟随滚动实现
简介 看到今日头条小程序页面可以滑动切换,而且tab导航条也会跟着滚动,点击tab导航,页面滑动,切导航栏也会跟着滚动,就想着要怎么实现这个功能 像商城类商品类目如果做成左右滑动切换类目用户体验应该会 ...
- 单片机成长之路(51基础篇) - 004 STC89C52MCU 软件实现系统复位
用户应用程序在运行过程中,有时会有特殊需求,需要实现单片机系统复位(热启动之一),传统的8051单片机由于硬件上未支持此功能,用户必须用软件模拟实现,实现起来较麻烦.STC单片机增加了相应的硬件功能, ...
- Java之JavaWeb项目开发开始准备
操作系统:Mac OS 10.11.6 Tomcat版本:9.0.0.M17 前言:部署Tomcat可以参考我一年前做的笔记:<在MAC下搭建JSP开发环境>,也可以参考大神写的挺好的&l ...
- mybatis #与$区别
mybatis #与$区别 #{}变量解析到SQL有带引号字符串:如查询条件变量如:select * from user where name = #{name}; 为:select * from u ...
- php获取当前被调函数的参数列表
下面是php中的一个获取当前别调用函数的参数列表的测试程序,感受一下php类库的强大之处: // 测试获取参数列表 getArgs('aaa', 'bbb', 'ccc', 123, true); f ...
- CentOS 7下PXE+Kickstart无人值守安装操作系统
1.简介 1.1. 什么是PXE PXE(Pre-boot Execution Environment,预启动执行环境)是由Intel公司开发的最新技术,工作于Client/Server的网络模式,支 ...
- 学习:ups电池放电时间是怎么计算的?
例如现有20KVA的UPS一台,负载功率为8000W,电池节数为64节,容量为32AH,电池电压为12V,那么UPS电源的放电时间计算方法如下: 负载功率*放电时长=电池放电量*电池电压*逆变率 80 ...
- 机器学习&深度学习基础(机器学习基础的算法概述及代码)
参考:机器学习&深度学习算法及代码实现 Python3机器学习 传统机器学习算法 决策树.K邻近算法.支持向量机.朴素贝叶斯.神经网络.Logistic回归算法,聚类等. 一.机器学习算法及代 ...
- 【转】JAVA反射与注解
转载自:https://www.daidingkang.cc/2017/07/18/java-reflection-annotations/ 前言 现在在我们构建自己或公司的项目中,或多或少都会依赖几 ...
- EntityFramework 动态构造排序 Func<IQueryable<T>, IOrderedQueryable<T>> Dynamic
using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; us ...