ReflectiveFeign
- 從
Feign
的使用方法我們可以推測阶牍,它的內(nèi)部實現(xiàn)是利用了Java反射解析Api
方法上的參數(shù)與注解,生成代理實現(xiàn)類缰犁。所以Feign
的實現(xiàn)類名稱就叫作ReflectiveFeign
鹃共。
/**
* ReflectiveFeign.newInstance 生成proxy代理實現(xiàn)的主邏輯
* @param Target<T> 在Feign.target中傳入的代理目標(biāo)Class與host url參數(shù)
*/
public <T> T newInstance(Target<T> target) {
//核心邏輯入口,反射解析目標(biāo)Class垛叨,得到MethodHandler集合
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
for (Method method : target.type().getMethods()) {
//Object的方法(如toString之類的)就無視
if (method.getDeclaringClass() == Object.class) {
continue;
}
//Default方法處理
else if(Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
}
//Http請求代理方法
else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
//主要邏輯,生成proxy柜某,實現(xiàn)其中的Rest請求方法嗽元。
//InvocationHandler實現(xiàn)類為FeignInvocationHandler
InvocationHandler handler = factory.create(target, methodToHandler);
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);
//處理其他默認(rèn)方法,綁定到Proxy上
for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
-
ReflectiveFeign.newInstance
主要分為兩塊邏輯:
1.反射解析代理目標(biāo)Class
的Method
與注解,得到MethodHandler
莺琳。
2.生成Proxy
對象,綁定Proxy
的方法實現(xiàn)载慈。
- 如何從代理目標(biāo)
Class
中解析出要實現(xiàn)的HTTP
調(diào)用方法惭等,則是整個Feign
框架的核心業(yè)務(wù)。完成這個工作的是ParseHandlersByName.apply
方法 办铡。
- 將解析的結(jié)果綁定到
Proxy
對象辞做,基本上按照Java
代理的標(biāo)準(zhǔn)模式處理琳要。主要實現(xiàn)邏輯在FeignInvocationHandler
中。
FeignInvocationHandler
- 先從結(jié)果開始分析秤茅,
ParseHandlersByName.apply
解析出來的結(jié)果MethodHandler
是一個抽象接口:
interface MethodHandler {
Object invoke(Object[] argv) throws Throwable;
}
- 因為這個結(jié)果最后使用在代理綁定中稚补,所以對外暴露方法只需要一個
invoke
就足夠了。
-
FeignInvocationHandler
是Java
代理中java.lang.reflect.InvocationHandler
的實現(xiàn)類框喳,實現(xiàn)了代理對象中方法需要完成的邏輯:
//FeignInvocationHandler部分代碼
static class FeignInvocationHandler implements InvocationHandler {
//代理目標(biāo)Class
private final Target target;
//持有前面解析出來的MethodHandler集合
private final Map<Method, MethodHandler> dispatch;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//一些特殊方法的處理
if ("equals".equals(method.getName())) {
try {
Object otherHandler =
args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return equals(otherHandler);
} catch (IllegalArgumentException e) {
return false;
}
} else if ("hashCode".equals(method.getName())) {
return hashCode();
} else if ("toString".equals(method.getName())) {
return toString();
}
//Rest請求方法調(diào)用课幕,并返回結(jié)果
return dispatch.get(method).invoke(args);
}
}
-
InvocationHandler
中只有一個invoke
方法需要實現(xiàn),入?yún)⑹钦{(diào)用的方法標(biāo)識與調(diào)用參數(shù)五垮,返回結(jié)果乍惊。
-
FeignInvocationHandler
的工作就是找到要執(zhí)行方法的代理MethodHandler
,調(diào)用并return
放仗。
- 這樣
FeignInvocationHandler
就可以參與到生成Proxy
的實現(xiàn)中去润绎。
- 看到這里我們就可以發(fā)現(xiàn),真正發(fā)生
Rest
請求調(diào)用的是在MethodHandler
的實現(xiàn)類SynchronousMethodHandler
中。
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者