实例调用过程
feign的核心主要分两块:
1,初始化
feign通过Feign.builder() 构造器构建传递初始化参数,如:发起http的工具,序列化工具,目标类,生产者地址等参数
然后解析目标类注解为每个方法生成对应的MethodHandler ,
然后使用jdk动态代理为目标类生成代理实例ReflectiveFeign.FeignInvocationHandler
2,调用过程
调用目标类实例方法实际调用的是代理对象 ReflectiveFeign.FeignInvocationHandler.invoke–>
同步调用方法处理器 SynchronousMethodHandler.invoke–> ApacheHttp装饰者 ApacheHttpClient.execute
测试接口
public interface TestFeignClient {
@GET
@Path("test")
String test(String str);
}
1,初始化过程,脱离spring自动装配的情况下,使用TestFeignClient,创建目标类接口的代理类实例
TestFeignClient target = Feign.builder()
.client(new ApacheHttpClient())
.contract(new JAXRS2Contract())
.decoder(new JacksonDecoder())
.encoder(new JacksonEncoder())
.target(TestFeignClient.class, "http://" + testClient);
Feign.builder() 基础构建器
.client(new ApacheHttpClient()) 选择具体发起http请求的工具
由ApacheHttpClient 类实现 实现feign.Client 接口,
核心实现方法execute(),通过解析转换feign.Request 为 org.apache.http.HttpResponse
然后通过apache.HttpClient 发起请求
.contract(new JAXRS2Contract()) 使用 JAX-RS 2 注解标识请求
.decoder(new JacksonDecoder()) 解码器
.encoder(new JacksonEncoder()) 编码器
.target(TestFeignClient.class, "http://" + testClient); 使用jdk动态代理生成代理对象
基础构建之后创建默认对象 ReflectiveFeign
1,new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
2,调用 ReflectiveFeign.newInstance(target); 创建实例
@Override
public <T> T newInstance(Target<T> target) {
//解析接口中方法请求注解 和参数相关元数据
Map<String, MethodHandler> nameToHandler = targetToHandlersByName.apply(target);
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 {
methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
}
}
//生成代理处理器,调用的还是ReflectiveFeign 由他来的内部类FeignInvocationHandler实现jdk
// 动态代理类 InvocationHandler接口
// @Override
// public InvocationHandler create(Target target, Map<Method, MethodHandler> dispatch) {
// return new ReflectiveFeign.FeignInvocationHandler(target, dispatch);
// }
//
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;
}
2,接口调用过程
我们使用上一步获取到的TestFeignClient实例直接调用 接口的方法TestFeignClient.test("aaa")
当我们调用此实例的方法实际调用的是代理 ReflectiveFeign.FeignInvocationHandler.invoke 方法
ReflectiveFeign.FeignInvocationHandler.invoke
//目标类
private final Target target;
//解析目标类缓存方法对应请求
private final Map<Method, MethodHandler> dispatch;
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//equals/hashCode/toString不发起请求
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();
}
//实际调用
return dispatch.get(method).invoke(args);
}
SynchronousMethodHandler 继承 MethodHandler 实现同步调用请求
@Override
public Object invoke(Object[] argv) throws Throwable {
//通过请求参数生成请求模板
RequestTemplate template = buildTemplateFromArgs.create(argv);
//请求相关参数,timeout等
Options options = findOptions(argv);
//重试机制
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;
}
}
}
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
//生成feign 请求对象
Request request = targetRequest(template);
if (logLevel != Logger.Level.NONE) {
logger.logRequest(metadata.configKey(), logLevel, request);
}
Response response;
long start = System.nanoTime();
try {
//调用 ApacheHttpClient feign 的装饰者请求类
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);
}
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
if (decoder != null)
return decoder.decode(response, metadata.returnType());
CompletableFuture<Object> resultFuture = new CompletableFuture<>();
asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,
metadata.returnType(),
elapsedTime);
try {
if (!resultFuture.isDone())
throw new IllegalStateException("Response handling not done");
return resultFuture.join();
} catch (CompletionException e) {
Throwable cause = e.getCause();
if (cause != null)
throw cause;
throw e;
}
}
ApacheHttpClient.execute 最终调用
private final HttpClient client;
@Override
public Response execute(Request request, Request.Options options) throws IOException {
HttpUriRequest httpUriRequest;
try {
//feign request 转换为ApacheHttpClient httpUriRequest
httpUriRequest = toHttpUriRequest(request, options);
} catch (URISyntaxException e) {
throw new IOException("URL '" + request.url() + "' couldn't be parsed into a URI", e);
}
//由 ApacheHttpClient 发起最终请求
HttpResponse httpResponse = client.execute(httpUriRequest);
return toFeignResponse(httpResponse, request);
}