29

Próbuję automatycznie wyposażyć trochę fasoli (do wstrzyknięcia zależności) za pomocą Springa dla aplikacji webowej. Jeden komponent bean kontrolera zawiera kolejną fasolę, która z kolei trzyma zestaw innych fasoli. Na razie mapa ma tylko jeden wpis. Kiedy biegnę w Tomcat i wezwać serwis pojawia się błąd mówiący, że druga fasola (odbyła się w kontrolerze) nie jest wyjątkowyWiosna w automatach z unikatowymi fasolami: Wiosna oczekiwana pojedyncza pasująca fasola, ale znalazłem 2

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

nie widzę, gdzie jestem definiowania fasoli dwukrotnie jednak jestem nowy na wiosnę i autowiring, więc może brakować czegoś podstawowego. Kod źródłowy XML i 2 klasy wymienionych poniżej ...

<?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> 

klasy asscoaites z autowired kontrolera i fasoli usług są tutaj ...

@Controller 
public class SuggestionController { 
private SuggestionService service; 

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

public SuggestionService getService() { 
    return service; 
} 

i ...

@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(); } 

Proszę o pomoc!

Odpowiedz

40

Problem jest, bo masz komponent bean typu SuggestionService utworzony za pomocą adnotacji @ Component, a także poprzez konfigurację XML. Jak wyjaśnił JB Nizet, doprowadzi to do utworzenia komponentu bean o nazwie "suggestionService" utworzonego za pomocą @Component i innego o nazwie "SuggestionService" utworzonej przez XML.

Kiedy odnoszą SuggestionService przez @Autowired w kontrolerze, autowires Wiosna „wg typu” domyślnie i znaleźć dwa fasoli typu „SuggestionService”

Można wykonać następujące czynności

  1. Usuń @ Składnik z usługi i zależy od mapowania za pośrednictwem XML - najłatwiejszy
  2. Usuń SuggestionService z XML i przeprowadź autouzupełnianie zależności - użyj util: map, aby wprowadzić mapę indeksu wyszukiwania.
  3. Użyj @Resource zamiast @Aucowired, aby wybrać fasolę według nazwy.

    @Resource("suggestionService") 
    private SuggestionService service; 
    

lub

@Resource("SuggestionService") 
    private SuggestionService service; 

oba powinny work.The trzeci jest brudny fix i to najlepiej rozwiązać konflikt fasoli poprzez inne sposoby.

+0

Brilliant Po prostu usunąłem komponent z klasy serwisowej. Następnie otrzymałem komunikat o błędzie, że kontroler jest zarejestrowany dwa razy i obejrzałam to, usuwając skanowanie komponentu zgodnie z tym rozwiązaniem. Http://pl.steroidflow.com/a/4804417/491196 Dziękujemy za pomoc –

5

Jeśli się nie mylę, domyślna nazwa fasoli deklarowanej przez @Component jest nazwą jej pierwszej litery małej literą. Oznacza to, że

@Component 
public class SuggestionService { 

deklaruje fasoli typu SuggestionService i nazwy suggestionService. Jest to równoznaczne z

@Component("suggestionService") 
public class SuggestionService { 

lub

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

Jesteś redefinicji kolejną fasolkę tego samego typu, ale z inną nazwą, w formacie XML:

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

Więc, albo podaj nazwę fasoli w adnotacji, która ma być SuggestionService, lub użyj ID suggestionService w XML (nie zapomnij także zmodyfikować elementu <ref> lub usunąć go, ponieważ nie jest potrzebny). W takim przypadku definicja XML zastąpi definicję adnotacji.

+0

przykro I dont dość śledzić swoje pierwsze zdanie jej trochę strangly napisane. Dlaczego "@Component public class SuggestionService {" i komponent bean w xml deklarują dwa komponenty bean? –

+0

W swoim ostatnim zdaniu mówisz "albo podaj nazwę fasoli w adnotacji, która ma być Sugerowaną Usługą" czy to nie jest to, co mam? Próbowałem zmienić definicję komponentu bean w języku xml na małe litery, ale problem nadal występował. Thansk za twoją pomoc :) –

+0

Moje edycje powinny uczynić go jaśniejszym. –

13

Jeśli masz 2 ziarna tej samej klasy, które zostały automatycznie wypróbowane w jednej klasie, możesz użyć @Qualifier (Spring Autowiring @Qualifier example).

Wygląda na to, że Twój problem wynika z nieprawidłowej składni języka Java.

Państwa obiekt należy rozpocząć od małej litery

SuggestionService suggestion; 

Twój seter powinien zaczynać się małą literą, jak również i nazwa obiektu powinna być z Górnym przypadku

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

Twoje prawo do nazwy i imienia kapitana. Musiałem to zmienić niepoprawnie, bawiąc się nim, aby to zadziałało. Niestety to nie wydaje się być problemem. Ive zaktualizował powyższe pytanie z prawidłowym seter. –

6

Dla mnie był to przypadek posiadania dwóch komponentów obsługujących ten sam interfejs. Jednym z nich był fałszywy zakaz na próbę jednostkową, która była sprzeczna z oryginalną fasolą. Jeśli używamy

@component ("suggestionServicefake")

, to nadal referencje z suggestionService. Więc usunąłem @component a jedynie wykorzystywane

@Qualifier ("suggestionServicefake")

który rozwiązał problem

+0

To samo, jeśli korzystasz z właściwości @SpringBootTest (classes = SuggestionService.class) w twojej klasie testowej. – DocDbg