it-swarm.com.de

frühlingsautodraht mit einzigartigen Bohnen: Einzelne passende Bohne erwartet, aber gefunden 2

Ich versuche, einige Bohnen (für die Abhängigkeitsinjektion) mithilfe von Spring für eine Webanwendung automatisch zu verdrahten. Eine Controller-Bean enthält eine andere Bean, die wiederum eine Hashmap einer anderen Gruppe von Beans enthält. Die Karte hat vorerst nur einen Eintrag. Wenn ich in Tomcat rufe und den Dienst anrufe, erhalte ich die Fehlermeldung, dass die zweite Bean (die im Controller gespeichert ist) nicht eindeutig ist

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

Ich kann nicht sehen, wo ich die Bohne zweimal definiere, bin jedoch neu in Spring und Autowiring, sodass mir möglicherweise etwas Grundlegendes fehlt. Quellcode für XML und Klasse 2 unten aufgeführt ...

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

Die Klassenkameraden mit dem Autowired-Controller und der Servicebohne sind da ...

@Controller
public class SuggestionController {
private SuggestionService service;

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

public SuggestionService getService() {
    return service;
}

und...

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

Bitte um Hilfe!

41
Rob McFeely

Das Problem liegt daran, dass Sie eine Bean vom Typ SuggestionService haben, die durch @Component-Annotation und auch durch die XML-Konfiguration erstellt wurde. Wie von JB Nizet erklärt, führt dies dazu, dass eine Bean mit dem Namen 'suggestionService' erstellt wird, die über @Component erstellt wird, und eine andere mit dem Namen 'SuggestionService', die über XML erstellt wird.

Wenn Sie auf SuggestionService von @Autowired verweisen, wird Spring in Ihrem Controller standardmäßig "nach Typ" automatisch verkabelt und es werden zwei Beans des Typs "SuggestionService" gefunden.

Sie könnten Folgendes tun

  1. Entfernen Sie @Component aus Ihrem Service und verlassen Sie sich auf die Zuordnung über XML - Am einfachsten
  2. Entfernen Sie SuggestionService aus XML und verdrahten Sie die Abhängigkeiten automatisch. Verwenden Sie util: map, um die indexSearchers-Map einzufügen.
  3. Verwenden Sie @Resource anstelle von @Autowired, um die Bean nach ihrem Namen auszuwählen.

    @Resource("suggestionService")
    private SuggestionService service;
    

oder

    @Resource("SuggestionService")
    private SuggestionService service;

beides sollte funktionieren. Der dritte ist ein Dirty Fix und es ist am besten, den Bean-Konflikt auf andere Weise zu lösen.

54
Aravind A

Wenn Sie 2 Beans derselben Klasse haben, die automatisch mit einer Klasse verkabelt wurden, sollten Sie @Qualifier ( Beispiel für Spring Autowiring @Qualifier ).

Aber es scheint, dass Ihr Problem von einer falschen Java Syntax herrührt.

Ihr Objekt sollte mit Kleinbuchstaben beginnen

SuggestionService suggestion;

Ihr Setter sollte ebenfalls mit Kleinbuchstaben beginnen und der Objektname sollte mit Großbuchstaben beginnen

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

Wenn ich mich nicht irre, ist der Standard-Bean-Name eines mit @Component deklarierten Bean der Name seiner Klasse, dessen erster Buchstabe in Kleinbuchstaben geschrieben ist. Das bedeutet, dass

@Component
public class SuggestionService {

deklariert eine Bean vom Typ SuggestionService und vom Namen suggestionService. Es ist gleichbedeutend mit

@Component("suggestionService")
public class SuggestionService {

oder zu

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

Sie definieren eine andere Bean desselben Typs mit einem anderen Namen im XML-Format neu:

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

Geben Sie also entweder den Namen der Bean in der Annotation als SuggestionService an oder verwenden Sie die ID suggestionService in der XML (vergessen Sie nicht, auch das <ref> Element, oder um es zu entfernen, da es nicht benötigt wird). In diesem Fall überschreibt die XML-Definition die Anmerkungsdefinition.

6
JB Nizet

Für mich war es der Fall, dass zwei Beans dieselbe Schnittstelle implementieren. Eines war ein gefälschtes Verbot aus Gründen des Einheitentests, das im Widerspruch zu Originalbohnen stand. Wenn wir verwenden

@component ("suggestionServicefake")

verweist es noch mit suggestionService. Also habe ich @component entfernt und nur benutzt

@Qualifier ("suggestionServicefake")

das löste das problem

6
vsingh