一、前言
今天在项目中遇见了Feign.Builder并通过内部的拦截器对feign接口做了一些配置,比较感兴趣,所以去特地了解了一下Feign.Builder的简要原理,在此记录一下,后面会慢慢去尝试读取源码并分享:
feign.Feign它是最上层的API,是使用者直接使用的对象,它能完成对接口生成动态代理对象,从而很方面的让你面向接口编程,而不用太过例会Feign内部的实现细节。
二、feign.Feign
Feign的目的是简化针对rest的Http Api的开发。在实现中,Feign是一个用于生成目标实例Feign.newInstance()的工厂,这个生成的实例便是接口的代理对象。
该类是个抽象类:
public abstract class Feign {
// 唯一的public的抽象方法,用于为目标target创建一个代理对象实例
public abstract <T> T newInstance(Target<T> target);
// -----------------静态方法-----------------
// 工具方法,生成configKey
// MethodMetadata#configKey属性的值就来自于此方法
public static String configKey(Class targetType, Method method) {
... }
// Feign的实例统一,有且只能通过builder构建,文下有详解,它是重点
public static Builder builder() {
return new Builder();
}
}
feign.Feign它有且仅有一个唯一实现类ReflectiveFeign,但这个实现类并不面向使用者,使用者只需用Builder构建,面向接口/抽象类编程足矣。
三、ParseHandlersByName
在接触ReflectiveFeign之前,我认为很有必要了解下它。
该类有且仅提供一个方法:将feign.Target转为Map<String, MethodHandler>,就是说为每一个configKey(其实就是一个Method),找到一个处理它的MethodHandler。
首先展示一下类和大概的理解,然后我们细细的理解:
static final class ParseHandlersByName {
// 提取器
private final Contract contract;
private final Options options;
private final Encoder encoder;
private final Decoder decoder;
private final ErrorDecoder errorDecoder;
private final QueryMapEncoder queryMapEncoder;
// 这个工厂只产生SynchronousMethodHandler实例
// 从这也很好理解:所有的Method最终的处理器都是SynchronousMethodHandler
private final SynchronousMethodHandler.Factory factory;
... // 省略构造器
public Map<String, MethodHandler> apply(Target key) {
// 通过Contract提取出该类所有方法的元数据信息:MethodMetadata
// 它会解析注解,不同的实现支持的注解是不一样的
List<MethodMetadata> metadata = contract.parseAndValidatateMetadata(key.type());
// 一个方法一个方法的处理,生成器对应的MethodHandler处理器
// 上篇文章有讲过,元数据都是交给RequestTemplate.Factory去构建成为一个请求模版的
Map<String, MethodHandler> result = new LinkedHashMap<>();
for (MethodMetadata md : metadata) {
// 这里其实我觉得使用接口RequestTemplate.Factory buildTemplate更加的合适
BuildTemplateByResolvingArgs buildTemplate;
// 针对不同元数据参数,调用不同的RequestTemplate.Factory实现类完成处理
if (!md.formParams().isEmpty() && md.template().