весенняя автопроводка с уникальными бобами: весна ожидала, что один соответствующий боб найден, но найден 2 - PullRequest
41 голосов
/ 07 декабря 2011

Я пытаюсь автоматически подключить некоторые bean-компоненты (для внедрения зависимостей), используя Spring для веб-приложения. Один бин контроллера содержит другой бин, который в свою очередь содержит хэш-карту другого набора бинов. На данный момент карта имеет только одну запись. Когда я запускаю tomcat и вызываю сервис, я получаю сообщение о том, что второй компонент (хранящийся в контроллере) не уникален

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

Я не могу понять, где я определяю бин дважды, однако я новичок в 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>

Классы asscoaites с автопроводным контроллером и компонентом обслуживания находятся здесь ...

@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 ]

53 голосов
/ 07 декабря 2011

Проблема в том, что у вас есть bean-компонент типа SuggestionService, созданный с помощью аннотации @Component, а также через XML-конфигурацию. Как объяснил JB Nizet, это приведет к созданию бина с именем 'SuggestionService', созданного с помощью @Component, а другого с именем 'SuggestionService', созданного с помощью XML.

Когда вы ссылаетесь на OffertionService от @Autowired, в вашем контроллере Spring по умолчанию автоматически связывает "по типу" и находит два bean-компонента типа 'SuggestionService'

Вы можете сделать следующее

  1. Удалите @Component из вашей службы и используйте отображение через XML - проще всего
  2. Удалите SuggestionService из XML и автоматически подключите зависимости - используйте util: map, чтобы внедрить карту indexSearchers.
  3. Используйте @Resource вместо @Autowired, чтобы выбрать бин по его имени.

    @Resource("suggestionService")
    private SuggestionService service;
    

или

    @Resource("SuggestionService")
    private SuggestionService service;

оба должны работать. Третье - грязное исправление, и лучше разрешить конфликт бинов другими способами.

15 голосов
/ 07 декабря 2011

Если у вас есть 2 бина одного и того же класса, автоматически подключенные к одному классу, который вы должны использовать @Qualifier ( Spring Autowiring @Qualifier example ).

Но похоже, что ваша проблема исходит отневерный синтаксис Java.

Ваш объект должен начинаться со строчной буквы

SuggestionService suggestion;

Ваш установщик должен начинаться также со строчной буквы, а имя объекта должно быть с верхним регистром

public void setSuggestion(final Suggestion suggestion) {
    this.suggestion = suggestion;
}
6 голосов
/ 08 августа 2012

Для меня это был случай, когда две компоненты реализовывали один и тот же интерфейс. Один из них был поддельным запретом ради юнит-теста, который противоречил оригинальному бину. Если мы используем

@ компонент ( "suggestionServicefake")

, это все еще ссылки с предложением службы. Поэтому я удалил @component и использовал только

@ Qualifier ( "suggestionServicefake")

которая решила проблему

6 голосов
/ 07 декабря 2011

Если я не ошибаюсь, по умолчанию имя компонента bean-компонента, объявленного с помощью @Component, является именем его класса, его первая буква в нижнем регистре.Это означает, что

@Component
public class SuggestionService {

объявляет компонент типа SuggestionService и имени suggestionService.Это эквивалентно

@Component("suggestionService")
public class SuggestionService {

или

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

В XML вы переопределяете другой бин того же типа, но с другим именем:

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

Таким образом, либо укажите имя компонента в аннотации как SuggestionService, либо используйте идентификатор suggestionService в XML (не забудьте также изменить элемент <ref> или удалить его,так как это не нужно).В этом случае определение XML переопределит определение аннотации.

...