2013-03-05 5 views
21

Wenn mehrere Spring Bohnen mit dem gleichen Namen definiert sind, welche werden die anderen verstecken?Welchen Vorrang haben Spring Beans Definitionen?

Lassen Sie uns sagen, ich habe mit @Component("bean") im Paket org.example mehrere Klassen mit Anmerkungen versehen, plus eine applicationContext.xml das enthält: wird

<context:component-scan base-package="org.example"/> 
<alias name="aliasedBean" alias="bean"/> 
<bean id="aliasedBean" class="org.example.AliasedBean"/> 
<bean id="bean" class="org.example.XmlBean"/> 
<import resource="otherApplicationContext.xml"/> 

Wich Bean abgerufen werden, wenn ich eine applicationContext.getBean("bean") tun?

Nach dem Spring documentation:

Jede Bohne hat eine oder mehrere Kennungen. Diese Bezeichner müssen innerhalb des Containers, der die Bean hostet, eindeutig sein.

Allerdings weiß ich (weil ich getestet habe), dass Frühling nicht beschweren wird, wenn dies getan wird. Eine Definition wird die anderen verbergen. Aber ich konnte nicht herausfinden, was die Regel war.

Ich möchte dies zu Testzwecken tun. Ich verwende Annotation-basierte Konfiguration, um echte (Produktions-) Beans zu definieren. Dann möchte ich eine testspezifische XML-Konfigurationsdatei verwenden, um diese Definitionen zu überschreiben und Scheinbohnen zu injizieren.

Bearbeiten: Da Sie mehrere waren, um für Protokolle zu fragen, verbrachte ich einige Zeit, einige zu erstellen. Hier sind sie:

0 INFO org.springframework.context.support.ClassPathXmlApplicationContext - Refreshing org[email protected]3934f69a: startup date [Wed Mar 06 23:04:35 CET 2013]; root of context hierarchy 
45 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [applicationContext.xml] 
223 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'bean': replacing [Generic bean: class [org.example.AnnotatedBean]; scope=singleton; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in file [/Users/etienne/Documents/Développement/Registre/workspace/SpringPrecedence/target/classes/org/example/AnnotatedBean.class]] with [Generic bean: class [org.example.XmlBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext.xml]] 
223 INFO org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from class path resource [otherApplicationContext.xml] 
246 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Overriding bean definition for bean 'bean': replacing [Generic bean: class [org.example.XmlBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [applicationContext.xml]] with [Generic bean: class [org.example.ImportedXmlBean]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null; defined in class path resource [otherApplicationContext.xml]] 
290 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.s[email protected]6aba4211: defining beans [bean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,aliasedBean,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy 
290 INFO org.example.AliasedBean - Construction of AliasedBean. 
302 INFO org.example.Main - Application context loaded. 
302 INFO org.springframework.context.support.ClassPathXmlApplicationContext - Closing org[email protected]3934f69a: startup date [Wed Mar 06 23:04:35 CET 2013]; root of context hierarchy 
302 INFO org.springframework.beans.factory.support.DefaultListableBeanFactory - Destroying singletons in org.s[email protected]6aba4211: defining beans [bean,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,aliasedBean,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor]; root of factory hierarchy 

Nach einigen Tests, fand ich heraus, dass ich eine Ausnahme während Kontext Schöpfung, wenn:

  • Ich habe zwei @Component("bean")oder
  • Ich habe zwei <bean id="bean"/> Elemente in die gleiche XML-Datei.
+0

Wenn Sie eine testspezifische Konfiguration verwenden, welche anderen Beans gibt es zum Überschreiben? –

+0

Die auf Anmerkung basierenden konfigurierten Beans. Meine Testkonfigurationsdatei enthält ein , da die meisten Beans die echten sind. Nur wenige müssen überschrieben werden. –

+0

Zeigt das Startprotokoll etwas? Denn wie du schon sagtest, kann der Frühling nur eine Bohne für jede ID haben. Es hängt davon ab, was es zuerst lädt, annotierte Klassen oder XML. –

Antwort

27
  • Bohnen werden in der Reihenfolge registriert, die in XML-Definitionsdatei zu finden sind.

  • Gescannte Bohnen werden an der Stelle registriert, an der das xml-Tag gefunden wurde, aber gescannte Beans können zuvor registrierte Bean-Definitionen nicht überschreiben.

  • Xml-Beans-Definitionen können jede vorherige Bean-Definition überschreiben, wenn DefaultListableBeanFactory.allowBeanDefinitionOverriding wahr ist (Standardeinstellung).

So XML gewinnt.

Wenn Sie das component-scan-Tag zuerst setzen, überschreibt xml bohnen die gescannten. Wenn Sie es zuletzt eingeben, werden gescannte Beans ignoriert.

bearbeiten

Aliases haben diferent Verhalten, wenn in Namensattribut in einer Bean Definition deklariert oder erklärt den Alias-Tag.

  • Aliase mit dem Alias-Tag versteckt sich ein später Bean Definition mit dem gleichen Namen erklärt.
  • Aliase in Namen deklarierte Attribut andere Bean Definition verhindert die gleichen Namen zu verwenden, indem ein BeanDefinitionParsingException werfen.

Zum Beispiel:

<bean id="foo" name="bar" class="Foo" /> 
<bean id="bar" class="Bar" /> -- throw Exception (name bar is in use) 

aber

<bean id="foo" class="Foo" /> 
<alias name="foo" alias="bar" /> 
<bean id="bar" class="Bar" /> -- Hidden by alias no exception thrown 

Die diference ist, dass BeanDefinitionParserDelegate eine Liste mit Namen und Aliase im Einsatz bei der gleichen Bohne Ebene Bohnen Element Verschachtelung halten und prüfen, ob Namenseindeutigkeit beim Analysieren von Bean-Definitionen.

Der Alias-Tag wird durch DefaultBeanDefinitionDocumentReader.processAliasRegistration() und der Parser Delegat ist nicht bewusst diese Namen direkt verarbeitet.

Ich weiß nicht, ob es ein Fehler oder vorsätzlich ist, aber reference sagt nichts über und scheint zu erwarten, dass die internen und externen Deklarationen von Aliasen das gleiche Verhalten haben.

+0

Tatsächlich habe ich festgestellt, dass eine '' jede spätere Bean-Definition überschreibt. Aber Sie haben Recht, dass eine gescannte Bean keine XML überschreiben kann, egal wo ich das component-scan Element platziert habe. –

+0

Ja, ich habe es getestet. Ein Alias ​​macht eine Bean-Definition mit demselben Namen unzugänglich. Die Bohne-Definition kann noch durch factoryBean.getBeanDefinition(), aber die Fabrik zurückgeholt werden wird es nicht instanziiert und die Bohne wird kein Kandidat für die autowiring nach Typ oder nach factory.getBean (Typ) –

+1

abgerufen werden @JoseLuisMartin ich, dass XML gewinnt verstehen, aber Was passiert, wenn der AnnotationConfigApplicationContext zwei Beans mit demselben Namen scannt? Wie entscheidet es dann, welche Bean-Definition Priorität hat? – Edge

Verwandte Themen