在Spring-Cloud-OpenFeign源码解析-03-FeignClientFactoryBean分析到,通过@Autowired
或者@Resource
注入FeignClient
实例的时候,实际上返回的是JDK动态代理对象,具体的实现逻辑在InvocationHandler
的invoke方法中
回看ReflectiveFeign.newInstance()
方法
public <T> T newInstance(Target<T> target) {//返回的是feign接口方法名和MethodHandler的对应mapMap<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);//存放feign接口方法和MethodHandler的对应mapMap<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取出来的MethodHandlermethodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));}}//这里创建的是FeignInvocationHandlerInvocationHandler 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);}@Overridepublic 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);//创建重试对象RetryerRetryer 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 12response = 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
发起调用。