前面介绍了Feign的使用(Feign的使用),
Feign整合Hystrix(Feign整合Hystrix) ,
Feign整合(Feign整合Ribbon负载均衡),
Feign的性能优化(Feign性能优化),
现在介绍下Feign的源码。
通过前面的使用过程,@EnableFeignClients和@FeignClient实现了Feign的功能
一、@EnableFeignClients
1、@EnableFeignClients注解
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Import({FeignClientsRegistrar.class})
public @interface EnableFeignClients {
String[] value() default {};
String[] basePackages() default {};
Class<?>[] basePackageClasses() default {};
Class<?>[] defaultConfiguration() default {};
Class<?>[] clients() default {};
}
重点是@Import({FeignClientsRegistrar.class})
2、FeignClientsRigistar实现了ImportBeanDefinitionRegistrar接口
class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar,
ResourceLoaderAware, BeanClassLoaderAware, EnvironmentAware{
@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
BeanDefinitionRegistry registry) {
// 1.针对那些在@EnableFeignClients中添加了defaultConfiguration属性的进行操作
// 将这些类定义的bean添加到容器中
registerDefaultConfiguration(metadata, registry);
// 2.注册那些添加了@FeignClient的类或接口
registerFeignClients(metadata, registry);
}
3、registerFeignClients(metadata, registry);方法
public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
ClassPathScanningCandidateComponentProvider scanner = this.getScanner();
scanner.setResourceLoader(this.resourceLoader);
Map<String, Object> attrs = metadata.getAnnotationAttributes(EnableFeignClients.class.getName());
//@FeignClient注解过滤器
AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(FeignClient.class);
Class<?>[] clients = attrs == null ? null : (Class[])((Class[])attrs.get("clients"));
//1、扫描包下所有带有@FeignClient注解的类
Object basePackages;
if (clients != null && clients.length != 0) {
final Set<String> clientClasses = new HashSet();
basePackages = new HashSet();
Class[] var9 = clients;
int var10 = clients.length;
for(int var11 = 0; var11 < var10; ++var11) {
Class<?> clazz = var9[var11];
((Set)basePackages).add(ClassUtils.getPackageName(clazz));
clientClasses.add(clazz.getCanonicalName());
}
AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
protected boolean match(ClassMetadata metadata) {
String cleaned = metadata.getClassName().replaceAll("\$", ".");
return clientClasses.contains(cleaned);
}
};
scanner.addIncludeFilter(new FeignClientsRegistrar.AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
} else {
scanner.addIncludeFilter(annotationTypeFilter);
basePackages = this.getBasePackages(metadata);
}
//2、针对所有带有@FeignClient注解的类或接口分别封装
//并将类或接口注入到Spring中
Iterator var17 = ((Set)basePackages).iterator();
while(var17.hasNext()) {
String basePackage = (String)var17.next();
Set<BeanDefinition> candidateComponents = scanner.findCandidateComponents(basePackage);
Iterator var21 = candidateComponents.iterator();
while(var21.hasNext()) {
BeanDefinition candidateComponent = (BeanDefinition)var21.next();
//验证被注解的类是否是接口
if (candidateComponent instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition)candidateComponent;
AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
Assert.isTrue(annotationMetadata.isInterface(), "@FeignClient can only be specified on an interface");
Map<String, Object> attributes = annotationMetadata.getAnnotationAttributes(FeignClient.class.getCanonicalName());
String name = this.getClientName(attributes);
//2.1 注册其Configuration类(如果有的话)
this.registerClientConfiguration(registry, name, attributes.get("configuration"));
//2.2将类或接口注入到Spring中
this.registerFeignClient(registry, annotationMetadata, attributes);
}
}
}
}
从这里可知,@EnableFeignCliengs注解的主要功能就是把带有@FeignClient注解的类或接口注册到Spring容器中
4、registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes)方法分析
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
//1、获取类名称,这里为com.example.springclouddeep.consumer.feign.ProviderApi
String className = annotationMetadata.getClassName();
//2、BeanDefinitionBuilder 的作用是构建一个BeanDefinition。BeanDefinition的类为FeignClientFactoryBean
BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);
this.validate(attributes);
//添加FeignClientFactoryBean的属性,这些属性都是我们在@FeignClient中定义的属性
definition.addPropertyValue("url", this.getUrl(attributes));
definition.addPropertyValue("path", this.getPath(attributes));
String name = this.getName(attributes);
definition.addPropertyValue("name", name);
String contextId = this.getContextId(attributes);
definition.addPropertyValue("contextId", contextId);
definition.addPropertyValue("type", className);
definition.addPropertyValue("decode404", attributes.get("decode404"));
definition.addPropertyValue("fallback", attributes.get("fallback"));
definition.addPropertyValue("fallbackFactory", attributes.get("fallbackFactory"));
definition.setAutowireMode(2);
//设置别名 name就是我们在@FeignClient中定义的name属性。 这里alias值为hello-service-providerFeignClient
String alias = contextId + "FeignClient";
AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
boolean primary = (Boolean)attributes.get("primary");
beanDefinition.setPrimary(primary);
String qualifier = this.getQualifier(attributes);
if (StringUtils.hasText(qualifier)) {
alias = qualifier;
}
//5、定义BeanDefinitionHolder,这里beanDefinition中的beanClass为 //org.springframework.cloud.openfeign.FeignClientFactoryBean<br>
//className为com.example.springclouddeep.consumer.feign.ProviderApi,类为FeignClientFactoryBean
BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});
BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}
通过分析可知:我们最终是向Spring中注册了一个bean,bean的名称就是类或接口的名称(这里com.example.springclouddeep.consumer.feign.ProviderApi,.ProviderApi代码参考Feign整合Hystrix),bean的实现类是FeignClientFactoryBean,其属性设置就是我们在@FeignClient中定义的属性。那FeignClientFactoryBean有什么作用呢?我们下面再来分析
总结:
1)@EnableFeignClients注解类将FeignClientsRegistrar注册到Spring中
2)FeignClientsRegistrar类的主要作用是扫码包路径下的所有类,将带有@FeignClient注解的类或接口注册到Spring中
3)如何注册带有@FeignClient的类或接口呢? 就是生成一个BeanDefinitionHolder类,beanName为@FeignClient所在接口名称,beanDefinition为FeignClientFactoryBean,并将@FeignClient的属性添加到FeignClientFactoryBean中。
二、FeignClientFactoryBean
FeignClientFactoryBean实现了FactoryBean接口,当从ApplicationContext中获取该bean的时候,实际上调用的是getObject()方法
class FeignClientFactoryBean implements FactoryBean<Object>, InitializingBean, ApplicationContextAware {
public Object getObject() throws Exception {
return this.getTarget();
}
<T> T getTarget() {
//1、获取容器中的FeignContext实现,默认实现在FeignAutoConfiguration类中
FeignContext context = (FeignContext)this.applicationContext.getBean(FeignContext.class);
//2、使用构造器模式来构建一个Feign,后面详细介绍
Builder builder = this.feign(context);
//3、判断是否有指定URL
if (!StringUtils.hasText(this.url)) {
if (!this.name.startsWith("http")) {
this.url = "http://" + this.name;
} else {
this.url = this.name;
}
this.url = this.url + this.cleanPath();
//关键方法,后面详细介绍
return this.loadBalance(builder, context, new HardCodedTarget(this.type, this.name, this.url));
} else {
if (StringUtils.hasText(this.url) && !this.url.startsWith("http")) {
this.url = "http://" + this.url;
}
String url = this.url + this.cleanPath();
Client client = (Client)this.getOptional(context, Client.class);
if (client != null) {
if (client instanceof LoadBalancerFeignClient) {
client = ((LoadBalancerFeignClient)client).getDelegate();
}
if (client instanceof FeignBlockingLoadBalancerClient) {
client = ((FeignBlockingLoadBalancerClient)client).getDelegate();
}
builder.client(client);
}
Targeter targeter = (Targeter)this.get(context, Targeter.class);
return targeter.target(this, builder, context, new HardCodedTarget(this.type, this.name, url));
}
}
1、构建Builder
protected Builder feign(FeignContext context) {
FeignLoggerFactory loggerFactory = (FeignLoggerFactory)this.get(context, FeignLoggerFactory.class);
Logger logger = loggerFactory.create(this.type);
Builder builder = ((Builder)this.get(context, Builder.class)).logger(logger).encoder((Encoder)this.get(context, Encoder.class)).decoder((Decoder)this.get(context, Decoder.class)).contract((Contract)this.get(context, Contract.class));
this.configureFeign(context, builder);
return builder;
}
protected void configureFeign(FeignContext context, Builder builder) {
FeignClientProperties properties = (FeignClientProperties)this.applicationContext.getBean(FeignClientProperties.class);
if (properties != null) {
if (properties.isDefaultToProperties()) {
this.configureUsingConfiguration(context, builder);
this.configureUsingProperties((FeignClientConfiguration)properties.getConfig().get(properties.getDefaultConfig()), builder);
this.configureUsingProperties((FeignClientConfiguration)properties.getConfig().get(this.contextId), builder);
} else {
this.configureUsingProperties((FeignClientConfiguration)properties.getConfig().get(properties.getDefaultConfig()), builder);
this.configureUsingProperties((FeignClientConfiguration)properties.getConfig().get(this.contextId), builder);
this.configureUsingConfiguration(context, builder);
}
} else {
this.configureUsingConfiguration(context, builder);
}
}
protected void configureUsingConfiguration(FeignContext context, Builder builder) {
//下面的几项getOptional()主要功能就是从ApplicationContext中获取对应类的实现
//这些类可以自定义,默认从FeignAutoConfiguration中获取对应的bean
Level level = (Level)this.getOptional(context, Level.class);
if (level != null) {
builder.logLevel(level);
}
Retryer retryer = (Retryer)this.getOptional(context, Retryer.class);
if (retryer != null) {
builder.retryer(retryer);
}
ErrorDecoder errorDecoder = (ErrorDecoder)this.getOptional(context, ErrorDecoder.class);
if (errorDecoder != null) {
builder.errorDecoder(errorDecoder);
}
Options options = (Options)this.getOptional(context, Options.class);
if (options != null) {
builder.options(options);
}
Map<String, RequestInterceptor> requestInterceptors = context.getInstances(this.contextId, RequestInterceptor.class);
if (requestInterceptors != null) {
builder.requestInterceptors(requestInterceptors.values());
}
QueryMapEncoder queryMapEncoder = (QueryMapEncoder)this.getOptional(context, QueryMapEncoder.class);
if (queryMapEncoder != null) {
builder.queryMapEncoder(queryMapEncoder);
}
if (this.decode404) {
builder.decode404();
}
ExceptionPropagationPolicy exceptionPropagationPolicy = (ExceptionPropagationPolicy)this.getOptional(context, ExceptionPropagationPolicy.class);
if (exceptionPropagationPolicy != null) {
builder.exceptionPropagationPolicy(exceptionPropagationPolicy);
}
}
2、获取负载均衡后的方法 protected <T> T loadBalance(Builder builder, FeignContext context, HardCodedTarget<T> target)
protected <T> T loadBalance(Builder builder, FeignContext context, HardCodedTarget<T> target) {
//1、获取Client的实现类,默认为LoadBalancerFeignClient类
//实现在FeignRibbonClientAutoConfiguration中
Client client = (Client)this.getOptional(context, Client.class);
if (client != null) {
//2、将LoadBalancerFeignClient包装到Feign.Builder
builder.client(client);
//3、获取ApplicationContext中的Target实现
//默认实现为HystrixTargeter,实现在FeignAutoConfiguration类中
Targeter targeter = (Targeter)this.get(context, Targeter.class);
//4、重点是这里
return targeter.target(this, builder, context, target);
} else {
throw new IllegalStateException("No Feign Client for loadBalancing defined. Did you forget to include spring-cloud-starter-netflix-ribbon?");
}
}
//HystrixTargeter.target
public <T> T target(FeignClientFactoryBean factory, Builder feign, FeignContext context, HardCodedTarget<T> target) {
//feign不是feign.hystrix.HystrixFeign.Builder,直接返回return feign.target(target)
if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
return feign.target(target);
} else {
feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder)feign;
String name = StringUtils.isEmpty(factory.getContextId()) ? factory.getName() : factory.getContextId();
SetterFactory setterFactory = (SetterFactory)this.getOptional(name, context, SetterFactory.class);
if (setterFactory != null) {
builder.setterFactory(setterFactory);
}
Class<?> fallback = factory.getFallback();
if (fallback != Void.TYPE) {
return this.targetWithFallback(name, context, target, builder, fallback);
} else {
Class<?> fallbackFactory = factory.getFallbackFactory();
return fallbackFactory != Void.TYPE ? this.targetWithFallbackFactory(name, context, target, builder, fallbackFactory) : feign.target(target);
}
}
}
//feign.Feign.Builder.target(target)
public <T> T target(Target<T> target) {
return this.build().newInstance(target);
}
//feign.Feign.Builder.build()
public Feign build() {
Factory synchronousMethodHandlerFactory = new Factory(this.client, this.retryer, this.requestInterceptors, this.logger, this.logLevel, this.decode404, this.closeAfterDecode, this.propagationPolicy);
ParseHandlersByName handlersByName = new ParseHandlersByName(this.contract, this.options, this.encoder, this.decoder, this.queryMapEncoder, this.errorDecoder, synchronousMethodHandlerFactory);
//这里看到了ReflectiveFeign
return new ReflectiveFeign(handlersByName, this.invocationHandlerFactory, this.queryMapEncoder);
}
//ReflectiveFeign.newInstance(target)
public <T> T newInstance(Target<T> target) {
//1、分析出具体方法和对应的Handler处理
Map<String, MethodHandler> nameToHandler = this.targetToHandlersByName.apply(target);
Map<Method, MethodHandler> methodToHandler = new LinkedHashMap();
List<DefaultMethodHandler> defaultMethodHandlers = new LinkedList();
Method[] var5 = target.type().getMethods();
int var6 = var5.length;
for(int var7 = 0; var7 < var6; ++var7) {
Method method = var5[var7];
if (method.getDeclaringClass() != Object.class) {
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)));
}
}
}
//2、由factory创建一个InvocationHandler,实现为FeignInvocationHandler
//target为HardCodedTarget
InvocationHandler handler = this.factory.create(target, methodToHandler);
//最终返回的是一个代理
T proxy = Proxy.newProxyInstance(target.type().getClassLoader(), new Class[]{target.type()}, handler);
Iterator var12 = defaultMethodHandlers.iterator();
while(var12.hasNext()) {
DefaultMethodHandler defaultMethodHandler = (DefaultMethodHandler)var12.next();
defaultMethodHandler.bindTo(proxy);
}
return proxy;
}
由以上分析可知,getObject()具体返回的是一个代理类,具体为FeignInvocationHandler
3、FeignInvocationHandler
static class FeignInvocationHandler implements InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if (!"equals".equals(method.getName())) {
if ("hashCode".equals(method.getName())) {
return this.hashCode();
} else {
//非Object方法,则执行this.dispatch.get(method)).invoke(args)
//dispath为map,方法的实现类为SynchronousMethodHandle。
//我们接下来分析SynchronousMethodHandle.invoke(args)
return "toString".equals(method.getName()) ? this.toString() : ((MethodHandler)this.dispatch.get(method)).invoke(args);
}
} else {
try {
Object otherHandler = args.length > 0 && args[0] != null ? Proxy.getInvocationHandler(args[0]) : null;
return this.equals(otherHandler);
} catch (IllegalArgumentException var5) {
return false;
}
}
}
}
1)、SynchronousMethodHandle.invoke(args)
public Object invoke(Object[] argv) throws Throwable {
//1、根据请求参数创建一个RequestTemplate
RequestTemplate template = this.buildTemplateFromArgs.create(argv);
Options options = this.findOptions(argv);
//2、用户定义的重试策略
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);
}
}
}
2)executeAndDecode(template, options)
Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
//分装请求信息
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 {
//执行。 client为LoadBalancerFeignClient,下面介绍exetute方法
response = this.client.execute(request, options);
response = response.toBuilder().request(request).requestTemplate(template).build();
} catch (IOException var16) {
if (this.logLevel != Level.NONE) {
this.logger.logIOException(this.metadata.configKey(), this.logLevel, var16, this.elapsedTime(start));
}
throw FeignException.errorExecuting(request, var16);
}
//响应处理
long elapsedTime = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - start);
boolean shouldClose = true;
Object var11;
try {
if (this.logLevel != Level.NONE) {
response = this.logger.logAndRebufferResponse(this.metadata.configKey(), this.logLevel, response, elapsedTime);
}
if (Response.class == this.metadata.returnType()) {
Response var19;
if (response.body() == null) {
var19 = response;
return var19;
}
if (response.body().length() != null && (long)response.body().length() <= 8192L) {
byte[] bodyData = Util.toByteArray(response.body().asInputStream());
Response var21 = response.toBuilder().body(bodyData).build();
return var21;
}
shouldClose = false;
var19 = response;
return var19;
}
Object result;
if (response.status() >= 200 && response.status() < 300) {
if (Void.TYPE == this.metadata.returnType()) {
result = null;
return result;
}
result = this.decode(response);
shouldClose = this.closeAfterDecode;
var11 = result;
return var11;
}
if (!this.decode404 || response.status() != 404 || Void.TYPE == this.metadata.returnType()) {
throw this.errorDecoder.decode(this.metadata.configKey(), response);
}
result = this.decode(response);
shouldClose = this.closeAfterDecode;
var11 = result;
} catch (IOException var17) {
if (this.logLevel != Level.NONE) {
this.logger.logIOException(this.metadata.configKey(), this.logLevel, var17, elapsedTime);
}
throw FeignException.errorReading(request, response, var17);
} finally {
if (shouldClose) {
Util.ensureClosed(response.body());
}
}
return var11;
}
3) LoadBalancerFeignClient的exetute方法
public Response execute(Request request, Options options) throws IOException {
try {
//1、获得URI
URI asUri = URI.create(request.url());
String clientName = asUri.getHost();
URI uriWithoutHost = cleanUrl(request.url(), clientName);
//2、封装RibbonRequest请求
RibbonRequest ribbonRequest = new RibbonRequest(this.delegate, request, uriWithoutHost);
//3、封装请求参数信息
IClientConfig requestConfig = this.getClientConfig(options, clientName);
//4、执行请求,并信息负载均衡
1)lbClient(clientName)获得执行类。这里为FeignLoadBalancer
2)FeignLoadBalancer.executeWithLoadBalancer() 执行请求。 下面介绍
3)toResponse()获得响应
return ((RibbonResponse)this.lbClient(clientName).executeWithLoadBalancer(ribbonRequest, requestConfig)).toResponse();
} catch (ClientException var8) {
IOException io = this.findIOException(var8);
if (io != null) {
throw io;
} else {
throw new RuntimeException(var8);
}
}
}
4) FeignLoadBalancer.executeWithLoadBalancer()执行请求
public T executeWithLoadBalancer(final S request, final IClientConfig requestConfig) throws ClientException {
LoadBalancerCommand command = this.buildLoadBalancerCommand(request, requestConfig);
try {
//这里是Hystrix的相关代码
return (IResponse)command.submit(new ServerOperation<T>() {
public Observable<T> call(Server server) {
URI finalUri = AbstractLoadBalancerAwareClient.this.reconstructURIWithServer(server, request.getUri());
ClientRequest requestForServer = request.replaceUri(finalUri);
try {
//执行ribbon负载均衡器
return Observable.just(AbstractLoadBalancerAwareClient.this.execute(requestForServer, requestConfig));
} catch (Exception var5) {
return Observable.error(var5);
}
}
}).toBlocking().single();
} catch (Exception var6) {
Throwable t = var6.getCause();
if (t instanceof ClientException) {
throw (ClientException)t;
} else {
throw new ClientException(var6);
}
}
}
总结:
1、FeignClientFactoryBean.getObject()方法返回的是一个代理类,InvocationHandler中包含类中每个方法对应的MethodHandler,也就是SynchronousMethodHandler,方法真正执行就是SynchronousMethodHandler.invoke()方法
2.LoadBalancerFeignClient.execute()方法进行业务的处理,在这一步操作中就用到了ribbon和Hystrix功能