总体而言Feign调用目标方法之前被jdk动态代理区分为两种形式:负载均衡方式以及域名直接调用方式。
public class FeignClientFactoryBean{
public <T> T getTarget() {
//通过父容器创建子容器工厂类FeignContext
FeignContext context = applicationContext.getBean(FeignContext.class);
// 通过子容器 FeignContext 为每个Feign客户端创建 Feign.Builder
Feign.Builder builder = feign(context);
//如果FeignClient注解存在URL配置则直接调用,否则通过ribbon负载均衡
if (!StringUtils.hasText(this.url)) {
...
HardCodedTarget target = new HardCodedTarget<>(this.type, this.name, this.url);
// 通常选择负载均衡方式
return (T) loadBalance(builder, context, target);
}
...
String url = this.url + cleanPath();
// LazyTracingFeignClient
Client client = getOptional(context, Client.class);
if (client != null) {
if (client instanceof FeignBlockingLoadBalancerClient) {
client = ((FeignBlockingLoadBalancerClient) client).getDelegate();
}
if (client instanceof RetryableFeignBlockingLoadBalancerClient) {
client = ...
}
builder.client(client);
}
applyBuildCustomizers(context, builder);
Targeter targeter = get(context, Targeter.class);
HardCodedTarget target = new HardCodedTarget<>(this.type, this.name, this.url);
return (T) targeter.target(this, builder, context,target);//域名调用方式
}
}
?HardCodedTarget中其中type是指Feign客户端接口类型。注意区别于Targeter。
该方式适用于服务治理过程中,代理的原因是为了真正调用目标方法之前完成服务端负载均衡策略。
public class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean {
protected <T> T loadBalance(Feign.Builder builder, FeignContext context, HardCodedTarget<T> target) {
Client client = getOptional(context, Client.class);
//TraceFeignBlockingLoadBalancerClient || LoadBalancerFeignClient,区别于域名调用方式client之LazyTracingFeignClient
if (client != null) {
builder.client(client);
applyBuildCustomizers(context, builder);//扩展点
Targeter targeter = get(context, Targeter.class);//从子容器获取 FeignCircuitBreakerTargeter
return targeter.target(this, builder, context, target);
}
}
}
class FeignCircuitBreakerTargeter implements Targeter {
public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,FeignContext context,Target.HardCodedTarget<T> target) {
// 如果没有显式设置 HystrixFeign 的开关,默认Builder 为 抽象类Feign内部静态类
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
return feign.target(target);// 忽略Feign降级功能
}
FeignCircuitBreaker.Builder builder = (FeignCircuitBreaker.Builder) feign;
String name = StringUtils.isEmpty(factory.getContextId()) ? factory.getName(): factory.getContextId();
Class<?> fallback = factory.getFallback();
if (fallback != void.class) {// 优先通过Fallback实现Feign降级功能
return targetWithFallback(name, context, target, builder, fallback);
}
Class<?> fallbackFactory = factory.getFallbackFactory();
if (fallbackFactory != void.class) {// 其次通过FallbackFactory实现Feign降级功能
return targetWithFallbackFactory(name, context, target, builder,fallbackFactory);
}
return feign.target(target);// 忽略Feign降级功能
}
private <T> T targetWithFallbackFactory(String feignClientName, FeignContext context,Target.HardCodedTarget<T> target,
FeignCircuitBreaker.Builder builder, Class<?> fallbackFactoryClass) {
// 服务熔断或者降级工厂类
FallbackFactory<? extends T> fallbackFactory = (FallbackFactory<? extends T>) getFromContext("fallbackFactory",
feignClientName, context, fallbackFactoryClass, FallbackFactory.class);
return builder(feignClientName, builder).target(target, fallbackFactory);
}
private FeignCircuitBreaker.Builder builder(String feignClientName, FeignCircuitBreaker.Builder builder) {
// 初始化 Feign.Builder 相关的一些参数
return builder.circuitBreakerFactory(circuitBreakerFactory)
.feignClientName(feignClientName)
//feign.circuitbreaker.group.enabled配置
.circuitBreakerGroupEnabled(circuitBreakerGroupEnabled)
.circuitBreakerNameResolver(circuitBreakerNameResolver);
}
}
public final class FeignCircuitBreaker {
public static Builder builder() {
return new Builder();
}
public static final class Builder extends Feign.Builder {
private CircuitBreakerFactory circuitBreakerFactory;
private String feignClientName;
private boolean circuitBreakerGroupEnabled;
...
public <T> T target(Target<T> target, FallbackFactory<? extends T> fallbackFactory) {
// 利用ReflectiveFeign完成当前Feign客户端的jdk动态代理
return build(fallbackFactory).newInstance(target);
}
public Feign build(final FallbackFactory<?> nullableFallbackFactory) {
// 初始化抽象类 Feign.Builder 相关的一些参数
super.invocationHandlerFactory((target, dispatch) -> new FeignCircuitBreakerInvocationHandler(
circuitBreakerFactory, feignClientName, target, dispatch, nullableFallbackFactory,
circuitBreakerGroupEnabled, circuitBreakerNameResolver));
//初始化抽象类 Feign.Builder父类BaseBuilder 相关的一些参数
return super.build();
}
}
}
?FeignCircuitBreakerInvocationHandler是JDK动态代理中设置处理器InvocationHandler。
public abstract class Feign {
public static class Builder extends BaseBuilder<Builder> {
public Feign build() {
super.enrich();
SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors,
responseInterceptor, logger, logLevel, dismiss404, closeAfterDecode,
propagationPolicy, forceDecoding);
ParseHandlersByName handlersByName =
new ParseHandlersByName(contract, options, encoder, decoder, queryMapEncoder,
errorDecoder, synchronousMethodHandlerFactory);
// invocationHandlerFactory抽象类 Feign.Builder父类BaseBuilder的属性之FeignCircuitBreakerInvocationHandler
return new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);
}
}
}
}
public class ReflectiveFeign extends Feign {
@Override
public <T> T newInstance(Target<T> target) {
//解析当前Feign客户端所有方法,将每个方法抽象为 SynchronousMethodHandler
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)));
}
}
// FeignCircuitBreakerInvocationHandler:将目标方法抽象体SynchronousMethodHandler 跟 InvocationHandler建立绑定关系
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;
}
}
?至此,利用JDK动态代理完成每个Feign客户端实例的创建。
?