Spring Bean重复 - NoUniqueBeanDefinitionException : expected single matching bean but found 2

本文介绍了如何处理Spring框架中遇到的NoUniqueBeanDefinitionException异常,该异常通常由于存在多个相同类型的bean定义而引发。文章通过一个实际案例,解释了问题的原因,包括bean继承和接口实现等多个可能导致此错误的情况,并提供了解决方案,如使用@Qualifier注解进行明确注入,或者通过调整代码设计以避免这种情况。最后,作者提倡在设计时考虑使用工厂模式以提高代码的可维护性和扩展性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文分享一则Spring NoUniqueBeanDefinitionException: expected single matching bean but found 2的排查案例。

问题处理

公司的一个Spring服务,启动时报错,log如下
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type ‘com.xxx.service.XxxService’ available: expected single matching bean but found 2: xxxService,subXxxService

错误说的比较清楚:装载bean com.xxx.service.XxxService时,发现了两个定义,不知道用哪个。并且告诉了我具体的两个类:xxxServicesubXxxService

排查服务代码,发现xxxService有个子类,这样通过xxxService类型去注入bean时,会找到父类和子类两个类、无法决定注入哪个:

// 服务1
@Component
public class XxxService {...}

// 服务2(继承服务1)
@Component
public class SubXxxService extends XxxService {...}

// 服务调用方
@Component
public class ServiceUser  {
	@Autowired
	private XxxService service;
}

两个bean都在使用,那只能给两个类加下标识来区分了:

// 服务1
@Component("service.xxx")
public class XxxService {...}

// 服务2(继承服务1)
@Component("service.xxx.sub")
public class SubXxxService extends XxxService {...}

// 服务调用方
@Component
public class ServiceUser  {
	@Resource(name = "service.xxx")
	private XxxService service;
}

问题解决。

总结

问题原因

除了继承这种情况,还有其他几种情况:

  • 两个Bean实现了同个接口,依赖Bean时使用接口注入Bean(本文的问题其实是这种情况的一个特例)
  • 不同包有同名的bean
  • 错误配置了类扫描,如xml和@ComponentScan重复配置、注解本身重复配置,导致bean注入两次

解决思路

只保留一个

如果业务上永远只会用到一个实现,那么可以使用@Primary将该实现标识为优先注入:

@Primary
@Component

但一般业务中这种情况不多。

通过其他标识区分bean

定义bean有两种方案

  • @Component @Qualifier("service.xxx")
  • @Component("service.xxx")

注入依赖也有两种方案:

  • 使用@Resource注解

    @Resource(name = "service.xxx")

  • 使用@Qualifier注解

    @Autowired @Qualifier("service.xxx")

其他思考

  1. 代码设计不太好,后来把两个bean改成了工厂模式,处理这种相似业务更恰当,扩展更便捷
  2. 使用名称修饰不同的bean,后面的代码维护也不是很友好。还是尽可能避免这种情况。

以上。
感谢您的阅读。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值