Feign源码学习(4)— Feign Client的动态代理机制

376 阅读1分钟

一、如何来创建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代理接口进行代理类的生成。