27

在 Spring IOC 中有两个有效的 bean 定义(具有相同的名称和类)吗?

我有两个包含在 web.xml 中的 bean 定义文件。请参阅下面的示例。

applicationContext-beans1.xml

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

applicationContext-beans2.xml

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

到目前为止,我没有遇到任何问题。但是,这可能会影响多线程和集群的真实环境吗?

注意:两个 XML 都已加载,因为我能够使用两个 XML 中定义的其他 bean(仅一次)

4

4 回答 4

48

这是有效的,但您会发现一个 bean 被另一个覆盖。您将在日志中看到这一点

Overriding bean definition for...

此行为允许您覆盖以前提供的 bean 定义。它会影响您的应用程序的静态程序集,并且与您的问题中建议的线程/集群无关。

请注意,DefaultListableBeanFactory允许您通过setAllowBeanDefinitionOverriding()配置此行为

于 2012-06-12T08:49:11.280 回答
13

从 Spring Boot 2.1 版开始,它默认被禁用。(链接

Bean Overriding:默认情况下禁用 Bean 覆盖以防止 bean 被意外覆盖。如果您依赖于覆盖,则需要设置 spring.main.allow-bean-definition-overridingtrue.

于 2020-02-15T07:56:01.693 回答
10

这是有效且有用的,尤其是当您尝试更改第三方 bean 的实现(我的意思是,您不允许更改 bean 的实现)以及您需要提供/配置一些额外(合并)属性的地方时豆子。

bean 的覆盖取决于您提供的用于构建ApplicationContext通过 web.xml 或独立的 xml 的顺序。最新的 bean 定义将赢得比赛。

于 2012-06-12T13:17:35.993 回答
2

我知道现在回复很晚了,但是还是想补充一点……

只要您在两个不同的 spring 配置文件上定义具有相同 bean 的相同 id 的两个 bean 定义,它就有效。而且您正在将一个配置文件导入另一个配置文件(一种合并),无论您如何导入(一种合并)。后一个或最后一个 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 的两个 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)
于 2019-03-27T04:54:05.797 回答