29

Sto provando a scartare alcuni bean (per l'iniezione delle dipendenze) utilizzando Spring per una webapp. Un bean controller contiene un altro bean che a sua volta contiene una hashmap di un altro set di bean. Per ora la mappa ha solo una voce. Quando eseguo in Tomcat e chiamare il servizio di ottengo un errore dicendo che il secondo di fagioli (tenutosi a controllore) non riguardano soloautowiring primaverile con bean univoci: fagiolo corrispondente corrispondente alla primavera ma trovato 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] 

non riesco a vedere dove sono la definizione del chicco di due volte però sono nuovo primavera e autowiring in modo che possa mancare qualcosa di fondamentale. Il codice sorgente per XML e 2 classe elencato di seguito ...

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

Le asscoaites classe con il controller autowired e fagioli di servizio sono qui ...

@Controller 
public class SuggestionController { 
private SuggestionService service; 

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

public SuggestionService getService() { 
    return service; 
} 

e ...

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

Si prega di aiuto!

risposta

40

Il problema è perché avete un bean di tipo SuggestionService creato tramite l'annotazione @Component e anche tramite la configurazione XML. Come spiegato da JB Nizet, ciò porterà alla creazione di un bean con nome 'suggestionService' creato tramite @Component e un altro con nome 'SuggestionService' creato tramite XML.

Quando si fa riferimento SuggestionService da @Autowired, nel controller, autowires Primavera "per tipo" per impostazione predefinita e trovare due chicchi di tipo 'SuggestionService'

Si potrebbe fare la seguente

  1. Rimuovere @ Componente dal tuo servizio e dipende dalla mappatura tramite XML - Il più semplice
  2. Rimuovi SuggestionService da XML e autowire le dipendenze - usa util: map per iniettare la mappa indexSearchers.
  3. Utilizzare @Resource anziché @Autowired per selezionare il bean in base al nome.

    @Resource("suggestionService") 
    private SuggestionService service; 
    

o

@Resource("SuggestionService") 
    private SuggestionService service; 

entrambi dovrebbero funzioni l'terzo è una correzione sporca ed è meglio per risolvere il conflitto di fagioli con altri sensi.

+0

Brillante Ho semplicemente rimosso il componente dalla classe di servizio. Quindi ho ricevuto un errore sul controller che si registra due volte e ho risolto questo problema rimuovendo la scansione dei componenti come da questa soluzione http://stackoverflow.com/a/4804417/491196 Grazie per il tuo aiuto –

5

Se non sbaglio, il nome bean predefinito di un bean dichiarato con @Component è il nome della sua classe la sua prima lettera in lettere minuscole. Ciò significa che

@Component 
public class SuggestionService { 

dichiara un fagiolo di tipo SuggestionService, e del nome suggestionService. E 'equivalente a

@Component("suggestionService") 
public class SuggestionService { 

o per

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

Stai ridefinire un altro bean dello stesso tipo, ma con un nome diverso, in XML:

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

Quindi, o specificare il nome del bean nell'annotazione da SuggestionService oppure utilizzare l'ID suggestionService nell'XML (non dimenticare di modificare anche l'elemento <ref> o di rimuoverlo, dal momento che non è necessario). In questo caso, la definizione XML sostituirà la definizione di annotazione.

+0

dispiace I dont abbastanza seguire la tua prima frase è un po 'strangly scritto. Perché "@Component public class SuggestionService {" e il bean nell'xml dichiarano due bean? –

+0

Sulla tua ultima frase dici "o specifica il nome del bean nell'annotazione per essere SuggestionService" non è questo quello che ho? Ho provato a cambiare la definizione del bean xml in minuscolo ma il problema persisteva. Grazie per il tuo aiuto :) –

+0

Le mie modifiche dovrebbero essere più chiare. –

13

Se si hanno 2 bean della stessa classe avviati a una classe, utilizzare @Qualifier (Spring Autowiring @Qualifier example).

Ma sembra che il problema sia dovuto alla sintassi Java errata.

vostro oggetto dovrebbe iniziare con la lettera minuscola

SuggestionService suggestion; 

tuo setter dovrebbe iniziare con lettere minuscole come bene e opporsi nome dovrebbe essere con Maiuscolo

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

Il tuo diritto sul nome del setter e la maiuscola. Devo averlo cambiato in modo errato mentre giocavo con esso per farlo funzionare. Sfortunatamente non sembra essere il problema. Ho aggiornato la domanda precedente con il setter corretto. –

6

Per me è stato il caso di avere due bean che implementano la stessa interfaccia. Uno era un falso divieto per il test unitario che era in conflitto con il fagiolo originale. Se usiamo

@component ("suggestionServicefake")

, ancora riferimenti con suggestionService. così ho rimosso @component e utilizzato solo

@Qualifier ("suggestionServicefake")

che ha risolto il problema

+0

Lo stesso se usi la proprietà @SpringBootTest (classes = SuggestionService.class) nella tua classe di test. – DocDbg

Problemi correlati