web-dev-qa-db-ja.com

同じSpring Beanを同じ名前で2回定義する

Beanの2つの定義(同じ名前とクラス)がSpringで有効ですかIOC?

Web.xmlに2つのBean定義ファイルが含まれています。以下のサンプルを参照してください。

applicationContext-beans1.xml

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

applicationContext-beans2.xml

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

今まで問題はありません。しかし、これはマルチスレッド化されてクラスター化される実際の環境に影響を与える可能性がありますか?

注:両方のXMLで定義されている他のBeanを(一度だけ)使用できるため、両方のXMLがロードされます

22
hop

それは有効ですが、1つのBeanが他のBeanによってオーバーライドされることがわかります。これはログに次のように表示されます

Overriding bean definition for...

この動作により、以前に提供されたBean定義をオーバーライドできます。これはアプリの静的アセンブリに影響し、質問で提案されているスレッド化/クラスタリングには関係ありません。

DefaultListableBeanFactoryでは、この動作を setAllowBeanDefinitionOverriding() で設定できることに注意してください

42
Brian Agnew

これは、サードパーティBeanの実装を変更しようとする場合(つまり、Beanの実装を変更することが許可されていない場合)、および追加の(マージ)プロパティを提供/構成する必要がある場合に特に有効で便利です。豆。

Beanのオーバーライドは、web.xmlまたはスタンドアロンでApplicationContextを構築するために提供するxmlの順序に依存します。最新のBean定義がゲームに勝ちます。

10
RP-

返信が非常に遅いのはわかっていますが、何かを追加したいのですが...

2つの異なるSpring構成ファイルで同じBeanの同じIDを持つ2つのBean定義を定義している限り、これは有効です。そして、1つの構成ファイルを別の構成ファイルにインポートしています(マージの種類)。どのようにインポートするか(マージの種類)は関係ありません。後のBean定義または最後のBean定義は、最初の定義によってオーバーライドされます。

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

例:#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>

例#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>

ただし、同じファイル内で同じBeanの同じBean IDを持つ2つのBean定義を定義している場合、Springアプリケーションの起動が失敗することがわかります。 Springでは、同じSpring構成ファイルで同じ名前の同じBeanの複数のBean定義を定義できません。

例#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>

エラー:

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

Spring Bootバージョン2.1以降では、デフォルトで無効になっています。 ( リンク

Beanのオーバーライド:Beanのオーバーライドは、Beanが誤ってオーバーライドされるのを防ぐために、デフォルトで無効になっています。オーバーライドに依存している場合は、spring.main.allow-bean-definition-overridingtrueに設定する必要があります。

0
H.Ç.T