关于OpenFeign的源码分析

核心流程图

关于OpenFeign的源码分析_第1张图片

首先是初始化流程

当我们在使用的时候首先启用Feign,即 启动类中添加注解@EnableFeignClients

@EnableFeignClients
public class GatewayApplication {
    public static void main(String[] args) {
        SpringApplication.run(GatewayApplication.class, args);
    }
}

进入@EnableFeignClients注解类中

@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {
}

关于@Import的使用可以查看@Import注解了解,此处加载FeignClientsRegistrar类,我们可以继续进入该类中

class FeignClientsRegistrar
		implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {
		
		}

FeignClientsRegistrar有多个接口实现,ImportBeanDefinitionRegistrar用于自定义实现Bean定义信息、ResourceLoaderAware、EnvironmentAware
我们重点看下ImportBeanDefinitionRegistrar的接口方法registerBeanDefinitions的实现

	@Override
	public void registerBeanDefinitions(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {
		registerDefaultConfiguration(metadata, registry);
		registerFeignClients(metadata, registry);
	}

其中registerDefaultConfiguration(metadata, registry);方法主要是获取@EnableFeignClients注解参数defaultConfiguration的值…

我们重点看下registerFeignClients(metadata, registry);

	public void registerFeignClients(AnnotationMetadata metadata,
			BeanDefinitionRegistry registry) {

		LinkedHashSet<BeanDefinition> candidateComponents = new LinkedHashSet<>();
		//获取注解中的属性信息
		Map<String, Object> attrs = metadata
				.getAnnotationAttributes(EnableFeignClients.class.getName());
		AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
				FeignClient.class);
		final Class<?>[] clients = attrs == null ? null
				: (Class<?>[]) attrs.get("clients");
		//如果没有clients配置信息,则取获取所有@FeignClient 标注的类
		if (clients == null || clients.length == 0) {
			ClassPathScanningCandidateComponentProvider scanner = getScanner();
			scanner.setResourceLoader(this.resourceLoader);
			scanner.addIncludeFilter(new AnnotationTypeFilter(FeignClient.class));
			Set<String> basePackages = getBasePackages(metadata);
			for (String basePackage : basePackages) {
				//存放被@FeignClient标注的类的定义信息(BeanDefinition)
				candidateComponents.addAll(scanner.findCandidateComponents(basePackage));
			}
		}
		//如果有指定的clients信息 会走到该逻辑
		else {
			for (Class<?> clazz : clients) {
				candidateComponents.add(new AnnotatedGenericBeanDefinition(clazz));
			}
		}
		//循环遍历@FeignClient标注的类的BeanDefinition
		for (BeanDefinition candidateComponent : candidateComponents) {
			if (candidateComponent instanceof AnnotatedBeanDefinition) {
				//验证带注解的类是否为接口
				AnnotatedBeanDefinition beanDefinition = (AnnotatedBeanDefinition) candidateComponent;
				AnnotationMetadata annotationMetadata = beanDefinition.getMetadata();
				Assert.isTrue(annotationMetadata.isInterface(),
						"@FeignClient can only be specified on an interface");

				//获取@FeignClient的属性信息
				Map<String, Object> attributes = annotationMetadata
						.getAnnotationAttributes(FeignClient.class.getCanonicalName());
				//获取名称
				String name = getClientName(attributes);
				//将一些配置信息添加到 registry的BeanDefinition集合中(编码器、解码器等)
				registerClientConfiguration(registry, name,
						attributes.get("configuration"));
				//注册FeignClient
				registerFeignClient(registry, annotationMetadata, attributes);
			}
		}
	}

我们还是重点关注下registerFeignClient方法的调用,我们需要重点留意下 有设置 FeignClientFactoryBean(表示注册的FeignClient都是FeignClientFactoryBean类型的)

	private void registerFeignClient(BeanDefinitionRegistry registry,
			AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
		//获取当前被@FeignClient标注的类名
		String className = annotationMetadata.getClassName();
		//通过建造者模式创建BeanDefinition
		//BeanDefinitionBuilder中含有属性beanDefinition(GenericBeanDefinition类型)
		//beanDefinition设置beanClass(Class类型)为FeignClientFactoryBean.class
		**BeanDefinitionBuilder definition = BeanDefinitionBuilder
				.genericBeanDefinition(FeignClientFactoryBean.class);**
		validate(attributes);
		definition.addPropertyValue("url", getUrl(attributes));
		definition.addPropertyValue("path", getPath(attributes));
		String name = getName(attributes);
		definition.addPropertyValue("name", name);
		String contextId = 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(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);

		String alias = contextId + "FeignClient";
		AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
		beanDefinition.setAttribute(FactoryBean.OBJECT_TYPE_ATTRIBUTE, className);

		// has a default, won't be null
		boolean primary = (Boolean) attributes.get("primary");

		beanDefinition.setPrimary(primary);

		String qualifier = getQualifier(attributes);
		if (StringUtils.hasText(qualifier)) {
			alias = qualifier;
		}
		//创建BeanDefinitionHolder
		BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className,
				new String[] { alias });
		//注册FeignClient的BeanDefinition信息
		BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
	}

我们继续重点看下BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);方法

	public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();
		//注册
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);
			}
		}
	}

关于调用流程

假设我们有一个IRemoteCallService类

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@FeignClient(name="server-user")
public interface IRemoteCallService {

    @RequestMapping(value="/user/getNameById",method = RequestMethod.POST)
    String getName(@RequestParam("userId") String userId);

}

当我们执行context.getBean(IRemoteCallService.class);时

@EnableFeignClients
public class GatewayApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(GatewayApplication.class, args);
        IRemoteCallService bean = context.getBean(IRemoteCallService.class);
    }
}

中间具体细节调用流程为:

org.springframework.context.support.AbstractApplicationContext#getBean(java.lang.Class)
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class)
org.springframework.beans.factory.support.DefaultListableBeanFactory#getBean(java.lang.Class, java.lang.Object…)
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveBean
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveNamedBean(org.springframework.core.ResolvableType, java.lang.Object[], boolean)
org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String, java.lang.Class, java.lang.Object…)
org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(java.lang.String, org.springframework.beans.factory.support.RootBeanDefinition, java.lang.Object[])

我们看下doGetBean中部分方法:

	protected <T> T doGetBean(
			String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
			throws BeansException {
			
				// Create bean instance.
				if (mbd.isSingleton()) {
					sharedInstance = getSingleton(beanName, () -> {
						try {
							return createBean(beanName, mbd, args);
						}
						catch (BeansException ex) {
							// Explicitly remove instance from singleton cache: It might have been put there
							// eagerly by the creation process, to allow for circular reference resolution.
							// Also remove any beans that received a temporary reference to the bean.
							destroySingleton(beanName);
							throw ex;
						}
					});
					bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
				}
				
	}
	@Override
	protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		//mbd 是 GenericBeanDefinition转化而来的 
		RootBeanDefinition mbdToUse = mbd;
		
		//获得beanClass,即:FeignClientFactoryBean
		Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
		
		if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
			mbdToUse = new RootBeanDefinition(mbd);
			mbdToUse.setBeanClass(resolvedClass);
		}
		
		try {
			mbdToUse.prepareMethodOverrides();
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
			//可以通过调用BeanPostProcessors来完成实例
			Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
			if (bean != null) {
				return bean;
			}
		}

		try {
			//调用doCreateBean方法,
			Object beanInstance = doCreateBean(beanName, mbdToUse, args);
			if (logger.isTraceEnabled()) {
				logger.trace("Finished creating instance of bean '" + beanName + "'");
			}
			return beanInstance;
		}
	}

我们继续看下 doCreateBean方法

	protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			//实例化
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		...
	}

createBeanInstance方法调用

	protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
		//beanClass :FeignClientFactoryBean
		Class<?> beanClass = resolveBeanClass(mbd, beanName);
		
		Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
		
		ctors = mbd.getPreferredConstructors();
		if (ctors != null) {
			return autowireConstructor(beanName, mbd, ctors, null);
		}

		// No special handling: simply use no-arg constructor.
		//调用构造方法实例化
		return instantiateBean(beanName, mbd);
	}

我们继续返回到doGetBean方法中,调用完createBean方法后,继续调用getObjectForBeanInstance方法

org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance

	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		//此时我们拿到的 beanInstance 是 FeignClientFactoryBean的实例,FeignClientFactoryBean是实现了FactoryBean接口的
		if (!(beanInstance instanceof FactoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
			//获取缓存
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// Return bean instance from factory.
			FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
			// 缓存获取Bean定义信息
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			//获取Object
			object = getObjectFromFactoryBean(factory, beanName, !synthetic);
		}
		return object;
	}
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
		else {
			//调用doGetObjectFromFactoryBean方法
			Object object = doGetObjectFromFactoryBean(factory, beanName);
			if (shouldPostProcess) {
				try {
					object = postProcessObjectFromFactoryBean(object, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
				}
			}
			return object;
		}
}
	private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
		Object object;
		try {
			else {
				//调用FeignClientFactoryBean的getObject方法
				object = factory.getObject();
			}
		}
	}

关于代理创建流程

org.springframework.cloud.openfeign.FeignClientFactoryBean#getObject

	@Override
	public Object getObject() throws Exception {
		return getTarget();
	}
	<T> T getTarget() {
		//获取FeignClientSpecification中存放的配置信息(编码器、解码器)
		FeignContext context = applicationContext.getBean(FeignContext.class);
		Feign.Builder builder = feign(context);
		//组装url,(http://server-user)
		if (!StringUtils.hasText(url)) {
			if (!name.startsWith("http")) {
				url = "http://" + name;
			}
			else {
				url = name;
			}
			url += cleanPath();
			return (T) loadBalance(builder, context,
					new HardCodedTarget<>(type, name, url));
		}
		if (StringUtils.hasText(url) && !url.startsWith("http")) {
			url = "http://" + url;
		}
		String url = this.url + cleanPath();
		Client client = 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 = get(context, Targeter.class);
		//生成代理
		return (T) targeter.target(this, builder, context,
				new HardCodedTarget<>(type, name, url));
	}

调用org.springframework.cloud.openfeign.DefaultTargeter#target

	@Override
	public <T> T target(FeignClientFactoryBean factory, Feign.Builder feign,
			FeignContext context, Target.HardCodedTarget<T> target) {
		return feign.target(target);
	}

调用 feign.Feign.Builder#target(feign.Target)

    public <T> T target(Target<T> target) {
      return build().newInstance(target);
    }

调用 feign.Feign.Builder#build

	private InvocationHandlerFactory invocationHandlerFactory = new InvocationHandlerFactory.Default();
        
        
    public Feign build() {
      SynchronousMethodHandler.Factory synchronousMethodHandlerFactory =
          new SynchronousMethodHandler.Factory(client, retryer, requestInterceptors, logger,
                                               logLevel, decode404);
      ParseHandlersByName handlersByName =
          new ParseHandlersByName(contract, options, encoder, decoder,
                                  errorDecoder, synchronousMethodHandlerFactory);
      //生成ReflectiveFeign,                
      return new ReflectiveFeign(handlersByName, invocationHandlerFactory);
    }

返回到feign.Feign.Builder#target(feign.Target),继续看newInstance方法调用

  @Override
  public <T> T newInstance(Target<T> target) {
  	//调用targetToHandlersByName.apply,对该FeignClient中所有的方法生成 MethodHandler (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 {
      	//将FeignClient中方法和对应的MethodHandler 保存起来
      	//nameToHandler 保存的是 基于类名方法名等信息和对应的MethodHandler的集合信息
      	//methodToHandler保存的是method类与对应的MethodHandler的集合信息
        methodToHandler.put(method, nameToHandler.get(Feign.configKey(target.type(), method)));
      }
    }
    //生成 handler (FeignInvocationHandler类型),含有两个属性target即 FeignClient对应的类,dispatch即类中方法和对应的MethodHandler(SynchronousMethodHandler类型)
    InvocationHandler handler = factory.create(target, methodToHandler);
    //基于Proxy生成JDK动态代理
    T proxy = (T) Proxy.newProxyInstance(target.type().getClassLoader(), new Class<?>[]{target.type()}, handler);

    for(DefaultMethodHandler defaultMethodHandler : defaultMethodHandlers) {
      defaultMethodHandler.bindTo(proxy);
    }
    //返回代理对象
    return proxy;
  }

targetToHandlersByName.apply的调用

    public Map<String, MethodHandler> apply(Target key) {
      List<MethodMetadata> metadata = contract.parseAndValidatateMetadata(key.type());
      Map<String, MethodHandler> result = new LinkedHashMap<String, MethodHandler>();
      for (MethodMetadata md : metadata) {
        BuildTemplateByResolvingArgs buildTemplate;
        if (!md.formParams().isEmpty() && md.template().bodyTemplate() == null) {
          buildTemplate = new BuildFormEncodedTemplateFromArgs(md, encoder);
        } else if (md.bodyIndex() != null) {
          buildTemplate = new BuildEncodedTemplateFromArgs(md, encoder);
        } else {
          buildTemplate = new BuildTemplateByResolvingArgs(md);
        }
        result.put(md.configKey(),
                   factory.create(key, md, buildTemplate, options, decoder, errorDecoder));
      }
      return result;
    }

关于代理调用流程

上面我们清楚了代理中生成的 handler (FeignInvocationHandler类型),含有两个属性target即 FeignClient对应的类,dispatch即类中方法和对应的MethodHandler(SynchronousMethodHandler类型)

1、我们看下 FeignInvocationHandler的具体调用流程

feign.ReflectiveFeign.FeignInvocationHandler#invoke

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      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();
      }
      //基于dispatch 找到对应的 MethodHandler,调用invoke方法
      return dispatch.get(method).invoke(args);
    }

2、我们看下 SynchronousMethodHandler的具体调用流程

  @Override
  public Object invoke(Object[] argv) throws Throwable {
  	//基于参数构建RequestTemplate
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    //克隆重试机制的类
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
      	//执行调用和解码工作
        return executeAndDecode(template);
      } catch (RetryableException e) {
        retryer.continueOrPropagate(e);
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
  }
  Object executeAndDecode(RequestTemplate template) throws Throwable {
    //获取Request对象
    //此处也是自定义拦截器的实现
    Request request = targetRequest(template);

    if (logLevel != Logger.Level.NONE) {
      logger.logRequest(metadata.configKey(), logLevel, request);
    }

    Response response;
    long start = System.nanoTime();
    try {
    	//通过client进行发起
      response = client.execute(request, options);
    } 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);

    boolean shouldClose = true;
    try {
      if (logLevel != Logger.Level.NONE) {
        response =
            logger.logAndRebufferResponse(metadata.configKey(), logLevel, response, elapsedTime);
      }
      //
      if (Response.class == metadata.returnType()) {
        if (response.body() == null) {
          return response;
        }
        if (response.body().length() == null ||
                response.body().length() > MAX_RESPONSE_BUFFER_SIZE) {
          shouldClose = false;
          return response;
        }
        // Ensure the response body is disconnected
        byte[] bodyData = Util.toByteArray(response.body().asInputStream());
        return Response.create(response.status(), response.reason(), response.headers(), bodyData);
      }
      //成功进行解码返回
      if (response.status() >= 200 && response.status() < 300) {
        if (void.class == metadata.returnType()) {
          return null;
        } else {
          return decode(response);
        }
      } else if (decode404 && response.status() == 404) {
        return decoder.decode(response, metadata.returnType());
      } else {
        throw errorDecoder.decode(metadata.configKey(), response);
      }
    } catch (IOException e) {
      if (logLevel != Logger.Level.NONE) {
        logger.logIOException(metadata.configKey(), logLevel, e, elapsedTime);
      }
      throw errorReading(request, response, e);
    } finally {
      if (shouldClose) {
      	//响应流关闭
        ensureClosed(response.body());
      }
    }
  }

关于一些核心的类的定义可以查看链接来学习

操作实例可查看feign自定义请求拦截器、编码器、解码器
OpenFeign拦截器RequestInterceptor的使用

你可能感兴趣的:(SpringBoot,java,开发语言)