发布时间:2023-08-03 09:30
如果我们使用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 enabling overriding by setting spring.main.allow-bean-definition-overriding=true
修改yml配置:spring.main.allow-bean-definition-overriding=true
spring: main: allow-bean-definition-overriding: true
在每个Feign的接口中,在注解上加 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= \"名称\" 中的名称,不能用“_”会报错,可以用“-”
private void registerFeignClient(BeanDefinitionRegistry registry, AnnotationMetadata annotationMetadata, Mapattributes) { 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); }
代码截图:
可以看到, name应该是从注解中的属性取值来的, 再看看getClientName()方法.
private String getClientName(Mapclient) { 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就好了.
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。