总体而言Feign调用目标方法之前被jdk动态代理区分为两种形式:负载均衡方式以及域名直接调用方式。
public class FeignClientFactoryBean{public <T> T getTarget() {//通过父容器创建子容器工厂类FeignContextFeignContext context = applicationContext.getBean(FeignContext.class);// 通过子容器 FeignContext 为每个Feign客户端创建 Feign.BuilderFeign.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();// LazyTracingFeignClientClient 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。
1.负载均衡之TraceFeignBlockingLoadBalancerClient
该方式适用于服务治理过程中,代理的原因是为了真正调用目标方法之前完成服务端负载均衡策略。
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之LazyTracingFeignClientif (client != null) {builder.client(client);applyBuildCustomizers(context, builder);//扩展点Targeter targeter = get(context, Targeter.class);//从子容器获取 FeignCircuitBreakerTargeterreturn targeter.target(this, builder, context, target);}}
}
1.1.FeignCircuitBreakerTargeter
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的属性之FeignCircuitBreakerInvocationHandlerreturn new ReflectiveFeign(handlersByName, invocationHandlerFactory, queryMapEncoder);}}}
}
1.2.ReflectiveFeign之jdk动态代理
public class ReflectiveFeign extends Feign {@Overridepublic <T> T newInstance(Target<T> target) {//解析当前Feign客户端所有方法,将每个方法抽象为 SynchronousMethodHandlerMap<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客户端实例的创建。
2.域名调用方式之LazyTracingFeignClient
3.执行目标方法的代理过程
4.Feign & Builder关系