web-dev-qa-db-fra.com

Définir deux fois le même bean Spring avec le même nom

Le fait d'avoir deux définitions pour un bean (avec le même nom et la même classe) est-il valide dans Spring IOC?

J'ai deux fichiers de définition de bean inclus dans web.xml. Voir l'exemple ci-dessous.

applicationContext-beans1.xml

<bean name="myWao"
    class="com.beans.myBean">       
</bean> 

applicationContext-beans2.xml

<bean name="myWao"
    class="com.beans.myBean">       
</bean> 

Je ne fais face à aucun problème jusqu'à présent. Mais cela aura-t-il un impact sur l'environnement réel qui sera multi-thread et clusterisé?

Note: Les deux XML sont chargés car je peux utiliser les autres beans définis (une seule fois) dans les deux XML

22
hop

C'est valide, mais vous constaterez qu'un bean est remplacé par l'autre. Vous verrez cela dans les journaux comme

Overriding bean definition for...

Ce comportement vous permet de remplacer les définitions de bean fournies précédemment. Il affecte l'assemblage statique de votre application et ne concerne pas le threading/clustering comme suggéré dans votre question.

Notez que le DefaultListableBeanFactory vous permet de configurer ce comportement via setAllowBeanDefinitionOverriding ()

42
Brian Agnew

Ceci est valide et utile, en particulier lorsque vous essayez de modifier l'implémentation d'un bean tiers (je veux dire, où vous n'êtes pas autorisé à modifier l'implémentation d'un bean) et lorsque vous devez fournir/configurer des propriétés supplémentaires (de fusion) pour le haricot.

Le remplacement du bean dépend de l'ordre des xml que vous fournissez pour construire le ApplicationContext via web.xml ou autonome. La dernière définition de bean gagnera la partie.

10
RP-

Je sais qu'il est très très tard pour répondre, mais je veux quand même ajouter quelque chose ...

Il est valable tant que vous définissez deux définitions de bean avec le même identifiant du même bean sur deux fichiers de configuration de ressort différents. Et vous importez un fichier de configuration dans un autre (type de fusion), peu importe la façon dont vous importez (type de fusion). La dernière ou la dernière définition de bean sera remplacée par la ou les premières.

package com.demo.bean;
public class TestBean {
    private String message;
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}

par exemple # 1

spring-config1.xml

<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="INSIDE_SPRING_CONFIG_1"></property>
</bean>

spring-config2.xml

<import resource="spring-config1.xml"/><
<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="INSIDE_SPRING_CONFIG_1"></property>
</bean>

par exemple # 2

spring-config1.xml

<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="INSIDE_SPRING_CONFIG_1"></property>
</bean>

spring-config1.xml

<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="INSIDE_SPRING_CONFIG_1"></property>
</bean>

web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/spring-config1.xml,
        /WEB-INF/spring-config2.xml
    </param-value>
</context-param>

Mais si vous définissez les deux définitions de bean avec le même identifiant de bean du même bean dans le même fichier, vous constaterez que le démarrage de l'application Spring a échoué. Spring ne vous permet pas de définir plusieurs définitions de bean du même bean avec le même nom dans le même fichier de configuration Spring.

par exemple # 3 spring-config3.xml

<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="CONFIG_VALUE_1"></property>
</bean>
<bean id="testbean" class="com.demo.TestBean">
    <property name="message"    value="CONFIG_VALUE_2"></property>
</bean>

Erreur :

ERROR ContextLoader:331 - Context initialization failed
org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Bean name 'testbean' is already used in this <bean> element
Offending resource:  resource [/spring-config3.xml]

    at org.springframework.beans.factory.parsing.FailFastProblemReporter.error(FailFastProblemReporter.Java:70)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.Java:85)
    at org.springframework.beans.factory.parsing.ReaderContext.error(ReaderContext.Java:80)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.error(BeanDefinitionParserDelegate.Java:316)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.checkNameUniqueness(BeanDefinitionParserDelegate.Java:525)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseBeanDefinitionElement(BeanDefinitionParserDelegate.Java:471)
    at org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseBeanDefinitionElement(BeanDefinitionParserDelegate.Java:443)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.processBeanDefinition(DefaultBeanDefinitionDocumentReader.Java:314)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(DefaultBeanDefinitionDocumentReader.Java:205)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseBeanDefinitions(DefaultBeanDefinitionDocumentReader.Java:184)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.doRegisterBeanDefinitions(DefaultBeanDefinitionDocumentReader.Java:141)
    at org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.registerBeanDefinitions(DefaultBeanDefinitionDocumentReader.Java:110)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.registerBeanDefinitions(XmlBeanDefinitionReader.Java:508)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.doLoadBeanDefinitions(XmlBeanDefinitionReader.Java:391)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.Java:335)
    at org.springframework.beans.factory.xml.XmlBeanDefinitionReader.loadBeanDefinitions(XmlBeanDefinitionReader.Java:303)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.Java:180)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.Java:216)
    at org.springframework.beans.factory.support.AbstractBeanDefinitionReader.loadBeanDefinitions(AbstractBeanDefinitionReader.Java:187)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.Java:125)
    at org.springframework.web.context.support.XmlWebApplicationContext.loadBeanDefinitions(XmlWebApplicationContext.Java:94)
    at org.springframework.context.support.AbstractRefreshableApplicationContext.refreshBeanFactory(AbstractRefreshableApplicationContext.Java:129)
    at org.springframework.context.support.AbstractApplicationContext.obtainFreshBeanFactory(AbstractApplicationContext.Java:540)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:454)
    at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.Java:403)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.Java:306)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.Java:106)
    at org.Apache.catalina.core.StandardContext.listenerStart(StandardContext.Java:4716)
    at org.Apache.catalina.core.StandardContext.startInternal(StandardContext.Java:5178)
    at org.Apache.catalina.util.LifecycleBase.start(LifecycleBase.Java:152)
    at org.Apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.Java:1403)
    at org.Apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.Java:1393)
    at Java.util.concurrent.FutureTask.run(FutureTask.Java:266)
    at Java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.Java:1142)
    at Java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.Java:617)
    at Java.lang.Thread.run(Thread.Java:745)
2
ParagFlume

Depuis Spring Boot version 2.1, il est désactivé par défaut. ( lien )

Remplacement du bean: Le remplacement du bean a été désactivé par défaut pour éviter qu'un bean soit accidentellement remplacé. Si vous comptez sur la substitution, vous devrez définir spring.main.allow-bean-definition-overriding à true.

0
H.Ç.T