一、如何来创建Feign Client动态代理
上一讲提到Feign Client是怎么样基于Target来动态代理创建对应的实现的。
protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
HardCodedTarget<T> target) {
Client client = getOptional(context, Client.class);
if (client != null) {
builder.client(client);
Targeter targeter = get(context, Targeter.class);
return targeter.target(this, builder, context, target);
}
throw new IllegalStateException(
"No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
提到loadBalance方法,最后是调用了targeter.target(this, builder, context, target)
然后,Targeter是一个接口,底层是:
interface Targeter {
<T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
Target.HardCodedTarget<T> target);
}
再看看,他的实现类有两个
那么,哪个是Targetr的实现呢,很明显,默认的就是 DefaultTargeter
这里的我还不是瞎猜的,是看了源码发现,如果我们在不打开Hystrix的情况下,用的就是DefaultTargeter 。源码如下:
DefaultTargeter 代码如下:
class DefaultTargeter implements Targeter {
@Override
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign, FeignContext context,
Target.HardCodedTarget<T> target) {
return feign.target(target);
}
}
调用的是 Feign#target 方法
public <T> T target(Target<T> target) {
return build().newInstance(target);
}
接着是 ReflectiveFeign#newInstance
/**
** 这里的target就是刚刚所说的 HardCodedTarget
*/
@Override
public <T> T newInstance(Target<T> target) {
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
// 从HardCodedTarget 中去获取对应的方法
for (Method method : target.type().getMethods()) {
if (method.getDeclaringClass() == Object.class) {
continue;
} else if (Util.isDefault(method)) {
DefaultMethodHandler handler = new DefaultMethodHandler(method);
defaultMethodHandlers.add(handler);
methodToHandler.put(method, handler);
} else {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
// 生成InvocationHandler ,需要注意的是,这个类是jdk的动态代理
InvocationHandler handler = factory.create(target, methodToHandler);
// 通过动态代理,生成动态代理的类,target.type = ServiceAFeign
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class<?>[] {target.type()}, handler);
// methHandler绑定好动态代理类
for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
// 最后返回动态代理的类
return proxy;
}
分析: 我们看到InvocationHandler,他本身就是JDK的动态代理的核心。
所以这个方法的意思是说,Feign底层就是通过JDK的动态代理,来对这个Feign代理接口进行代理类的生成。