使用唯一的bean进行spring自动装配:spring需要单个匹配bean,但是发现2

我正在尝试使用Spring为webapp自动装配一些bean(用于依赖注入)。 一个控制器bean包含另一个bean,后者又保存另一组bean的哈希图。 目前,该地图只有一个条目。 当我在tomcat中运行并调用服务时,我收到一条错误消息,说第二个bean(保存在控制器中)不是唯一的

No unique bean of type [com.hp.it.km.search.web.suggestion.SuggestionService] is defined: expected single matching bean but found 2: [suggestionService, SuggestionService]

我看不到我在两次定义bean的地方,但是对于Spring和自动装配来说是新的,所以我可能缺少一些基本知识。 xml和以下2类的源代码...

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"     xmlns:context="http://www.springframework.org/schema/context"     xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
    http://www.springframework.org/schema/mvc
    http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">

<context:component-scan base-package="com.hp.it.km.search.web.suggestion" />
<mvc:annotation-driven />
<context:annotation-config />

<bean id="SuggestionController" class="com.hp.it.km.search.web.suggestion.SuggestionController">
    <property name="service">
        <ref bean="SuggestionService" />
    </property>
</bean>

<bean id="SuggestionService" class="com.hp.it.km.search.web.suggestion.SuggestionService">
    <property name="indexSearchers"> 
         <map>
            <entry key="KMSearcher"> <ref bean="KMSearcherBean"></ref></entry>
        </map>
    </property>
</bean>

<bean id="KMSearcherBean" class="com.hp.it.km.search.web.suggestion.SuggestionIndexSearcher">
      <constructor-arg index="0" value="KMSearcher" />
      <constructor-arg index="1" value="C://dev//workspace//search-restful-webapp//src//main//resources//indexes//keyword" />
</bean>

与自动接线的控制器和服务Bean相关的类在这里...

@Controller
public class SuggestionController {
private SuggestionService service;

@Autowired
public void setService(SuggestionService service) {
    this.service = service;
}

public SuggestionService getService() {
    return service;
}

和...

@Component
public class SuggestionService {

private Map<String, IndexSearcher> indexSearchers = new HashMap<String,      IndexSearcher>();

@Autowired
public void setIndexSearchers(Map<String, IndexSearcher> indexSearchers) {
    this.indexSearchers = indexSearchers;
}

    public SuggestionService() {
    super(); }

请帮忙!

4个解决方案
55 votes

问题是因为您具有通过@Component注释以及通过XML config创建的类型为RecommendationionService的bean。 正如JB Nizet解释的那样,这将导致创建一个通过@Component创建的名称为'suggestionService'的bean和另一个通过XML创建的名称为'SuggestionService'的bean。

当您通过@Autowired引用RecommendationionService时,在您的控制器中,Spring默认情况下会“按类型”自动装配并找到两个类型为'SuggestionService'的bean。

您可以执行以下操作

  1. 从您的服务中删除@Component并依靠通过XML进行映射-最简单
  2. 从XML中删除RecommendationionService并自动关联依赖项-使用util:map注入indexSearchers映射。
  3. 使用@Resource而不是@Autowired来按其名称选择bean。

    @Resource("suggestionService")
    private SuggestionService service;
    

要么

    @Resource("SuggestionService")
    private SuggestionService service;

两者都应该起作用。第三是肮脏的修复程序,最好通过其他方式解决bean冲突。

Aravind A answered 2020-08-03T02:19:53Z
15 votes

如果您将2个相同类的bean自动连接到一个类,则应使用@Qualifier(Spring Autowiring @Qualifier示例)。

但似乎您的问题来自错误的Java语法。

您的对象应以小写字母开头

SuggestionService suggestion;

设置器也应以小写开头,对象名称也应以大写开头

public void setSuggestion(final Suggestion suggestion) {
    this.suggestion = suggestion;
}
danny.lesnik answered 2020-08-03T02:20:27Z
6 votes

如果我没记错的话,用@Component声明的bean的默认bean名称是其类的名称,其首字母小写。 这意味着

@Component
public class SuggestionService {

声明类型为SuggestionService且名称为suggestionService的bean。

@Component("suggestionService")
public class SuggestionService {

或者

<bean id="suggestionService" .../>

您正在XML中重新定义另一个相同类型但名称不同的bean:

<bean id="SuggestionService" class="com.hp.it.km.search.web.suggestion.SuggestionService">
    ...
</bean>

因此,要么在注释中将bean的名称指定为SuggestionService,要么在XML中使用ID suggestionService(不要忘记也修改<ref>元素,或者将其删除,因为不需要它)。 在这种情况下,XML定义将覆盖注释定义。

JB Nizet answered 2020-08-03T02:21:05Z
6 votes

对我来说,是两个bean实现相同接口的情况。 一个是为了单元测试而假的禁令,这与原始的bean相冲突。如果我们使用

@component(“ suggestionServicefake”)

,它仍然使用建议服务引用。所以我删除了@component而只使用了

@Qualifier(“ suggestionServicefake”)

解决了问题

vsingh answered 2020-08-03T02:21:43Z
translate from https://stackoverflow.com:/questions/8414287/spring-autowiring-with-unique-beans-spring-expected-single-matching-bean-but-fo