前面介绍了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功能