GenericDAO 和 NoSuchBeanDefinitionException:没有唯一的 bean Spring 3.0

Posted

技术标签:

【中文标题】GenericDAO 和 NoSuchBeanDefinitionException:没有唯一的 bean Spring 3.0【英文标题】:GenericDAO and NoSuchBeanDefinitionException: No unique bean Spring 3.0 【发布时间】:2012-06-20 08:45:40 【问题描述】:

我正在使用带有 genericDAO 的 Spring 3.0。我有这个:

public interface GenericDAO<T, ID extends Serializable>
...
@Repository("genericDAO")
public class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> 
...
public interface A extends GenericDAO<Turno, Long> 
...
public interface B extends GenericDAO<TipoTurno, Long> 
...
@Repository("A")
public class AImpl extends GenericDAOImpl<TipoTurno, Long>  implements A
...
@Repository("B")
public class BImpl extends GenericDAOImpl<TipoTurno, Long>  implements B

但是当我尝试按如下方式注入它们时:

@Autowired
A a;

我明白了:

预期的单个匹配 bean,但找到了 3 个:[genericDAOImpl, A, B]

我不明白为什么。我也试过用

@Resource(name="A")

甚至

@Resource(type=A.class)

我也尝试过使用@Qualifier,但我总是遇到同样的异常,看起来 Spring 总是在寻找 GenericDao 而不是特定的类。

但它仍然无法正常工作。我不明白为什么。

有什么建议吗?

非常感谢。

【问题讨论】:

您确定在所有三种情况下都收到相同的错误消息吗?我可以看到您如何在 @Autowired 案例中获得“预期的单个匹配 bean”消息,但绝对不是在 @Resource(name="A") 案例中。您是否可能同时注释了 getter 和成员变量? 非常感谢您的帮助。我已经加倍检查它来回答你,是的,当我使用 @Resource(name="specific_name") 我得到 org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [xxx.model.entities.dao. GenericDAO] 被定义:预期的单个匹配 bean,但找到了 3:[genericDAO,A,B]。关于您的问题,我没有对 getter 进行注释。 @CalamarBicefalo 限定符名称与接口相同,这是错误的 @NimChimpsky,我更改了限定符名称,而不是 A 我设置了猫,而不是 B 我设置了狗,这一次它再次失败:预期单个匹配 bean 但找到 3:[genericDAO,猫狗]。我试过用@Resource(name="cat") 来做。 删除 @Repository("genericDAO") 注释。您不需要将其定义为 bean。 【参考方案1】:

我复制了您的确切错误消息,然后修复了它。这正是我使用的源代码,减去包名。我建议复制它,运行它并与你的不同。我注意到的一个区别是,正如问题中所写,AImpl 无法编译。它实现了 GenericDAOImpl 和 GenericDAO。我将第一个通用参数更改为 Turno,以使其编译。我认为这是一个错字。当我最初将所有字段设置为 @Autowired 时,我准确地重现了您的错误。然后我添加了@Qualifier("genericDAO") 并成功连接了所有三个。

public interface GenericDAO<T, ID extends Serializable> 
...
@Repository("genericDAO")
public class GenericDAOImpl<T, ID extends Serializable> implements GenericDAO<T, ID> 
...
public interface A extends GenericDAO<Turno, Long> 
...
public interface B extends GenericDAO<TipoTurno, Long> 
...
@Repository("A")
public class AImpl extends GenericDAOImpl<Turno, Long> implements A 
...
@Repository("B")
public class BImpl extends GenericDAOImpl<TipoTurno, Long>  implements B 
...
public class TipoTurno 
...
public class Turno 
...
@Component
public class Thingy 
    @Autowired
    private A a;

    @Autowired
    private B b;

    @Autowired
    @Qualifier(value="genericDAO")
    private GenericDAO genericDao;

...
public class Main 
    public static void main(String[] args) 
        ApplicationContext context = new ClassPathXmlApplicationContext("genericdao.xml");
        context.getBean(Thingy.class);
    

...
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config/>
    <context:component-scan base-package="genericdao"/>
</beans>

请注意,实际的错误消息比您提供的要长。阅读整件事寻找原因很重要。 Spring 喜欢具有 5 甚至 10 级原因的异常堆栈跟踪。这是我收到的消息的相关子字符串:

无法自动装配字段:genericdao.GenericDAO genericdao.Thingy.genericDao;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有定义类型 [genericdao.GenericDAO] 的唯一 bean:预期单个匹配 bean 但找到 3:[A,B,genericDAO]

它表示没有被自动连接的字段是Thingy.genericDao,而不是Thingy.a。我强烈怀疑您的错误也是这种情况。

【讨论】:

它做到了。事实上,问题在于我试图在没有限定条件的情况下注入“genericDAO”。但这让我抓狂,因为我希望通过特定的注射来解决它。非常感谢@John Watts,非常有帮助。我不能投票赞成你的答案,因为我没有名声:'( 不客气。感谢您接受答案。我希望有关春季异常的评论会有所帮助。尽管它们通常包含必要的信息,但它可能会在大量原因中丢失。 仔细阅读异常跟踪是我发现错误的方式,所以是的,你的评论真的很有帮助。【参考方案2】:
@Repository("AImpl")
public class AImpl extends GenericDAOImpl<TipoTurno, Long>  implements A
...
@Repository("BImpl")
public class BImpl extends GenericDAOImpl<TipoTurno, Long>  implements B
...
@Resource(name = "AImpl")
A whatever; //I would normally call it aImpl

只要限定符名称匹配,您就可以开始了。该错误是由自动装配注入引起的,其中接口被实现了两次。

【讨论】:

谢谢 NimChimpsky,但如前所述,我在同时使用 @Resource(name= "specific_name") 和 @Resource(type=specific_class.class) 时遇到完全相同的异常 @CalamarBicefalo 看看我改变了什么。您的接口名称与限定符相同,这会导致问题。按照我概述的方式进行操作很好。 正如我上次回复中所说,它仍然无法正常工作。但无论如何,非常感谢@NimChimpsky。我用实现名称和随机名称都试过了。 @CalamarBicefalo 我根本无法复制它。您正在使用限定符名称进行注入? GenericDAO 在 AImpl 上“实现了两次”——这会在自动装配时引起问题。 @CalamarBicefalo 您需要删除自动连线注入。并且只使用限定符注入。并期待重构,它有点复杂的 api 设计

以上是关于GenericDAO 和 NoSuchBeanDefinitionException:没有唯一的 bean Spring 3.0的主要内容,如果未能解决你的问题,请参考以下文章

用于开发 GenericDao 的最佳 Spring API

Hibernate genericDao 投影

如何在 GenericDao 中检索常用值(IpAddress、TenantId)?

如何使用 QueryDSL 构建 GenericDao?

Hibernate GenericDAO 用于父/子关系和 DAO/DTO 模式

GenericDAO 与 Guice,玩泛型和 ParameterizedType