解决The bean ‘XXX.FeignClientSpecification‘ could not be registered

解决完上个问题,紧接着就出现这个问题The bean ‘XXX.FeignClientSpecification’ could not be registered.A bean with that name has already been defined and overriding is disabled.
在这里插入图片描述

问题描述

出现问题的代码如下:

// yz-service-pay模块
@FeignClient(
        value = ServiceConstants.USER_SERVICE_NAME,
        fallback = PayUserServiceFallBackFactory.class
)
public interface PayUserFeign extends UserFacade {
}
//yz-service-promotion模块
@FeignClient(
        name = ServiceConstants.USER_SERVICE_NAME,
        fallback = PromotionUserServiceFallBackFactory.class
)
public interface PromotionUserFeign extends UserFacade {
}

这个问题的原因是项目中有多个FeignClient声明的服务一样的,导致出错

解决方法

方法一:
按照他的提示在配置文件中添加配置

// .yaml文件
spring:
  main:
    allow-bean-definition-overriding: true

方法二:
在@FeignClient注解里面添加contextId属性

// yz-service-pay模块
@FeignClient(
        contextId = "payUser",
        value = ServiceConstants.USER_SERVICE_NAME,
        fallback = PayUserServiceFallBackFactory.class
)
public interface PayUserFeign extends UserFacade {
}
//yz-service-promotion模块
@FeignClient(
		contextId = "promotionUser",
        name = ServiceConstants.USER_SERVICE_NAME,
        fallback = PromotionUserServiceFallBackFactory.class
)
public interface PromotionUserFeign extends UserFacade {
}

分析:为什么要加一个contextId就不报错了呢

直接看源码

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

FeignClientsRegistrar类

// FeignClientsRegistrar.java
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
	registerDefaultConfiguration(metadata, registry);
	registerFeignClients(metadata, registry);
}

registerFeignClients方法 (FeignClientsRegistrar)

public void registerFeignClients(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
	// 省略前部分代码
	// 主要就是getClientName这个方法
	String name = getClientName(attributes);
	String className = annotationMetadata.getClassName();
	registerClientConfiguration(registry, name, className, attributes.get("configuration"));
	registerFeignClient(registry, annotationMetadata, attributes);
}

getClientName方法 (FeignClientsRegistrar)

// 返回className
private String getClientName(Map<String, Object> client) {
	if (client == null) {
		return null;
	}
	//从缓存中获取contextId
	String value = (String) client.get("contextId");
	if (!StringUtils.hasText(value)) {
		// 如果contextId为空,就获取value属性
		value = (String) client.get("value");
	}
	if (!StringUtils.hasText(value)) {
		// 如果value为空,就获取name属性
		value = (String) client.get("name");
	}
	if (!StringUtils.hasText(value)) {
		// 如果name为空,就获取serviceId属性
		value = (String) client.get("serviceId");
	}
	// 返回value(此value是最终值,不是map里面存储的value)
	if (StringUtils.hasText(value)) {
		return value;
	}

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

通过源码分析,我们可以发现,当多个Feign客户端指向同一个服务时,如果不指定contextId,这些客户端在注册过程中可能会因为获取到相同的className而导致冲突,从而引发注册失败的问题。因此,在配置多个指向相同服务的Feign客户端时,正确设置contextId是至关重要的,以确保每个客户端都能被Spring框架唯一地识别和注册。

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值