@FeignClient注解中属性contextId的使用说明

网友投稿 507 2022-07-22


目录一、概述二、解决方案2.1 方案12.2 方案2三、源代码分析相关代码1相关代码2

一、概述

如果我们使用Feign定义了两个接口,但是目标服务是同一个,那么在SpringBoot启动时就会遇到一个问题:

Description:The bean 'xxxxxxxx.FeignClientSpecification', defined in null, could not be registered. A bean with that name has already been defined in null and overriding is disabled.Action:Consider renaming one of the beans or enabBStvCLling overriding by setting spring.main.allow-bean-definition-overriding=true

二、解决方案

2.1 方案1

修改yml配置:spring.main.allow-bean-definition-overriding=true

spring:

main:

allow-bean-definition-overriding: true

2.2 方案2

在每个Feign的接口中,在注解BStvCL上加 contextId属性

contextId在Feign Client的作用是在注册Feign Client Configuration的时候需要一个名称,名称是通过getClientName方法获取的

@FeignClient(name = "sale-service",contextId= "saleservice1")

public interface saleClient{

@RequestMapping(value = "/sale/add", method = RequestMethod.GET)

String add(@RequestParam("saleNum") String queryStr);

}

备注:contextId= "名称" 中的名称,不能用“_”会报错,可以用“-”

三、源代码分析

包名:spring-cloud-openfeign-core-2.2.5.RELEASE.jar类路径:org.springframework.cloud.openfeign.FeignClientsRegistrar

相关代码1

private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Map attributes) {

String className = annotationMetadata.getClassName();

BeanDefinitionBuilder definition = BeanDefinitionBuilder.genericBeanDefinition(FeignClientFactoryBean.class);

this.validate(attributes);

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);

String alias = contextId + "FeignClient";

AbstractBeanDefinition beanDefinition = definition.getBeanDefinition();

beanDefinition.setAttribute("factoryBeanObjectType", className);

boolean primary = (Boolean)attributes.get("primary");

beanDefinition.setPrimary(primary);

String qualifier = this.getQualifier(attributes);

if (StringUtils.hasText(qualifier)) {

alias = qualifier;

}

BeanDefinitionHolder holder = new BeanDefinitionHolder(beanDefinition, className, new String[]{alias});

BeanDefinitionReaderUtils.registerBeanDefinition(holder, registry);

}

代码截图:

相关代码2

可以看到, name应该是从注解中的属性取值来的, 再看看getClientName()方法.

private String getClientName(Map client) {

if (client == null) {

return null;

} else {

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;

} else {

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

}

}

}

代码截图:

一目了然了, 我们声明@FeignClient注解时, 只使用了value属性, 所以产生了冲突, 只要加上contextId就好了.


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:基于Bigdecimal科学计数问题
下一篇:BigDecimal divide除法除不尽报错的问题及解决
相关文章

 发表评论

暂时没有评论,来抢沙发吧~