FeignClient接口在Spring容器中都是生成关联FeignInvocationHandler的代理类,所以在调用FeignClient接口的方法时,都会执行FeignInvocationHandler.invoke方法,FeignClient的接口方法的信息都被解析封装在SynchronousMethodHandler中,并以FeignClient接口的Method为key,SynchronousMethodHandler为value,保存在dispatch变量的Map结构中。在FeignInvocationHandler.invoke方法中,会通过调用的Method,从dispatch中找到对应的SynchronousMethodHandler,并执行SynchronousMethodHandler的invoke方法。
FeignInvocationHandler.invoke:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(!"equals".equals(method.getName())) {//通过method从Map集合中获取对应的SynchronousMethodHandlerreturn "hashCode".equals(method.getName())?Integer.valueOf(this.hashCode()):("toString".equals(method.getName())?this.toString():((MethodHandler)this.dispatch.get(method)).invoke(args));} else {try {InvocationHandler e = args.length > 0 && args[0] != null?Proxy.getInvocationHandler(args[0]):null;return Boolean.valueOf(this.equals(e));} catch (IllegalArgumentException var5) {return Boolean.valueOf(false);}}
}
SynchronousMethodHandler.invoke:
public Object invoke(Object[] argv) throws Throwable {//根据请求参数生成RequestTemplate对象RequestTemplate template = this.buildTemplateFromArgs.create(argv);Options options = this.findOptions(argv);Retryer retryer = this.retryer.clone();while(true) {try {return this.executeAndDecode(template, options);} catch (RetryableException var9) {RetryableException e = var9;try {retryer.continueOrPropagate(e);} catch (RetryableException var8) {Throwable cause = var8.getCause();if(this.propagationPolicy == ExceptionPropagationPolicy.UNWRAP && cause != null) {throw cause;}throw var8;}if(this.logLevel != Level.NONE) {this.logger.logRetry(this.metadata.configKey(), this.logLevel);}}}
}
在SynchronousMethodHandler.invoke方法中会调用BuildTemplateByResolvingArgs.create方法解析请求参数,生成RequestTemplate。BuildTemplateByResolvingArgs.create中,从MethodMetadata中复制出一个新的RequestTemplate,然后调用BuildEncodedTemplateFromArgs.resolve(body有数据使用BuildEncodedTemplateFromArgs.resolve{BuildTemplateByResolvingArgs的子类}方法封装完请求的body后也会调用父类BuildTemplateByResolvingArgs.resolve方法)方法进行参数的解析。
BuildTemplateByResolvingArgs.create:
public RequestTemplate create(Object[] argv) {RequestTemplate mutable = RequestTemplate.from(this.metadata.template());mutable.feignTarget(this.target);if(this.metadata.urlIndex() != null) {int varBuilder = this.metadata.urlIndex().intValue();Util.checkArgument(argv[varBuilder] != null, "URI parameter %s was null", new Object[]{Integer.valueOf(varBuilder)});mutable.target(String.valueOf(argv[varBuilder]));}LinkedHashMap varBuilder1 = new LinkedHashMap();Iterator template = this.metadata.indexToName().entrySet().iterator();while(true) {Entry value;int queryMap;Object value1;do {if(!template.hasNext()) {//解析参数RequestTemplate template1 = this.resolve(argv, mutable, varBuilder1);if(this.metadata.queryMapIndex() != null) {//方法参数有@SpringQueryMap注解会走这个逻辑Object value2 = argv[this.metadata.queryMapIndex().intValue()];Map queryMap1 = this.toQueryMap(value2);//将标注有@SpringQueryMap的参数的字段名称和值添加到RequestTemplate的 queries属性中,后续会调用RequestTemplate.url方法将参数拼接到url上面template1 = this.addQueryMapQueryParameters(queryMap1, template1);}if(this.metadata.headerMapIndex() != null) {template1 = this.addHeaderMapHeaders((Map)argv[this.metadata.headerMapIndex().intValue()], template1);}return template1;}value = (Entry)template.next();queryMap = ((Integer)value.getKey()).intValue();value1 = argv[((Integer)value.getKey()).intValue()];} while(value1 == null);if(this.indexToExpander.containsKey(Integer.valueOf(queryMap))) {value1 = this.expandElements((Expander)this.indexToExpander.get(Integer.valueOf(queryMap)), value1);}Iterator var8 = ((Collection)value.getValue()).iterator();while(var8.hasNext()) {String name = (String)var8.next();varBuilder1.put(name, value1);}}
}
BuildEncodedTemplateFromArgs.resolve:
protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map<String, Object> variables) {Object body = argv[this.metadata.bodyIndex().intValue()];Util.checkArgument(body != null, "Body parameter %s was null", new Object[]{this.metadata.bodyIndex()});try {//封装请求中Body的参数this.encoder.encode(body, this.metadata.bodyType(), mutable);} catch (EncodeException var6) {throw var6;} catch (RuntimeException var7) {throw new EncodeException(var7.getMessage(), var7);}//调用父类的BuildTemplateByResolvingArgs的resolve方法return super.resolve(argv, mutable, variables);
}
BuildTemplateByResolvingArgs.resolve方法最终会调用RequestTemplate.resolve进行参数的处理:protected RequestTemplate resolve(Object[] argv, RequestTemplate mutable, Map<String, Object> variables) {return mutable.resolve(variables);
}
RequestTemplate.resolve:
public RequestTemplate resolve(Map<String, ?> variables) {StringBuilder uri = new StringBuilder();RequestTemplate resolved = from(this);if(this.uriTemplate == null) {this.uriTemplate = UriTemplate.create("", !this.decodeSlash, this.charset);}String expanded = this.uriTemplate.expand(variables);if(expanded != null) {uri.append(expanded);}String headerValues;String header1;if(!this.queries.isEmpty()) {//上次说过@RequestParam标注的参数信息会被设置到queries中保存,这里会根据参数名称从请求中获取参数的值,
而且这里会将queries设置为空,因为后面调用RequestTemplate.url方法时,
会再次将queries的参数拼接到url上,不请空会导致重复resolved.queries(Collections.emptyMap());StringBuilder query = new StringBuilder();Iterator headerTemplate = this.queries.values().iterator();while(headerTemplate.hasNext()) {QueryTemplate header = (QueryTemplate)headerTemplate.next();headerValues = header.expand(variables);if(Util.isNotBlank(headerValues)) {//将请求参数拼接到url上query.append(headerValues);if(headerTemplate.hasNext()) {query.append("&");}}}header1 = query.toString();if(!header1.isEmpty()) {Matcher headerValues1 = QUERY_STRING_PATTERN.matcher(uri);if(headerValues1.find()) {uri.append("&");} else {uri.append("?");}uri.append(header1);}}resolved.uri(uri.toString());if(!this.headers.isEmpty()) {resolved.headers(Collections.emptyMap());Iterator query1 = this.headers.values().iterator();while(query1.hasNext()) {HeaderTemplate headerTemplate1 = (HeaderTemplate)query1.next();header1 = headerTemplate1.expand(variables);if(!header1.isEmpty()) {headerValues = header1.substring(header1.indexOf(" ") + 1);if(!headerValues.isEmpty()) {resolved.header(headerTemplate1.getName(), new TemplateChunk[]{Literal.create(headerValues)});}}}}if(this.bodyTemplate != null) {resolved.body(this.bodyTemplate.expand(variables));}resolved.resolved = true;return resolved;
}
回到SynchronousMethodHandler.invoke方法,调用buildTemplateFromArgs.create方法,解析请求参数,生成了RequestTemplate 之后,调用SynchronousMethodHandler.executeAndDecode方法,发起http请求。
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {//调用Feign拦截器,组装request,设置请求的url,参数等Request request = this.targetRequest(template);if(this.logLevel != Level.NONE) {this.logger.logRequest(this.metadata.configKey(), this.logLevel, request);}long start = System.nanoTime();Response response;try {//调用LoadBalancerFeignClient的execute方法,比如Ribbon的请求调用逻辑response = this.client.execute(request, options);response = response.toBuilder().request(request).requestTemplate(template).build();} catch (IOException var12) {if(this.logLevel != Level.NONE) {this.logger.logIOException(this.metadata.configKey(), this.logLevel, var12, this.elapsedTime(start));}throw FeignException.errorExecuting(request, var12);}long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);if(this.decoder != null) {return this.decoder.decode(response, this.metadata.returnType());} else {CompletableFuture resultFuture = new CompletableFuture();this.asyncResponseHandler.handleResponse(resultFuture, this.metadata.configKey(), response, this.metadata.returnType(), elapsedTime);try {if(!resultFuture.isDone()) {throw new IllegalStateException("Response handling not done");} else {return resultFuture.join();}} catch (CompletionException var13) {Throwable cause = var13.getCause();if(cause != null) {throw cause;} else {throw var13;}}}
}
Request targetRequest(RequestTemplate template) {//获取设置的所有的Feign拦截器Iterator var2 = this.requestInterceptors.iterator();while(var2.hasNext()) {//迭代调用RequestInterceptor interceptor = (RequestInterceptor)var2.next();interceptor.apply(template);}//组装request,设置请求的url,参数等return this.target.apply(template);
}