本文已参与「新人创作礼」活动,一起开启掘金创作之路。
6. 创建feign动态代理
基于Feign.Builder和HardCodedTarget,通过JDK原生动态代理机制,针对接口创建动态代理对象。
Targeter
在FeignAutoConfiguration中,创建Targeter子类HystrixTargeter。
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")
protected static class HystrixFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new HystrixTargeter();
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
protected static class DefaultFeignTargeterConfiguration {
@Bean
@ConditionalOnMissingBean
public Targeter feignTargeter() {
return new DefaultTargeter();
}
}
如果有feign.hystrix.HystrixFeign这个类的话,那么就会构造一个HystrixTargeter出来;如果没有feign.hystrix.HystrixFeign这个类的话,那么就会构造一个DefaultTargeter出来
Feign.Builder
启用feign.hystrix.enabled,feign与hystrix整合,使用HystrixFeign.Builder。
默认的情况下,Feign.Builder使用feign原生的Feign.Builder。
ParseHandlersByName
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
targetToHandlersByName(ParseHandlersByName)基于配置的Contract, Options, Encoder, Decoder, QueryMapEncoder, ErrorDecoder, SynchronousMethodHandler.Factory等组件,应用到Target对象(HardCodedTarget(type=ProductFacadeServiceFeign, name=eureka-provider-ribbon-feign-api-impl, url=http://eureka-provider-ribbon-feign-api-impl)),解析接口上所有的Spring Mvc的注解,以及接口中各个方法封装成MethodHandler(SynchronousMethodHandler:同步方法代理处理器组件),返回方法名与方法处理器的map
遍历ProductFacadeServiceFeign接口中的每个方法,重新映射成方法对象与方法处理器的map(动态代理中作为Method对象的dispatch)
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
nameToHandler:接口中的每个方法的名称,对应一个处理方法的SynchronousMethodHandler
methodToHandler:接口中的每个方法对应的Method对象,对应一个处理方法的SynchronousMethodHandler
// InvocationHandlerFactory factory
InvocationHandler handler = factory.create(target, methodToHandler);
基于InvocationHandlerFactory工厂,创建一个动态代理InvocationHandler调用处理器。
static final class Default implements InvocationHandlerFactory {
@Override
public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
}
}
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[] {target.type()}, handler);
基于JDK的动态代理,创建一个动态代理Proxy。Proxy实现ProductFacadeServiceFeign接口。
new Class<?>[]{target.type()}:是ProductFacadeServiceFeign接口。基于JDK动态代理的机制,创建一个实现ProductFacadeServiceFeign接口的动态代理对象。
handler:InvocationHandler实现类。针对ProductFacadeServiceFeign的proxy动态代理类,所有方法的调用,都经过InvocationHandler的invoke()方法拦截处理,由InvocationHandler.invoke()方法提供所有方法的实现逻辑。