在Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean分析到,通过@Autowired
或者@Resource
注入FeignClient
实例的时候,实际上返回的是JDK动态代理对象,具体的实现逻辑在InvocationHandler
的invoke方法中
回看ReflectiveFeign.newInstance()
方法
public <T> T newInstance(Target<T> target) {
//返回的是feign接口方法名和MethodHandler的对应map
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
//存放feign接口方法和MethodHandler的对应map
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap<Method, MethodHandler>();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList<DefaultMethodHandler>();
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 {
//key是方法,value是从nameToHandler取出来的MethodHandler
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
//这里创建的是FeignInvocationHandler
InvocationHandler handler = factory.create(target, methodToHandler);
T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(),
new Class<?>[] {target.type()}, handler);
for (DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
targetToHandlersByName#apply()
public Map<String, MethodHandler> apply(Target target) {
//拿到feign接口的所有属性集合
List<MethodMetadata> metadata = contract.parseAndValidateMetadata(target.type());
Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();
for (MethodMetadata md : metadata) {
......
if (md.isIgnored()) {
result.put(md.configKey(), args -> {
throw new IllegalStateException(md.configKey() + " is not a method handled by feign");
});
} else {
//key--TestFeign#test(),value--SynchronousMethodHandler对象
result.put(md.configKey(),
factory.create(target, md, buildTemplate, options, decoder, errorDecoder));
}
}
return result;
}
}
FeignInvocationHandler#invoke()
static class FeignInvocationHandler implements InvocationHandler {
private final Target target;
private final Map<Method, MethodHandler> dispatch;
FeignInvocationHandler(Target target, Map<Method, MethodHandler> dispatch) {
this.target = checkNotNull(target, "target");
this.dispatch = checkNotNull(dispatch, "dispatch for %s", target);
}
@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();
}
//dispatch就是之前说到的methodToHandler的map集合
//这里通过method得到MethodHandler实际是SynchronousMethodHandler,再调用invoke方法
return dispatch.get(method).invoke(args);
}
}
SynchronousMethodHandler#invoke()
public Object invoke(Object[] argv) throws Throwable {
//构建RequestTemplate对象,处理HTTP请求
RequestTemplate template = buildTemplateFromArgs.create(argv);
Options options = findOptions(argv);
//创建重试对象Retryer
Retryer retryer = this.retryer.clone();
//循环重试调用
while (true) {
try {
//实际调用方法
return executeAndDecode(template, options);
} catch (RetryableException e) {
try {
//处理重试
retryer.continueOrPropagate(e);
} catch (RetryableException th) {
Throwable cause = th.getCause();
if (propagationPolicy == UNWRAP && cause != null) {
throw cause;
} else {
throw th;
}
}
if (logLevel != Logger.Level.NONE) {
logger.logRetry(metadata.configKey(), logLevel);
}
continue;
}
}
}
SynchronousMethodHandler#executeAndDecode()
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
Request request = targetRequest(template);
Response response;
long start = System.nanoTime();
try {
//实际调用execute方法执行调用请求
response = client.execute(request, options);
// ensure the request is set. TODO: remove in Feign 12
response = response.toBuilder()
.request(request)
.requestTemplate(template)
.build();
} catch (IOException e) {
if (logLevel != Logger.Level.NONE) {
logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime(start));
}
throw errorExecuting(request, e);
}
}
调用execute方法时会通过FeignBlockingLoadBalancerClient
完成负载均衡,找到对应的服务器,最后底层默认通过HttpURLConnection
发起调用。