七、Feign源码分析

一、准备

@EnableFeignClients注解开启feign

@SpringBootApplication
@EnableFeignClients
//@RibbonClients 注意 配置类不能写在@SpringbootApplication注解的@CompentScan扫描得到的地方
/*@RibbonClients(
		value = {
				@RibbonClient(name = "order-server",configuration = RuleConfig.class)
		}
)*/

public class UserApplication {

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

}

feigin接口上使用@FeignClient注解

//局部指定configuration 配置类FeignConfig,FeignConfig上不能有@Configuration注解,否则全局生效
//@FeignClient(value = "order-server",path = "/order",configuration = FeignConfig.class)
@FeignClient(value = "order-server",path = "/order")
public interface OrderFeignService {
    /*@GetMapping("queryOrderByUserId/{userId}")
    public String queryOrderByUserId(@PathVariable("userId") Long userId);*/


    @RequestLine("GET queryOrderByUserId/{userId}")
    public String queryOrderByUserId(@Param("userId") Long userId);
}

二、源码分析

FeignAutoConfiguration自动配置类注入

@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(Feign.class)
@EnableConfigurationProperties({ FeignClientProperties.class,
		FeignHttpClientProperties.class })
@Import(DefaultGzipDecoderConfiguration.class)
public class FeignAutoConfiguration {

	@Autowired(required = false)
	private List<FeignClientSpecification> configurations = new ArrayList<>();

	@Bean
	public HasFeatures feignFeature() {
		return HasFeatures.namedFeature("Feign", Feign.class);
	}
    //注入FeignContext
	@Bean
	public FeignContext feignContext() {
		FeignContext context = new FeignContext();
		context.setConfigurations(this.configurations);
		return context;
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass(name = "feign.hystrix.HystrixFeign")
	protected static class HystrixFeignTargeterConfiguration {
        //注入Targeter
		@Bean
		@ConditionalOnMissingBean
		public Targeter feignTargeter() {
			return new HystrixTargeter();
		}

	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnMissingClass("feign.hystrix.HystrixFeign")
	protected static class DefaultFeignTargeterConfiguration {

		@Bean
		@ConditionalOnMissingBean
		public Targeter feignTargeter() {
			return new DefaultTargeter();
		}

	}

...
}

FeignContext构造方法,设置FeignClientsConfiguration配置类,后面创建容器加载配置类:

public FeignContext() {
	super(FeignClientsConfiguration.class, "feign", "feign.client.name");
}

FeignClientsConfiguration注入Decoder,Encoder,Contract等各种组件

@Configuration(proxyBeanMethods = false)
public class FeignClientsConfiguration {

	@Autowired
	private ObjectFactory<HttpMessageConverters> messageConverters;

	@Autowired(required = false)
	private List<AnnotatedParameterProcessor> parameterProcessors = new ArrayList<>();

	@Autowired(required = false)
	private List<FeignFormatterRegistrar> feignFormatterRegistrars = new ArrayList<>();

	@Autowired(required = false)
	private Logger logger;

	@Autowired(required = false)
	private SpringDataWebProperties springDataWebProperties;

	@Bean
	@ConditionalOnMissingBean
	public Decoder feignDecoder() {
		return new OptionalDecoder(
				new ResponseEntityDecoder(new SpringDecoder(this.messageConverters)));
	}

	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnMissingClass("org.springframework.data.domain.Pageable")
	public Encoder feignEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider) {
		return springEncoder(formWriterProvider);
	}

	@Bean
	@ConditionalOnClass(name = "org.springframework.data.domain.Pageable")
	@ConditionalOnMissingBean
	public Encoder feignEncoderPageable(
			ObjectProvider<AbstractFormWriter> formWriterProvider) {
		PageableSpringEncoder encoder = new PageableSpringEncoder(
				springEncoder(formWriterProvider));

		if (springDataWebProperties != null) {
			encoder.setPageParameter(
					springDataWebProperties.getPageable().getPageParameter());
			encoder.setSizeParameter(
					springDataWebProperties.getPageable().getSizeParameter());
			encoder.setSortParameter(
					springDataWebProperties.getSort().getSortParameter());
		}
		return encoder;
	}

    //SpringMVC注解它们是被谁处理的呢?
	//Contract的实现类SpringMVCContract就是来解析它们的,解析所有的注解信息、然后拼凑成一个完整的HTTP请求所需要的信息。
	@Bean
	@ConditionalOnMissingBean
	public Contract feignContract(ConversionService feignConversionService) {
		return new SpringMvcContract(this.parameterProcessors, feignConversionService);
	}

	@Bean
	public FormattingConversionService feignConversionService() {
		FormattingConversionService conversionService = new DefaultFormattingConversionService();
		for (FeignFormatterRegistrar feignFormatterRegistrar : this.feignFormatterRegistrars) {
			feignFormatterRegistrar.registerFormatters(conversionService);
		}
		return conversionService;
	}

	@Bean
	@ConditionalOnMissingBean
	public Retryer feignRetryer() {
		return Retryer.NEVER_RETRY;
	}

	@Bean
	@Scope("prototype")
	@ConditionalOnMissingBean
	public Feign.Builder feignBuilder(Retryer retryer) {
		return Feign.builder().retryer(retryer);
	}

	@Bean
	@ConditionalOnMissingBean(FeignLoggerFactory.class)
	public FeignLoggerFactory feignLoggerFactory() {
		return new DefaultFeignLoggerFactory(this.logger);
	}

	@Bean
	@ConditionalOnClass(name = "org.springframework.data.domain.Page")
	public Module pageJacksonModule() {
		return new PageJacksonModule();
	}

	@Bean
	@ConditionalOnClass(name = "org.springframework.data.domain.Page")
	public Module sortModule() {
		return new SortJacksonModule();
	}

	@Bean
	@ConditionalOnMissingBean(FeignClientConfigurer.class)
	public FeignClientConfigurer feignClientConfigurer() {
		return new FeignClientConfigurer() {
		};
	}

	private Encoder springEncoder(ObjectProvider<AbstractFormWriter> formWriterProvider) {
		AbstractFormWriter formWriter = formWriterProvider.getIfAvailable();

		if (formWriter != null) {
			return new SpringEncoder(new SpringPojoFormEncoder(formWriter),
					this.messageConverters);
		}
		else {
			return new SpringEncoder(new SpringFormEncoder(), this.messageConverters);
		}
	}

	@Configuration(proxyBeanMethods = false)
	@ConditionalOnClass({ HystrixCommand.class, HystrixFeign.class })
	protected static class HystrixFeignConfiguration {

		@Bean
		@Scope("prototype")
		@ConditionalOnMissingBean
		@ConditionalOnProperty(name = "feign.hystrix.enabled")
		public Feign.Builder feignHystrixBuilder() {
			return HystrixFeign.builder();
		}

	}

	private class SpringPojoFormEncoder extends SpringFormEncoder {

		SpringPojoFormEncoder(AbstractFormWriter formWriter) {
			super();

			MultipartFormContentProcessor processor = (MultipartFormContentProcessor) getContentProcessor(
					MULTIPART);
			processor.addFirstWriter(formWriter);
		}

	}

}

@EnableFeignClients注解开启feign

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(FeignClientsRegistrar.class)
public @interface EnableFeignClients {

...
}

核心是@Import(FeignClientsRegistrar.class),FeignClientsRegistrar实现ImportBeanDefinitionRegistrar接口,注册bean定义时会调用registerBeanDefinitions方法

@Override
public void registerBeanDefinitions(AnnotationMetadata metadata,
		BeanDefinitionRegistry registry) {
	//注册默认配置
	registerDefaultConfiguration(metadata, registry);
	//注册FeignClients
	registerFeignClients(metadata, registry);
}

registerDefaultConfiguration注册默认配置


private void registerDefaultConfiguration(AnnotationMetadata metadata,
		BeanDefinitionRegistry registry) {
	//获得注解属性
	Map<String, Object> defaultAttrs = metadata
			.getAnnotationAttributes(EnableFeignClients.class.getName(), true);

	if (defaultAttrs != null && defaultAttrs.containsKey("defaultConfiguration")) {
		String name;
		if (metadata.hasEnclosingClass()) {
			name = "default." + metadata.getEnclosingClassName();
		}
		else {
			name = "default." + metadata.getClassName();
		}
		//name 是 default.com.xyy.UserApplication
		//注册Client配置类
		registerClientConfiguration(registry, name,
				defaultAttrs.get("defaultConfiguration"));
	}
}

registerClientConfiguration方法,向容器中注册BeanDefinition,类型是FeignClientSpecification

private void registerClientConfiguration(BeanDefinitionRegistry registry, Object name,
			Object configuration) {
	//注册一个FeignClientSpecification
	BeanDefinitionBuilder builder = BeanDefinitionBuilder
			.genericBeanDefinition(FeignClientSpecification.class);
	builder.addConstructorArgValue(name);
	builder.addConstructorArgValue(configuration);
	registry.registerBeanDefinition(
			name + "." + FeignClientSpecification.class.getSimpleName(),
			builder.getBeanDefinition());
}

下面看下registerFeignClients方法

public void registerFeignClients(AnnotationMetadata metadata,
		BeanDefinitionRegistry registry) {
	//扫描器
	ClassPathScanningCandidateComponentProvider scanner = getScanner();
	scanner.setResourceLoader(this.resourceLoader);

	Set<String> basePackages;

	//获取@EnableFeignClients注解属性值
	Map<String, Object> attrs = metadata
			.getAnnotationAttributes(EnableFeignClients.class.getName());
	//注解类型的过滤器AnnotationTypeFilter,指定注解是@FeignClient
	AnnotationTypeFilter annotationTypeFilter = new AnnotationTypeFilter(
			FeignClient.class);
	//获取@EnableFeignClients的clients属性
	final Class<?>[] clients = attrs == null ? null
			: (Class<?>[]) attrs.get("clients");
			
	if (clients == null || clients.length == 0) {
	    //设置扫描器包含filter
		scanner.addIncludeFilter(annotationTypeFilter);
		//获取扫描包,没设置的话,默认是有@EnableFeignClients注解类所在的包
		basePackages = getBasePackages(metadata);
	}
	else {
		final Set<String> clientClasses = new HashSet<>();
		basePackages = new HashSet<>();
		for (Class<?> clazz : clients) {
			basePackages.add(ClassUtils.getPackageName(clazz));
			clientClasses.add(clazz.getCanonicalName());
		}
		AbstractClassTestingTypeFilter filter = new AbstractClassTestingTypeFilter() {
			@Override
			protected boolean match(ClassMetadata metadata) {
				String cleaned = metadata.getClassName().replaceAll("\\$", ".");
				return clientClasses.contains(cleaned);
			}
		};
		scanner.addIncludeFilter(
				new AllTypeFilter(Arrays.asList(filter, annotationTypeFilter)));
	}

	for (String basePackage : basePackages) {
	    //扫描组件
		Set<BeanDefinition> candidateComponents = scanner
				.findCandidateComponents(basePackage);
		for (BeanDefinition candidateComponent : candidateComponents) {
			if (candidateComponent instanceof AnnotatedBeanDefinition) {
				// verify annotated class is an interface
				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());
				//获取Client名称
				String name = getClientName(attributes);
				//如果有configuration属性,还要加载配置
				registerClientConfiguration(registry, name,
						attributes.get("configuration"));
				//注册feginclient
				registerFeignClient(registry, annotationMetadata, attributes);
			}
		}
	}
}

getBasePackages方法:

protected Set<String> getBasePackages(AnnotationMetadata importingClassMetadata) {
		Map<String, Object> attributes = importingClassMetadata
				.getAnnotationAttributes(EnableFeignClients.class.getCanonicalName());

    //@EnableFeignClients 注解的value
	Set<String> basePackages = new HashSet<>();
	for (String pkg : (String[]) attributes.get("value")) {
		if (StringUtils.hasText(pkg)) {
			basePackages.add(pkg);
		}
	}
	//@EnableFeignClients 注解的basePackages
	for (String pkg : (String[]) attributes.get("basePackages")) {
		if (StringUtils.hasText(pkg)) {
			basePackages.add(pkg);
		}
	}
	//@EnableFeignClients 注解的basePackageClasses
	for (Class<?> clazz : (Class[]) attributes.get("basePackageClasses")) {
		basePackages.add(ClassUtils.getPackageName(clazz));
	}
    //以上都没有,则设为有@EnableFeignClients注解类所在的包
	if (basePackages.isEmpty()) {
		basePackages.add(
				ClassUtils.getPackageName(importingClassMetadata.getClassName()));
	}
	return basePackages;
}

registerFeignClient方法注册


private void registerFeignClient(BeanDefinitionRegistry registry,
			AnnotationMetadata annotationMetadata, Map<String, Object> attributes) {
	//beaNname就是类名		
	String className = annotationMetadata.getClassName();
	//注册成FeignClientFactoryBean
	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);

    //别名order-serverFeignClient
	String alias = contextId + "FeignClient";
	AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();
	//设置factoryBeanObjectType属性,也就是设置为FactoryBean
	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 holder = new BeanDefinitionHolder(beanDefinition, className,
			new String[] { alias });
	//注册BeanDefinition		
	BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
}

FeignClientFactoryBean实现FactoryBean,在spring启动时时候,如果是FactoryBean,则调用getObject()方法创建bean
FeignClientFactoryBean的getObject()方法:

@Override
public Object getObject() throws Exception {
	return getTarget();
}

getTarget()方法


<T> T getTarget() {
    //获取FeignContext,前面已经注册过
	FeignContext context = applicationContext.getBean(FeignContext.class);
	//构建Feign.Builder,配置feign
	Feign.Builder builder = feign(context);

    //构建url
	if (!StringUtils.hasText(url)) {
		if (!name.startsWith("http")) {
			url = "http://" + name;
		}
		else {
			url = name;
		}
		// url是http://order-server/order
		url += cleanPath();
		//负载
		return (T) loadBalance(builder, context,
				new HardCodedTarget<>(type, name, url));
	}
	if (StringUtils.hasText(url) && !url.startsWith("http")) {
		url = "http://" + url;
	}
	
	Client client = getOptional(context, Client.class);
	if (client != null) {
		if (client instanceof LoadBalancerFeignClient) {
			// not load balancing because we have a url,
			// but ribbon is on the classpath, so unwrap
			client = ((LoadBalancerFeignClient) client).getDelegate();
		}
		if (client instanceof FeignBlockingLoadBalancerClient) {
			// not load balancing because we have a url,
			// but Spring Cloud LoadBalancer is on the classpath, so unwrap
			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));
}

构建Feign.Builder,配置feign

protected Feign.Builder feign(FeignContext context) {
   FeignLoggerFactory loggerFactory = get(context, FeignLoggerFactory.class);
   Logger logger = loggerFactory.create(type);

   //加载各种组件,前面已经配置过
   Feign.Builder builder = get(context, Feign.Builder.class)
   		// required values
   		.logger(logger)
   		.encoder(get(context, Encoder.class))
   		.decoder(get(context, Decoder.class))
   		.contract(get(context, Contract.class));
   // @formatter:on
  //把配置文件的一些配置绑定到feign的配置类上
   configureFeign(context, builder);

   return builder;
}

loadBalance方法



protected <T> T loadBalance(Feign.Builder builder, FeignContext context,
		HardCodedTarget<T> target) {
	//client 是 LoadBalancerFeignClient	
	Client client = getOptional(context, Client.class);
	if (client != null) {
	    //设置client为LoadBalancerFeignClient
        //FeignRibbonClientAutoConfiguration自动配置类,import导入了DefaultFeignLoadBalancedConfiguration
		//DefaultFeignLoadBalancedConfiguration配置@Bean的形式注册了LoadBalancerFeignClient
		builder.client(client);
		Targeter targeter = get(context, Targeter.class);
		//创建代理类 targeter 是HystrixTargeter
		return targeter.target(this, builder, context, target);
	}

	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, Feign.Builder feign,
			FeignContext context, Target.HardCodedTarget<T> target) {
	if (!(feign instanceof feign.hystrix.HystrixFeign.Builder)) {
	    //这里
		return feign.target(target);
	}
	feign.hystrix.HystrixFeign.Builder builder = (feign.hystrix.HystrixFeign.Builder) feign;
	String name = StringUtils.isEmpty(factory.getContextId()) ? factory.getName()
			: factory.getContextId();
	SetterFactory setterFactory = getOptional(name, context, SetterFactory.class);
	if (setterFactory != null) {
		builder.setterFactory(setterFactory);
	}
	Class<?> fallback = factory.getFallback();
	if (fallback != void.class) {
		return targetWithFallback(name, context, target, builder, fallback);
	}
	Class<?> fallbackFactory = factory.getFallbackFactory();
	if (fallbackFactory != void.class) {
		return targetWithFallbackFactory(name, context, target, builder,
				fallbackFactory);
	}

	return feign.target(target);
}

feign.target方法:


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

ReflectiveFeign的newInstance方法:

public <T> T newInstance(Target<T> target) {
    //这里处理了Contract,apply()-> contract.parseAndValidateMetadata()
	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)));
			}
		}
	}
    //动态代理!!!!
	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;
}

到此代理对象生成了
在这里插入图片描述

Feign在涉及到一系列的组件,所以Feign⼲脆为每个服务创建了一个Spring容器类ApplicationContext,来存放每个服务各自所需要的组件
每个服务的这些工具类、组件都是互不影响的,所以我们看到它在底层是通过一个Map来缓存的,key为服务名,value为服务所对应的的spring容器ApplicationContext。

实现核心代码:


protected AnnotationConfigApplicationContext getContext(String name) {
	if (!this.contexts.containsKey(name)) {
		synchronized (this.contexts) {
			if (!this.contexts.containsKey(name)) {
				//createContext(name) 创建容器
				this.contexts.put(name, createContext(name));
			}
		}
	}
	return this.contexts.get(name);
}

createContext(name)方法

createContext(String name) {
    //创建
	AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
	if (this.configurations.containsKey(name)) {
		for (Class<?> configuration : this.configurations.get(name)
				.getConfiguration()) {
			//注册配置类
			context.register(configuration);
		}
	}
	for (Map.Entry<String, C> entry : this.configurations.entrySet()) {
		if (entry.getKey().startsWith("default.")) {
			for (Class<?> configuration : entry.getValue().getConfiguration()) {
				context.register(configuration);
			}
		}
	}
	context.register(PropertyPlaceholderAutoConfiguration.class,
			this.defaultConfigType);
	context.getEnvironment().getPropertySources().addFirst(new MapPropertySource(
			this.propertySourceName,
			Collections.<String, Object>singletonMap(this.propertyName, name)));
	if (this.parent != null) {
		// Uses Environment from parent as well as beans
		context.setParent(this.parent);
		// jdk11 issue
		// https://github.com/spring-cloud/spring-cloud-netflix/issues/3101
		context.setClassLoader(this.parent.getClassLoader());
	}
	context.setDisplayName(generateDisplayName(name));
	//刷新容器
	context.refresh();
	return context;
}

接口调用:http://127.0.0.1:8888/user/queryOrderByUserId2/111

进入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();
  }
  //调用
  return dispatch.get(method).invoke(args);
}

SynchronousMethodHandler的invoke方法

@Override
public Object invoke(Object[] argv) throws Throwable {
    RequestTemplate template = buildTemplateFromArgs.create(argv);
    Options options = findOptions(argv);
    Retryer retryer = this.retryer.clone();
    while (true) {
      try {
	    //这里执行
        return executeAndDecode(template, options);
      } catch (RetryableException e) {
        try {
          retryer.continueOrPropagate(e);
        } catch (RetryableException th) {
          Throwable cause = th.getCause();
          if (propagationPolicy == UNWRAP && cause != null) {
            throw cause;
          } else {
            throw th;
          }
        }
        if (logLevel != Logger.Level.NONE) {
          logger.logRetry(metadata.configKey(), logLevel);
        }
        continue;
      }
    }
 }

executeAndDecode方法:

Object executeAndDecode(RequestTemplate template, Options options) throws Throwable {
    Request request = targetRequest(template);

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

    Response response;
    long start = System.nanoTime();
    try {
	  //这里
	  //client 是LoadBalancerFeignClient  后面就不用看了
      response = client.execute(request, options);
      // ensure the request is set. TODO: remove in Feign 12
      response = response.toBuilder()
          .request(request)
          .requestTemplate(template)
          .build();
    } 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);


    if (decoder != null)
      return decoder.decode(response, metadata.returnType());

    CompletableFuture<Object> resultFuture = new CompletableFuture<>();
    asyncResponseHandler.handleResponse(resultFuture, metadata.configKey(), response,
        metadata.returnType(),
        elapsedTime);

    try {
      if (!resultFuture.isDone())
        throw new IllegalStateException("Response handling not done");

      return resultFuture.join();
    } catch (CompletionException e) {
      Throwable cause = e.getCause();
      if (cause != null)
        throw cause;
      throw e;
    }
}

总结:
1、FeignAutoConfiguration自动配置类,注册FeignContext,FeignContext继承NamedContextFactory,内部未每一个feiginclient创建一个spring容器
2、EnableFeignClients注解开启feign,@Import(FeignClientsRegistrar.class),注册配置和FeignClients
3、创建扫描器扫描@FeignClient注解标记的接口,注册为FeignClientFactoryBean类型的工厂bean
4、spring启动初始化bean时,调用工厂bean的getObject方法,生成代理对象
5、方法执行时,调用LoadBalancerFeignClient的execute方法,最终还是整合了ribbon,封装FeignLoadBalancer.RibbonRequest,实现负载均衡的调用。

源码分析流程图:
在这里插入图片描述

  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值