Подтвердить что ты не робот

Spring autwiring с уникальным beans: spring ожидаемым однократным сопоставлением bean, но найдено 2

Я пытаюсь autwire некоторые beans (для инъекции зависимостей), используя Spring для webapp. Один контроллер bean содержит другой bean, который, в свою очередь, содержит хэш-карту другого набора beans. Пока на карте только одна запись. Когда я запускаю 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>

Класс asscoaites с автоподвешенным контроллером и сервисом 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(); }

Пожалуйста, помогите!

4b9b3361

Ответ 1

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

Когда вы ссылаетесь на SuggestionService на @Autowired, в вашем контроллере, Spring autwires "по типу" по умолчанию и найдите два beans типа 'SuggestionService'

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

  • Удалить @Component из вашей службы и зависеть от сопоставления через XML - Самый простой
  • Удалить службу предложений из XML и выполнить аутсорсинг зависимостей - используйте утилиту: map, чтобы ввести карту indexSearchers.
  • Используйте @Resource вместо @Autowired, чтобы выбрать bean по его имени.

    @Resource("suggestionService")
    private SuggestionService service;
    

или

    @Resource("SuggestionService")
    private SuggestionService service;

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

Ответ 2

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

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

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

SuggestionService suggestion;

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

public void setSuggestion(final Suggestion suggestion) {
    this.suggestion = suggestion;
}

Ответ 3

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

@component ( "suggestionServicefake" )

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

@Qualifier ( "suggestionServicefake" )

который решил проблему

Ответ 4

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

@Component
public class SuggestionService {

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

@Component("suggestionService")
public class SuggestionService {

или

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

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

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

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