【微服务|openfeign】@FeignClient详解

上一篇,我们通过使用sentinel整合feign,对二者都有了初步的了解,这一篇,更侧重于对feign的使用以及其细节。

整合的步骤大体和前者一致,我们先来看看@FeignClient。

【微服务|openfeign】@FeignClient详解

value/name

value和name的作用一样,如果没有配置url那么配置的值将作为服务名称,用于服务发现。

反之只是一个名称。

如果同时指定了url和name/value , 以url为准, name/value将作为服务的名称,url为服务的地址。

serviceId

serviceId已经废弃了,直接使用name即可。

contextId

如果有两个feignclient的名称都一样,可以通过指定不同的contextId来区分,不然同时存在两个bean就报错了。

当然,也可以配置spring.main.allow-bean-definition-overriding=true,作用是允许出现beanName一样的BeanDefinition。

让我们看一看源码:

org.springframework.cloud.openfeign.FeignClientsRegistrar#getClientName

 private String getClientName(Map<String, Object> client) {
  if (client == null) {
   return null;
  }
  String value = (String) client.get("contextId");
  if (!StringUtils.hasText(value)) {
   value = (String) client.get("value");
  }
  if (!StringUtils.hasText(value)) {
   value = (String) client.get("name");
  }
  if (!StringUtils.hasText(value)) {
   value = (String) client.get("serviceId");
  }
  if (StringUtils.hasText(value)) {
   return value;
  }

  throw new IllegalStateException("Either 'name' or 'value' must be provided in @"
    + FeignClient.class.getSimpleName());
 }

可以看到如果配置了contextId就会用contextId,如果没有配置就会去value然后是name最后是serviceId。默认都没有配置,当出现一个服务有多个Feign Client的时候就会报错了。

其次的作用是在注册FeignClient中,contextId会作为Client 别名的一部分,如果配置了qualifier优先用qualifier作为别名。

 private void registerFeignClient(BeanDefinitionRegistry registry,
   AnnotationMetadata annotationMetadata, Map<String, Object> attributes)
 
{
  String className = annotationMetadata.getClassName();
  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 holder = new BeanDefinitionHolder(beanDefinition, className,
    new String[] { alias });
  BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);
 }

url

用于配置指定服务的地址,相当于直接请求这个服务,不经过负载均衡器的服务选择。

decode404

当调用请求发生404错误时,decode404的值为true,那么会执行decoder解码,否则抛出异常。

configuration

configuration是配置Feign配置类,在配置类中可以自定义Feign的Encoder、Decoder、LogLevel、Contract等。

fallback

定义容错的处理类,也就是回退逻辑,fallback的类必须实现Feign Client的接口,无法知道熔断的异常信息。

fallbackFactory

也是容错的处理,可以知道熔断的异常信息。

path

path定义当前FeignClient访问接口时的统一前缀,比如接口地址是/user/get, 如果你定义了前缀是user, 那么具体方法上的路径就只需要写/get 即可,当我们项目中配置了server.context-path,server.servlet-path时使用。

primary

primary对应的是@Primary注解,默认为true,官方这样设置也是有原因的。当我们的Feign实现了fallback后,也就意味着Feign Client有多个相同的Bean在Spring容器中,当我们在使用@Autowired进行注入的时候,不知道注入哪个,所以我们需要设置一个优先级高的,@Primary注解就是干这件事情的。

qualifier

qualifier对应的是@Qualifier注解,一般场景直接@Autowired直接注入就可以了。

如果我们的Feign Client有fallback实现,默认@FeignClient注解的primary=true, 意味着我们使用@Autowired注入是没有问题的,会优先注入你的Feign Client。

如果你鬼斧神差的把primary设置成false了,直接用@Autowired注入的地方就会报错,不知道要注入哪个对象。

解决方案很明显,你可以将primary设置成true即可,如果由于某些特殊原因,你必须得去掉primary=true的设置,这种情况下我们怎么进行注入,我们可以配置一个qualifier,然后使用@Qualifier注解进行注入。


原文始发于微信公众号(步尔斯特):【微服务|openfeign】@FeignClient详解

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/48088.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!