上篇文章介绍了Feign的介绍和入门,这次我们介绍下Feign的七大核心组件。
相信稍微了解Feign的小伙伴都知道,Feign底层其实是基于JDK动态代理实现的,所以Feign.builder()最终构造的是一个代理对象,Feign在构建动态代理的时候,会去解析方法上的注解和参数,获取Http请求需要用到基本参数以及和这些参数和方法参数的对应关系。比如Http请求的url、请求体是方法中的第几个参数、请求头是方法中的第几个参数等……之后在构建Http请求时,就知道请求路径以及方法的第几个参数对应是Http请求的哪部分数据,当调用动态代理方法的时候,Feign就会将上述解析出来的Http请求基本参数和方法入参组装成一个Http请求,然后发送Http请求,获取响应,再根据响应的内容的类型将响应体的内容转换成对应的类型,这就是Feign的大致原理。为更好的说明,从网上找到下图
在整个Feign动态代理生成和调用过程中,需要依靠Feign的一些核心组件来协调完成,如下图源码所示是Feign的一些核心组件。
这些核心组件可以根据项目实际需要通过Feign.builder()进行替换。由于组件比较很多,这里仅挑几个重要的进行说明。
1、Contract
Feign在构建动态代理的时候,会去解析方法上的注解和参数,获取Http请求需要用到基本参数,而这个Contract接口的作用就是用来解析Feign原生注解的。
解析时,会为每个方法生成一个MethodMetadata对象
MethodMetadata就封装了Http请求需要用到基本参数以及这些参数和方法参数的对应关系。
2、Encoder
通过名字可以看出来,这个其实用来编码的。具体的作用就是将请求体对应的方法参数序列化成字节数组,如下图所示
Feign默认的Encoder实现只支持请求体对应的方法参数类型为String和字节数组。
如果是其它类型,比如说请求体对应的方法参数类型为User.class类型,此时就无法对User对象进行序列化,这就导致默认情况下,这个Encoder的实现很难用,于是Spring就实现了自己的Encoder接口。它可以将任意请求体对应的方法参数类型对象序列化成字节数组,源码如下图。
3、Decoder
Decoder的作用恰恰是跟Encoder相反,Encoder是将请求体对应的方法参数序列化成字节数组,而Decoder其实就是将响应体由字节流反序列化成方法返回值类型的对象。Decoder默认情况下跟Encoder的默认情况是一样的,只支持反序列化成字节数组或者是String。
Spring也同样实现了Decoder,扩展它的功能,可以将响应体对应的字节流反序列化成任意返回值类型对象。
4、Client
从接口方法的参数和返回值可以看出,这其实就是动态代理对象最终用来执行Http请求的组件,默认实现就是通过JDK提供的HttpURLConnection来的。
除了这个默认的,Feign还提供了基于HttpClient和OkHttp实现。在项目中,要想替换默认的实现,只需要引入相应的依赖,在构建Feign.builder()时设置一下就可以了,非常灵活。
除了上述的三个实现外,最重要的当然是属于它基于负载均衡的实现,如下是OpenFeign用来整合Ribbon的核心实现。
在调用服务时Client会根据服务名,从Ribbon中获取一个服务实例的信息,也就是ip和端口,然后通过ip和端口向服务实例发送Http请求。
5、InvocationHandlerFactory
InvocationHandler我相信大家应该都不陌生,对于JDK动态代理来说,必须得实现InvocationHandler才能创建动态代理,InvocationHandler的invoke方法实现就是动态代理走的核心逻辑,而InvocationHandlerFactory其实就是创建InvocationHandler的工厂。从这里就可以猜到,通过InvocationHandlerFactory创建的InvocationHandler应该就是Feign动态代理执行的核心逻辑,InvocationHandlerFactory默认实现是下面这个。
SpringCloud环境下默认也是使用它的这个默认实现,直接去看看InvocationHandler的实现类FeignInvocationHandler。
从实现可以看出,除了Object类的一些方法,最终会调用方法对应的MethodHandler的invoke方法。所以注意,这个MethodHandler就封装了Feign执行Http调用的核心逻辑。
虽然说默认情况下SpringCloud使用是默认实现,最终使用FeignInvocationHandler,但是当其它框架整合SpringCloud生态的时候,为了适配OpenFeign,有时会自己实现InvocationHandler,比如常见的限流熔断框架Hystrix和Sentinel都实现了自己的InvocationHandler。这样就可以对MethodHandler执行前后,也就是Http接口调用前后进行限流降级等操作。
6、RequestInterceptor
RequestInterceptor它其实是一个在发送请求前的一个拦截接口,通过这个接口,在发送Http请求之前再对Http请求的内容进行修改,比如我们可以设置一些接口需要的公共参数,如鉴权token之类的。
7、Retryer
这是一个重试的组件,默认实现如下。默认情况下,最大重试5次。
在SpringCloud下,并没有使用上面那个实现,而使用的是下面这个实现。
总结
这一节主要是介绍了7个Feign的核心组件以及Spring对应的扩展实现,为了方便查看,整理了如下表格:
接口 | 作用 | Feign默认实现 | Spring实现 |
Contract | 解析方法注解和参数,将Http请求参数和方法参数对应 | Contract.Default | SpringMvcContract |
Encoder | 将请求体对应的方法参数序列化成字节数组 | Encoder.Default | SpringEncoder |
Decoder | 将响应体的字节流反序列化成方法返回值类型对象 | Decoder.Default | SpringDecoder |
Client | 发送Http请求 | Client.Default | LoadBalancerFeignClient |
InvocationHandlerFactory | InvocationHandler工厂,动态代理核心逻辑 | InvocationHandlerFactory.Default | 无 |
RequestInterceptor | 在发送Http请求之前,再对Http请求的内容进行拦截修改 | 无 | 无 |
Retryer | 重试组件 | Retryer.Default | 无 |
除了这些之外,其它组件这里就没有列出,有兴趣的可以自己查看!下次将进行Feign核心原理分析
本文暂时没有评论,来添加一个吧(●'◡'●)