当前位置:首页 > 科技  > 软件

33张图探秘OpenFeign核心架构原理

来源: 责编: 时间:2024-02-29 14:42:48 131观看
导读大家好,我是三友~~在很久之前,我写过两篇关于OpenFeign和Ribbon这两个SpringCloud核心组件架构原理的文章但是说实话,从我现在的角度来看,这两篇文章的结构和内容其实还可以更加完善刚好我最近打算整个SpringCloud各个组

大家好,我是三友~~rug28资讯网——每日最新资讯28at.com

在很久之前,我写过两篇关于OpenFeign和Ribbon这两个SpringCloud核心组件架构原理的文章rug28资讯网——每日最新资讯28at.com

但是说实话,从我现在的角度来看,这两篇文章的结构和内容其实还可以更加完善rug28资讯网——每日最新资讯28at.com

刚好我最近打算整个SpringCloud各个组件架构原理的小册子rug28资讯网——每日最新资讯28at.com

所以趁着这个机会,我就来重新写一下这两篇文章,弥补之前文章的不足rug28资讯网——每日最新资讯28at.com

这一篇文章就先来讲一讲OpenFeign的核心架构原理rug28资讯网——每日最新资讯28at.com

整篇文章大致分为以下四个部分的内容:rug28资讯网——每日最新资讯28at.com

第一部分,脱离于SpringCloud,原始的Feign是什么样的?rug28资讯网——每日最新资讯28at.com

第二部分,Feign的核心组件有哪些,整个执行链路是什么样的?rug28资讯网——每日最新资讯28at.com

第三部分,SpringCloud是如何把Feign融入到自己的生态的?rug28资讯网——每日最新资讯28at.com

第四部分,OpenFeign有几种配置方式,各种配置方式的优先级是什么样的?rug28资讯网——每日最新资讯28at.com

好了,话不多说,接下来就直接进入主题,来探秘OpenFeign核心架构原理rug28资讯网——每日最新资讯28at.com

原始Feign是什么样的?

在日常开发中,使用Feign很简单,就三步rug28资讯网——每日最新资讯28at.com

第一步:引入依赖rug28资讯网——每日最新资讯28at.com

<dependency>     <groupId>org.springframework.cloud</groupId>     <artifactId>spring-cloud-starter-openfeign</artifactId>     <version>2.2.5.RELEASE</version></dependency>

第二步:在启动引导类加上@EnableFeignClients注解rug28资讯网——每日最新资讯28at.com

@SpringBootApplication@EnableFeignClientspublic class MyApplication {    public static void main(String[] args) {        SpringApplication.run(MyApplication.class, args);    }}

第三步:写个FeignClient接口rug28资讯网——每日最新资讯28at.com

@FeignClient(name = "order")@RequestMapping("/order")public interface OrderApiClient {    @GetMapping    Order queryOrder(@RequestParam("orderId") Long orderId);}

之后当我们要使用时,只需要注入OrderApiClient对象就可以了rug28资讯网——每日最新资讯28at.com

虽然使用方便,但这并不是Feign最原始的使用方式,而是SpringCloud整合Feign之后的使用方式rug28资讯网——每日最新资讯28at.com

Feign最开始是由Netflix开源的rug28资讯网——每日最新资讯28at.com

后来SpringCloud就将Feign进行了一层封装,整合到自己的生态,让Feign使用起来更加简单rug28资讯网——每日最新资讯28at.com

并同时也给它起了一个更高级的名字,OpenFeignrug28资讯网——每日最新资讯28at.com

接下来文章表述有时可能并没有严格区分Feign和OpenFeign的含义,你知道是这么个意思就行了。rug28资讯网——每日最新资讯28at.com

Feign本身有自己的使用方式,也有类似Spring MVC相关的注解,如下所示:rug28资讯网——每日最新资讯28at.com

public interface OrderApiClient {    @RequestLine("GET /order/{orderId}")    Order queryOrder(@Param("orderId") Long orderId);}

OrderApiClient对象需要手动通过Feign.builder()来创建rug28资讯网——每日最新资讯28at.com

public class FeignDemo {    public static void main(String[] args) {        OrderApiClient orderApiClient = Feign.builder()                .target(OrderApiClient.class, "http://localhost:8088");        orderApiClient.queryOrder(9527L);    }}

Feign的本质:动态代理 + 七大核心组件

相信稍微了解Feign的小伙伴都知道,Feign底层其实是基于JDK动态代理来的rug28资讯网——每日最新资讯28at.com

所以Feign.builder()最终构造的是一个代理对象rug28资讯网——每日最新资讯28at.com

Feign在构建动态代理的时候,会去解析方法上的注解和参数rug28资讯网——每日最新资讯28at.com

获取Http请求需要用到基本参数以及和这些参数和方法参数的对应关系rug28资讯网——每日最新资讯28at.com

比如Http请求的url、请求体是方法中的第几个参数、请求头是方法中的第几个参数等等rug28资讯网——每日最新资讯28at.com

之后在构建Http请求时,就知道请求路径以及方法的第几个参数对应是Http请求的哪部分数据rug28资讯网——每日最新资讯28at.com

当调用动态代理方法的时候,Feign就会将上述解析出来的Http请求基本参数和方法入参组装成一个Http请求rug28资讯网——每日最新资讯28at.com

然后发送Http请求,获取响应,再根据响应的内容的类型将响应体的内容转换成对应的类型rug28资讯网——每日最新资讯28at.com

这就是Feign的大致原理rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

在整个Feign动态代理生成和调用过程中,需要依靠Feign的一些核心组件来协调完成rug28资讯网——每日最新资讯28at.com

如下图所示是Feign的一些核心组件rug28资讯网——每日最新资讯28at.com

这些核心组件可以通过Feign.builder()进行替换rug28资讯网——每日最新资讯28at.com

由于组件很多,这里我挑几个重要的跟大家讲一讲rug28资讯网——每日最新资讯28at.com

1、Contract

图片图片rug28资讯网——每日最新资讯28at.com

前面在说Feign在构建动态代理的时候,会去解析方法上的注解和参数,获取Http请求需要用到基本参数rug28资讯网——每日最新资讯28at.com

而这个Contract接口的作用就是用来干解析这件事的rug28资讯网——每日最新资讯28at.com

Contract的默认实现是解析Feign自己原生注解的rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

解析时,会为每个方法生成一个MethodMetadata对象rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

MethodMetadata就封装了Http请求需要用到基本参数以及这些参数和方法参数的对应关系rug28资讯网——每日最新资讯28at.com

SpringCloud在整合Feign的时候,为了让Feign能够识别Spring MVC的注解,所以就自己实现了Contract接口rug28资讯网——每日最新资讯28at.com

2、Encoder

通过名字也可以看出来,这个其实用来编码的rug28资讯网——每日最新资讯28at.com

具体的作用就是将请求体对应的方法参数序列化成字节数组rug28资讯网——每日最新资讯28at.com

Feign默认的Encoder实现只支持请求体对应的方法参数类型为String和字节数组rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

如果是其它类型,比如说请求体对应的方法参数类型为AddOrderRequest.class类型,此时就无法对AddOrderRequest对象进行序列化rug28资讯网——每日最新资讯28at.com

这就导致默认情况下,这个Encoder的实现很难用rug28资讯网——每日最新资讯28at.com

于是乎,Spring就实现了Encoder接口rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

可以将任意请求体对应的方法参数类型对象序列化成字节数组rug28资讯网——每日最新资讯28at.com

3、Decoder

Decoder的作用恰恰是跟Encoder相反rug28资讯网——每日最新资讯28at.com

Encoder是将请求体对应的方法参数序列化成字节数组rug28资讯网——每日最新资讯28at.com

而Decoder其实就是将响应体由字节流反序列化成方法返回值类型的对象rug28资讯网——每日最新资讯28at.com

Decoder默认情况下跟Encoder的默认情况是一样的,只支持反序列化成字节数组或者是Stringrug28资讯网——每日最新资讯28at.com

所以,Spring也同样实现了Decoder,扩展它的功能rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

可以将响应体对应的字节流反序列化成任意返回值类型对象rug28资讯网——每日最新资讯28at.com

4、Client

图片rug28资讯网——每日最新资讯28at.com

从接口方法的参数和返回值其实可以看出,这其实就是动态代理对象最终用来执行Http请求的组件rug28资讯网——每日最新资讯28at.com

默认实现就是通过JDK提供的HttpURLConnection来的rug28资讯网——每日最新资讯28at.com

除了这个默认的,Feign还提供了基于HttpClient和OkHttp实现的rug28资讯网——每日最新资讯28at.com

在项目中,要想替换默认的实现,只需要引入相应的依赖,在构建Feign.builder()时设置一下就行了rug28资讯网——每日最新资讯28at.com

SpringCloud环境底下会根据引入的依赖自动进行设置rug28资讯网——每日最新资讯28at.com

除了上述的三个实现,最最重要的当然是属于它基于负载均衡的实现rug28资讯网——每日最新资讯28at.com

如下是OpenFeign用来整合Ribbon的核心实现rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

这个Client会根据服务名,从Ribbon中获取一个服务实例的信息,也就是ip和端口rug28资讯网——每日最新资讯28at.com

之后会通过ip和端口向服务实例发送Http请求rug28资讯网——每日最新资讯28at.com

5、InvocationHandlerFactory

InvocationHandler我相信大家应该都不陌生rug28资讯网——每日最新资讯28at.com

对于JDK动态代理来说,必须得实现InvocationHandler才能创建动态代理rug28资讯网——每日最新资讯28at.com

InvocationHandler的invoke方法实现就是动态代理走的核心逻辑rug28资讯网——每日最新资讯28at.com

而InvocationHandlerFactory其实就是创建InvocationHandler的工厂rug28资讯网——每日最新资讯28at.com

所以,这里就可以猜到,通过InvocationHandlerFactory创建的InvocationHandler应该就是Feign动态代理执行的核心逻辑rug28资讯网——每日最新资讯28at.com

InvocationHandlerFactory默认实现是下面这个rug28资讯网——每日最新资讯28at.com

SpringCloud环境下默认也是使用它的这个默认实现rug28资讯网——每日最新资讯28at.com

所以,我们直接去看看InvocationHandler的实现类FeignInvocationHandlerrug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

从实现可以看出,除了Object类的一些方法,最终会调用方法对应的MethodHandler的invoke方法rug28资讯网——每日最新资讯28at.com

所以注意注意,这个MethodHandler就封装了Feign执行Http调用的核心逻辑,很重要,后面还会提到rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

虽然说默认情况下SpringCloud使用是默认实现,最终使用FeignInvocationHandlerrug28资讯网——每日最新资讯28at.com

但是当其它框架整合SpringCloud生态的时候,为了适配OpenFeign,有时会自己实现InvocationHandlerrug28资讯网——每日最新资讯28at.com

比如常见的限流熔断框架Hystrix和Sentinel都实现了自己的InvocationHandlerrug28资讯网——每日最新资讯28at.com

这样就可以对MethodHandler执行前后,也就是Http接口调用前后进行限流降级等操作。rug28资讯网——每日最新资讯28at.com

6、RequestInterceptor

图片图片rug28资讯网——每日最新资讯28at.com

RequestInterceptor它其实是一个在发送请求前的一个拦截接口rug28资讯网——每日最新资讯28at.com

通过这个接口,在发送Http请求之前再对Http请求的内容进行修改rug28资讯网——每日最新资讯28at.com

比如我们可以设置一些接口需要的公共参数,如鉴权token之类的rug28资讯网——每日最新资讯28at.com

@Componentpublic class TokenRequestInterceptor implements RequestInterceptor {    @Override    public void apply(RequestTemplate template) {        template.header("token", "token值");    }}

7、Retryer

这是一个重试的组件,默认实现如下rug28资讯网——每日最新资讯28at.com

默认情况下,最大重试5次rug28资讯网——每日最新资讯28at.com

在SpringCloud下,并没有使用上面那个实现,而使用的是下面这个实现rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

所以,SpringCloud下默认是不会进行重试rug28资讯网——每日最新资讯28at.com

小总结

这一节主要是介绍了7个Feign的核心组件以及Spring对应的扩展实现rug28资讯网——每日最新资讯28at.com

为了方便你查看,我整理了如下表格rug28资讯网——每日最新资讯28at.com

接口rug28资讯网——每日最新资讯28at.com

作用rug28资讯网——每日最新资讯28at.com

Feign默认实现rug28资讯网——每日最新资讯28at.com

Spring实现rug28资讯网——每日最新资讯28at.com

Contractrug28资讯网——每日最新资讯28at.com

解析方法注解和参数,将Http请求参数和方法参数对应rug28资讯网——每日最新资讯28at.com

Contract.Defaultrug28资讯网——每日最新资讯28at.com

SpringMvcContractrug28资讯网——每日最新资讯28at.com

Encoderrug28资讯网——每日最新资讯28at.com

将请求体对应的方法参数序列化成字节数组rug28资讯网——每日最新资讯28at.com

Encoder.Defaultrug28资讯网——每日最新资讯28at.com

SpringEncoderrug28资讯网——每日最新资讯28at.com

Decoderrug28资讯网——每日最新资讯28at.com

将响应体的字节流反序列化成方法返回值类型对象rug28资讯网——每日最新资讯28at.com

Decoder.Defaultrug28资讯网——每日最新资讯28at.com

SpringDecoderrug28资讯网——每日最新资讯28at.com

Clientrug28资讯网——每日最新资讯28at.com

发送Http请求rug28资讯网——每日最新资讯28at.com

Client.Defaultrug28资讯网——每日最新资讯28at.com

LoadBalancerFeignClientrug28资讯网——每日最新资讯28at.com

InvocationHandlerFactoryrug28资讯网——每日最新资讯28at.com

InvocationHandler工厂,动态代理核心逻辑rug28资讯网——每日最新资讯28at.com

InvocationHandlerFactory.Defaultrug28资讯网——每日最新资讯28at.com

rug28资讯网——每日最新资讯28at.com

RequestInterceptorrug28资讯网——每日最新资讯28at.com

在发送Http请求之前,再对Http请求的内容进行拦截修改rug28资讯网——每日最新资讯28at.com

rug28资讯网——每日最新资讯28at.com

rug28资讯网——每日最新资讯28at.com

Retryerrug28资讯网——每日最新资讯28at.com

重试组件rug28资讯网——每日最新资讯28at.com

Retryer.Defaultrug28资讯网——每日最新资讯28at.com

rug28资讯网——每日最新资讯28at.com

除了这些之外,还有一些其它组件这里就没有说了rug28资讯网——每日最新资讯28at.com

比如日志级别Logger.Level,日志输出Logger,有兴趣的可以自己查看rug28资讯网——每日最新资讯28at.com

Feign核心运行原理分析

上一节说了Feign核心组件,这一节我们来讲一讲Feign核心运行原理,主要分为两部分内容:rug28资讯网——每日最新资讯28at.com

  • 动态代理生成原理
  • 一次Feign的Http调用执行过程

1、动态代理生成原理

这里我先把上面的Feign原始使用方式的Demo代码再拿过来rug28资讯网——每日最新资讯28at.com

public class FeignDemo {    public static void main(String[] args) {        OrderApiClient orderApiClient = Feign.builder()                .target(OrderApiClient.class, "http://localhost:8088");        orderApiClient.queryOrder(9527L);    }}

通过Demo可以看出,最后是通过Feign.builder().target(xx)获取到动态代理的rug28资讯网——每日最新资讯28at.com

而上述代码执行逻辑如下所示:rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

最终会调用ReflectiveFeign的newInstance方法来创建动态代理对象rug28资讯网——每日最新资讯28at.com

而ReflectiveFeign内部设置了前面提到的一些核心组件rug28资讯网——每日最新资讯28at.com

接下我们来看看newInstance方法rug28资讯网——每日最新资讯28at.com

这个方法主要就干两件事:rug28资讯网——每日最新资讯28at.com

第一件事首先解析接口,构建每个方法对应的MethodHandlerrug28资讯网——每日最新资讯28at.com

MethodHandler在前面讲InvocationHandlerFactory特地提醒过rug28资讯网——每日最新资讯28at.com

动态代理(FeignInvocationHandler)最终会调用MethodHandler来处理Feign的一次Http调用rug28资讯网——每日最新资讯28at.com

在解析接口的时候,就会用到前面提到的Contract来解析方法参数和注解,生成MethodMetadata,这里我代码我就不贴了rug28资讯网——每日最新资讯28at.com

第二件事通过InvocationHandlerFactory创建InvocationHandlerrug28资讯网——每日最新资讯28at.com

然后再构建出接口的动态代理对象rug28资讯网——每日最新资讯28at.com

ok,到这其实就走完了动态代理的生成过程rug28资讯网——每日最新资讯28at.com

所以动态代理生成逻辑很简单,总共也没几行代码,画个图来总结一下rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

2、一次Feign的Http调用执行过程

前面说了,调用接口动态代理的方式时,通过InvocationHandler(FeignInvocationHandler),最终交给MethodHandler的invoke方法来执行rug28资讯网——每日最新资讯28at.com

MethodHandler是一个接口,最终会走到它的实现类SynchronousMethodHandler的invoke方法实现rug28资讯网——每日最新资讯28at.com

SynchronousMethodHandler中的属性就是我们前面提到的一些组件rug28资讯网——每日最新资讯28at.com

由于整个代码调用执行链路比较长,这里我就不截代码了,有兴趣的可以自己翻翻rug28资讯网——每日最新资讯28at.com

不过这里我画了一张图,可以通过这张图来大致分析整个Feign一次Http调用的过程rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

  • 首先就是前面说的,进入FeignInvocationHandler,找到方法对应的SynchronousMethodHandler,调用invoke方法实现
  • 之后根据MethodMetadata和方法的入参,构造出一个RequestTemplate,RequestTemplate封装了Http请求的参数,在这个过程中,如果有请求体,那么会通过Encoder序列化
  • 然后调用RequestInterceptor,通过RequestInterceptor对RequestTemplate进行拦截扩展,可以对请求数据再进行修改
  • 再然后将RequestTemplate转换成Request,Request其实跟RequestTemplate差不多,也是封装了Http请求的参数
  • 接下来通过Client去根据Request中封装的Http请求参数,发送Http请求,得到响应Response
  • 最后根据Decoder,将响应体反序列化成方法返回值类型对象,返回

这就是Feign一次Http调用的执行过程rug28资讯网——每日最新资讯28at.com

如果有设置重试,那么也是在这个阶段生效的rug28资讯网——每日最新资讯28at.com

SpringCloud是如何整合Feign的?

SpringCloud在整合Feign的时候,主要是分为两部分rug28资讯网——每日最新资讯28at.com

  • 核心组件重新实现,支持更多SpringCloud生态相关的功能
  • 将接口动态代理对象注入到Spring容器中

第一部分核心组件重新实现前面已经都说过了,这里就不再重复了rug28资讯网——每日最新资讯28at.com

至于第二部分我们就来好好讲一讲,Spring是如何将接口动态代理对象注入到Spring容器中的rug28资讯网——每日最新资讯28at.com

1、将FeignClient接口注册到Spring中

使用OpenFeign时,必须加上@EnableFeignClientsrug28资讯网——每日最新资讯28at.com

这个注解就是OpenFeign的发动机rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

@EnableFeignClients最后通过@Import注解导入了一个FeignClientsRegistrarrug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

FeignClientsRegistrar实现了ImportBeanDefinitionRegistrarrug28资讯网——每日最新资讯28at.com

所以最终Spring在启动的时候会调用registerBeanDefinitions方法实现rug28资讯网——每日最新资讯28at.com

之所以会调用registerBeanDefinitions方法,是@Import注解的作用,不清楚的同学可以看一下扒一扒Bean注入到Spring的那些姿势,你会几种?rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

最终会走到registerFeignClients这个方法rug28资讯网——每日最新资讯28at.com

这个方法虽然比较长,主要是干了下面这个2件事:rug28资讯网——每日最新资讯28at.com

第一件事,扫描@EnableFeignClients所在类的包及其子包(如果有指定包就扫指定包),找出所有加了@FeignClient注解的接口,生成一堆BeanDefinitionrug28资讯网——每日最新资讯28at.com

这个BeanDefinition包含了这个接口的信息等信息rug28资讯网——每日最新资讯28at.com

第二件事,将扫描到的这些接口注册到Spring容器中rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

在注册的时候,并非直接注册接口类型,而是FeignClientFactoryBean类型rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

好了,到这整个@EnableFeignClients启动过程就结束了rug28资讯网——每日最新资讯28at.com

虽然上面写的很长,但是整个@EnableFeignClients其实也就只干了一件核心的事rug28资讯网——每日最新资讯28at.com

扫描到所有的加了@FeignClient注解的接口rug28资讯网——每日最新资讯28at.com

然后为每个接口生成一个Bean类型为FeignClientFactoryBean的BeanDefinitionrug28资讯网——每日最新资讯28at.com

最终注册到Spring容器中rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

2、FeignClientFactoryBean的秘密

上一节说到,每个接口都对应一个class类型为FeignClientFactoryBean的BeanDefinitionrug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

如上所示,FeignClientFactoryBean是一个FactoryBeanrug28资讯网——每日最新资讯28at.com

并且FeignClientFactoryBean的这些属性,是在生成BeanDefinition的时候设置的rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

并且这个type属性就是代表的接口类型rug28资讯网——每日最新资讯28at.com

由于实现了FactoryBean,所以Spring启动过程中,一定为会调用getObject方法获取真正的Bean对象rug28资讯网——每日最新资讯28at.com

FactoryBean的作用就不说了,不清楚的小伙伴还是可以看看扒一扒Bean注入到Spring的那些姿势,你会几种?这篇文章rug28资讯网——每日最新资讯28at.com

getObject最终会走到getTarget()方法rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

从如上代码其实可以看出来,最终还是会通过Feign.builder()来创建动态代理对象rug28资讯网——每日最新资讯28at.com

只不过不同的是,SpringCloud会替换Feign默认的组件,改成自己实现的rug28资讯网——每日最新资讯28at.com

总的来说,Spring是通过FactoryBean的这种方式,将Feign动态代理对象添加到Spring容器中rug28资讯网——每日最新资讯28at.com

OpenFeign的各种配置方式以及对应优先级

既然Feign核心组件可以替换,那么在SpringCloud环境下,我们该如何去配置自己的组件呢?rug28资讯网——每日最新资讯28at.com

不过在说配置之前,先说一下FeignClient配置隔离操作rug28资讯网——每日最新资讯28at.com

在SpringCloud环境下,为了让每个不同的FeignClient接口配置相互隔离rug28资讯网——每日最新资讯28at.com

在应用启动的时候,会为每个FeignClient接口创建一个Spring容器,接下来我就把这个容器称为FeignClient容器rug28资讯网——每日最新资讯28at.com

这些FeignClient的Spring容器有一个相同的父容器,那就是项目启动时创建的容器rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

SpringCloud会给每个FeignClient容器添加一个默认的配置类FeignClientsConfiguration配置类rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

这个配置类就声明了各种Feign的组件rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

所以,默认情况下,OpenFeign就使用这些配置的组件构建代理对象rug28资讯网——每日最新资讯28at.com

知道配置隔离之后,接下来看看具体的几种方式配置以及它们之间的优先级关系rug28资讯网——每日最新资讯28at.com

1、通过@EnableFeignClients注解的defaultConfiguration属性配置

举个例子,比如我自己手动声明一个Contract对象,类型为MyContractrug28资讯网——每日最新资讯28at.com

public class FeignConfiguration {        @Bean    public Contract contract(){        return new MyContract();    }    }

注意注意,这里FeignConfiguration我没加@Configuration注解,原因后面再说rug28资讯网——每日最新资讯28at.com

此时配置如下所示:rug28资讯网——每日最新资讯28at.com

@EnableFeignClients(defaultConfiguration = FeignConfiguration.class)

之后这个配置类会被加到每个FeignClient容器中,所以这个配置是对所有的FeignClient生效rug28资讯网——每日最新资讯28at.com

并且优先级大于默认配置的优先级rug28资讯网——每日最新资讯28at.com

比如这个例子就会使得FeignClient使用我声明的MyContract,而不是FeignClientsConfiguration中声明的SpringMvcContractrug28资讯网——每日最新资讯28at.com

2、通过@FeignClient注解的configuration属性配置

还以上面的FeignConfiguration配置类举例,可以通过@FeignClient注解配置rug28资讯网——每日最新资讯28at.com

@FeignClient(name = "order", configuration = FeignConfiguration.class)

此时这个配置类会被加到自己FeignClient容器中,注意是自己FeignClient容器rug28资讯网——每日最新资讯28at.com

所以这种配置的作用范围是自己的这个FeignClientrug28资讯网——每日最新资讯28at.com

并且这种配置的优先级是大于@EnableFeignClients注解配置的优先级rug28资讯网——每日最新资讯28at.com

3、在项目启动的容器中配置

前面提到,由于所有的FeignClient容器的父容器都是项目启动的容器rug28资讯网——每日最新资讯28at.com

所以可以将配置放在这个项目启动的容器中rug28资讯网——每日最新资讯28at.com

还以FeignConfiguration为例,加上@Configuration注解,让项目启动的容器的扫描到就成功配置了rug28资讯网——每日最新资讯28at.com

这种配置的优先级大于前面提到的所有配置优先级rug28资讯网——每日最新资讯28at.com

并且是对所有的FeignClient生效rug28资讯网——每日最新资讯28at.com

所以,这就是为什么使用注解配置时为什么配置类不能加@Configuration注解的原因,因为一旦被项目启动的容器扫描到,这个配置就会作用于所有的FeignClient,并且优先级是最高的,就会导致你其它的配置失效,当然你也可以加@Configuration注解,但是一定不能被项目启动的容器扫到rug28资讯网——每日最新资讯28at.com

4、配置文件

除了上面3种编码方式配置,OpenFeign也是支持通过配置文件的方式进行配置rug28资讯网——每日最新资讯28at.com

并且也同时支持对所有FeignClient生效和对单独某个FeignClient生效rug28资讯网——每日最新资讯28at.com

对所有FeignClient生效配置:rug28资讯网——每日最新资讯28at.com

feign:  client:    config:      default: # default 代表对全局生效        contract: com.sanyou.feign.MyContract

对单独某个FeignClient生效配置:rug28资讯网——每日最新资讯28at.com

feign:  client:    config:      order: # 具体的服务名        contract: com.sanyou.feign.MyContract

在默认情况下,这种配置文件方式优先级最高rug28资讯网——每日最新资讯28at.com

但是如果你在配置文件中将配置项feign.client.default-to-properties设置成false的话,配置文件的方式优先级就是最低了rug28资讯网——每日最新资讯28at.com

feign:  client:    default-to-properties: false

小总结

这一节,总共总结了4种配置OpenFeign的方式以及它们优先级和作用范围rug28资讯网——每日最新资讯28at.com

画张图来总结一下rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

如果你在具体使用的时候,还是遇到了一些优先级的问题,可以debug这部分源码,看看到底生效的是哪个配置rug28资讯网——每日最新资讯28at.com


rug28资讯网——每日最新资讯28at.com

图片图片rug28资讯网——每日最新资讯28at.com

图片 rug28资讯网——每日最新资讯28at.com

本文链接://www.dmpip.com//www.dmpip.com/showinfo-26-75334-0.html33张图探秘OpenFeign核心架构原理

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 在Golang中简化日志记录:提升性能和调试效率

下一篇: 使用原生cookieStore方法,让Cookie操作更简单

标签:
  • 热门焦点
Top
Baidu
map