#Feign
Fiegn包含以下组件
Contract:Defines what annotations and values are valid on interfaces.
Client:具体执行HTTP请求的地方,传入Request对象,获得Response对象;RequestTemplate对象用来Build一个Request对象,传递给Client对象,Client执行请求之前,可以被RequestInterceptor处理,得到Response请求之后可以被ResponseMapper处理;
Retryer
Logger
Encoder
Decoder
ErrorDecoder
Target:就是要处理的接口类,有两个实现EmptyTarget和HardCodedTarget
RequestTemplate:每个方法在每次调用时都会先生成这个对象,生成这个对象的信息来自每个方法对应的MethodMetadata对象;

代理模块

ReflectiveFeign和SynchronousMethodHandler
InvocationHandler:Feign启动时,给一个Target创建一个FeignInvocationHandler对象,此类有个工厂类InvocationHandlerFactory;
Fiegn启动过程:
1.Feign.build()的时候,其实是生成了一个ReflectiveFeign对象;
2.接着调用public T newInstance(Target target),处理这个Target,处理过程如下
3.遍历这个Target的所有方法,为每一个方法生成一个SynchronousMethodHandler对象,将方法签名和辞方法的SynchronousMethodHandler对应关系存储到Map对象中;
4.InvocationHandlerFactory传入辞Target和上面的Map,生成一个InvocationHandler对象;这个对象的具体实现是ReflectiveFeign.FeignInvocationHandler;
5.用上面生成的ReflectiveFeign.FeignInvocationHandler对象,为当前处理的Target生成一个代理;
FiegnTarget方法调用处理流程
1.前面提到Feign启动时会为每一个Target生成一个代理对象,这个代理对象的InvocationHandler是ReflectiveFeign.FeignInvocationHandler;
2.当调用Target的某个方法时,会进入到ReflectiveFeign.FeignInvocationHandler的invoke方法;
3.这个方法的主要逻辑就是根据根据当前调用的Method,从存储方法签名和辞方法的SynchronousMethodHandler对应关系到Map对象中,取出SynchronousMethodHandler对象,然后调用SynchronousMethodHandler对象的invoke方法
4.SynchronousMethodHandler对象中持有当前调用的方法的MethodMetadata,当前的Target对象,发起Http请求的Client对象,Retryer…等等,在SynchronousMethodHandler对象的invoke方法中会直接发起请求,并处理请求响应;
5.SynchronousMethodHandler的invoke方法返回的结果,就是调用Target的业务方法的结果;

Annotation

@RequestLine
@Headers
@HeaderMap
@Body
@Param
@QueryMap

Feign & Ribbon

Feign 提供了一个feign-ribbon模块用来使用Ribbon的客户端负载均衡能力;

ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
GitHubService service = Feign.builder().client(RibbonClient.create()).decoder(new GsonDecoder())
.target(LoadBalancingTarget.create(GitHubService.class, GitHubService.URL));
List<Contributor> contributors = service.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.getLogin() + " (" + contributor.getContributions() + ")");
}
ConfigurationManager.loadPropertiesFromResources("sample-client.properties");
GitHubService service = Feign.builder().client(RibbonClient.create()).decoder(new GsonDecoder())
.target(GitHubService.class, GitHubService.URL);
List<Contributor> contributors = service.contributors("OpenFeign", "feign");
for (Contributor contributor : contributors) {
System.out.println(contributor.getLogin() + " (" + contributor.getContributions() + ")");
}

Spring Cloud Feign

FeignContext:A factory that creates instances of feign classes. It creates a Spring ApplicationContext per client name, and extracts the beans that it needs from there.
@FeignClient中可以配置一个configuration类,功能就是依赖上边的能力实现的,为每个FiegnClient创建一个子IOC容器;默认的配置是FeignClientsConfiguration类;
SpringMvcContract:我们在FeignClient的方法上写RequestMapping之所以生效,就是因为这个类;
@PathVariable/@RequestHeader/@RequestParam的处理逻辑是PathVariableParameterProcessor/RequestHeaderParameterProcessor/RequestParamParameterProcessor实现的,这三个类最终会在SpringMvcContract被调用处理对应的注解;

Spring Cloud Netflix Feign & Spring Cloud Netflix Ribbon

Spring Cloud Netflix Feign是模仿feign-ribbon模块的模式,重新实现了一遍接口;
LoadBalancerFeignClient:Spring Cloud Netflix Feign 实现了Feign的Client接口;LoadBalancerFeignClient的execute方法使用的是FeignLoadBalancer接口的executeWithLoadBalancer方法请求的接口;
FeignLoadBalancer:AbstractLoadBalancingClient的实现,真正发生HTTP 请求的地方;

参考

​retrofit​​​​feign​​​​spring-cloud-openfeign​​​​SpringCloud之Feign(一) ​​​​SpringCloud之Feign(二) ​​​​深入理解Feign之源码解析​​​​spring环境中Feign + Ribbon的使用​