2012-12-10 4 views
31

Ich habe ein Problem mit einigen Spring Bean-Definitionen. Ich habe ein paar Kontext-XML-Dateien, die von meiner main() -Methode geladen werden, und beide enthalten fast ausschließlich ein Tag. Als meine Hauptmethode startet, erhalte ich diese Störung von Spring:Der Name des Annotation-spezifizierten Beans steht im Konflikt mit dem vorhandenen nicht-kompatiblen Bean def

Caused by: org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name 'converterDAO' for bean class [my.package.InMemoryConverterDaoImpl] conflicts with existing, non-compatible bean definition of same name and class [my.other.package.StaticConverterDAOImpl] 

Beide DAO-Klassen mit Anmerkungen versehen werden auf diese Weise:

@Repository("converterDAO") 
public class StaticConverterDAOImpl implements ConverterDAO { 
... 
} 

Die In-Memory-dao hat auch die @Repository ("converterDAO") Annotation. Die dao in anderen Klassen wie folgt verwiesen:

... 
private @Autowired @Qualifier("converterDAO") ConverterDAO converterDAO; 
... 

ich ein DAO wollen die Definition des anderen außer Kraft zu setzen, die, wie ich immer war es verstanden einer der Hauptgründe, einen DI Rahmen in der ersten verwenden Ort. Ich mache das seit Jahren mit XML-Definitionen und hatte nie Probleme. Nicht so bei Komponenten-Scans und annotierten Bean-Definitionen? Und was bedeutet Frühling, wenn es sagt, dass sie nicht "kompatibel" sind? Sie implementieren die gleiche Schnittstelle und werden in Felder mit diesem Schnittstellentyp automatisch eingefügt. Warum zum Teufel sind sie nicht kompatibel?

Kann mir jemand eine Möglichkeit geben, dass eine mit Anmerkungen versehene Komponente gescannte Bean überschreibt?

-Mike

+0

gibt es etwas komisches mit Ihnen zweiten Code schnippeln ... bitte überprüfen Sie es. – Yevgeniy

+0

Vielleicht müssen Sie Ihre Hauptmethode teilen? –

+0

Bitte fügen Sie die tatsächliche Deklaration des converterDAO Felds hinzu. Ist es eine 'ConverterDao'-Schnittstelle oder Implementierung? Es ist nicht klar aus der Frage. –

Antwort

22

In einer XML-Datei, gibt es eine Folge von Erklärungen, und Sie können mit einem neueren einer vorherigen Definition außer Kraft setzen. Wenn Sie Annotationen verwenden, gibt es keine vor oder nach. Alle Bohnen sind auf dem gleichen Niveau. Sie haben zwei Beans mit demselben Namen definiert, und Spring weiß nicht, welchen es auswählen soll.

Geben Sie ihnen einen anderen Namen (staticConverterDAO, inMemoryConverterDAO zum Beispiel), einen Aliasnamen in der Spring-XML-Datei erstellen (theConverterDAO zum Beispiel), und diesen Alias ​​verwenden, wenn Sie den Konverter Injektion:

@Autowired @Qualifier("theConverterDAO") 
+1

Warum gibt es keine Vorstellung von vorher oder nachher? Ich habe zwei Kontextdateien, eine wird geladen, dann die nächste. In dieser Hinsicht unterscheidet sich nichts von reinen XML-Definitionen. Die Reihenfolge ist einfach die Reihenfolge, in der die Komponentenscananweisungen auftreten. Beim zweiten Scan erzeugte Bohnen überschreiben Bohnen, die beim ersten Scan erzeugt wurden. Ich höre, was du sagst, aber ich verstehe die Logik oder den technischen Grund dahinter nicht. Auch ist es nicht dokumentiert und die Ausnahme macht überhaupt keinen Sinn. Nicht deine Schuld natürlich :-) Punkte für die Alias-Idee. Besser als zurück zu XML-Definitionen. – user1283068

+0

Auch im Hinblick auf die Vorschlag hat es die Implikation, dass alle verschiedenen Implementierungen von ConverterDAO von Spring erkannt und instanziiert werden, wenn die Kontextdateien geladen werden. Mit XML wird nur die letzte überschreibende Implementierung gestartet. Dies bedeutet, dass alle autoverwirkten Abhängigkeiten aller ConverterDAO-Implementierungen vorhanden sein müssen, obwohl nur einer jemals verwendet wird. – user1283068

+0

Jede Strategie, um Bean Name Konflikt mit Jar-Archiven zu vermeiden? – Stephane

19

Ich hatte ein ähnliches Problem, mit zwei jar-Bibliotheken (app1 und app2) in einem Projekt. Die Bean "BeanName" ist in app1 definiert und wird in app2 erweitert und die Bean wird mit demselben Namen neu definiert.

In App1:

package com.foo.app1.pkg1; 

@Component("BeanName") 
public class Class1 { ... } 

In App2:

package com.foo.app2.pkg2; 

@Component("BeanName") 
public class Class2 extends Class1 { ... } 

Dies bewirkt, dass die ConflictingBeanDefinitionException Ausnahme in dem Laden des application aufgrund der gleichen Komponente bean Namen.

Um dieses Problem in der Spring-Konfigurationsdatei applicationContext.xml zu lösen:

<context:component-scan base-package="com.foo.app2.pkg2"/> 
<context:component-scan base-package="com.foo.app1.pkg1"> 
    <context:exclude-filter type="assignable" expression="com.foo.app1.pkg1.Class1"/> 
</context:component-scan> 

So ist der Class1 ist ausgeschlossen automatisch bauteil gescannt und an eine Bean zugeordnet sein, um den Konflikt Namen zu vermeiden.

12

Ich hatte ein ähnliches Problem mit Spring 4.x mit @RestController.Zwei verschiedene Pakete hatten eine Klasse mit dem gleichen Namen ...

package com.x.catalog 

@RestController 
public class TextureController { 
... 

package com.x.cms 
@RestController 
public class TextureController { 
... 

Das Update war einfach ...

package com.x.catalog 

@RestController("CatalogTextureController") 
public class TextureController { 
... 

package com.x.cms 
@RestController("CMSTextureController") 
public class TextureController { 
... 

Das Problem scheint zu sein, dass die Anmerkung wird autowired und nimmt den Namen der Klasse von Standard. Wenn Sie der Annotation @RestController einen expliziten Namen geben, können Sie die Klassennamen beibehalten.

+1

Danke, arbeitete wie Charme. – Azim

Verwandte Themen