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集合中获取对应的SynchronousMethodHandler
return "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); }