1.spring-cloud-openfeign概述
在官方文档中,feign的定义是:Feign是一种声明式、模板化的HTTP客户端。
Spring Cloud OpenFeign作为Spring Cloud的子项目,为微服务架构下服务之间的调用提供了解决方案。
Feign的核心特性如下图所示:
2.Feign接口调用过程
调用过程如下图所示:
3.feign-client配置
配置类为org.springframework.cloud.openfeign.FeignClientProperties,在spring-cloud-openfeign-core包中定义。
feign:
client:
config:
feignName:
connectTimeout: 5000
readTimeout: 5000
loggerLevel: full
errorDecoder: com.example.SimpleErrorDecoder
retryer: com.example.SimpleRetryer
defaultQueryParameters:
query: queryValue
defaultRequestHeaders:
header: headerValue
requestInterceptors:
- com.example.FooRequestInterceptor
- com.example.BarRequestInterceptor
decode404: false
encoder: com.example.SimpleEncoder
decoder: com.example.SimpleDecoder
contract: com.example.SimpleContract
capabilities:
- com.example.FooCapability
- com.example.BarCapability
queryMapEncoder: com.example.SimpleQueryMapEncoder
metrics.enabled: false
具体配置的使用可查看https://docs.spring.io/spring-cloud-openfeign/docs/current/reference/html/
4.feign-client调用过程
下面,我们从初始化到调用过程做详细的介绍。
4.1.FeignClient初始化为Spring bean过程
在spring cloud中,FeignClient是以单例形态存在的,也是一个Spring bean。初始化过程如下所示:
FeignClientsRegistrar#registerBeanDefinitions
FeignClientsRegistrar#registerDefaultConfiguration
FeignClientsRegistrar#registerFeignClients
获取所有被@FeignClient注解的类,并针对每个类进行注册
FeignClientsRegistrar#registerFeignClient
BeanDefinitionBuilder#genericBeanDefinition
设置BeanDefinition相关参数,这个BeanDefinition的指定的class类型是FeignClientFactoryBean
BeanDefinitionReaderUtils#registerBeanDefinition
org.springframework.cloud.openfeign.FeignClientFactoryBean这个类实现了FactoryBean接口。spring在生成bean的时候,判断BeanDefinition中bean的class如果是FactoryBean的实现的话,会调用这个实现类的getObject来获取对象。
org.springframework.cloud.openfeign.FeignClientsRegistrar类实现了ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar主要用于实现“动态注册bean”功能,所有实现了该接口的类的都会被ConfigurationClassPostProcessor处理,ConfigurationClassPostProcessor实现了BeanFactoryPostProcessor接口,所以ImportBeanDefinitionRegistrar中动态注册的bean是优先与依赖其的bean初始化的,也能被aop、validator等机制处理。
4.2.FeignClient方法调用过程
如果想要调用feign api,首先需要获取对应的FeignClient bean。
4.2.1.FeignClient对象获取
上面说到,所有的FeignClient在spring容器中是以FeignClientFactoryBean身份存在的,如果要获取该FeignClient,比如通过@Autowired进行获取,则会调用FeignClientFactoryBean.getObject方法进行获取。
具体流程如下图所示:
Targeter有两个实现类:DefaultTargeter和FeignCircuitBreakerTargeter。
最终返回的是feign.ReflectiveFeign对象,ReflectiveFeign对象中包含各种FeignClient接口中方法的methodHandler,并通过Proxy.newProxyInstance创建代理对象的实例,代理方法的执行由FeignInvocationHandler类来实现。
4.2.2.FeignClient方法调用
方法调用时,由对应代理对象来实现,当调用FeignClient的某个方法时,会触发对应的InvocationHandler#invoke方法。具体的调用链路如下所示:
xxxFeignClient
feign.ReflectiveFeign.FeignInvocationHandler#invoke
feign.InvocationHandlerFactory.MethodHandler#invoke
feign.SynchronousMethodHandler#invoke
feign.SynchronousMethodHandler#executeAndDecode
org.springframework.cloud.openfeign.loadbalancer.FeignBlockingLoadBalancerClient#execute
feign.Client.Default#execute
feign.AsyncResponseHandler#handleResponse