使用相同的名称两次定义同一个 Spring bean

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10993181/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:09:55  来源:igfitidea点击:

Defining the same Spring bean twice with same name

springinversion-of-controljavabeans

提问by hop

Is having two definition for a bean (with same name and class) valid in Spring IOC ?

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

I am having two bean definition files included in web.xml. See the sample below.

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

applicationContext-beans1.xml

applicationContext-beans1.xml

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

applicationContext-beans2.xml

applicationContext-beans2.xml

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

I am not facing any issue till now. But, will this possibly impact in the real environment which will be multi threaded and clustered ?

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

Note:Both the XMLs are loaded as I am able to use the other beans defined(only once) in both the XMLs

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

回答by Brian Agnew

It's valid, but you'll find that one bean is overridden by the other. You'll see this in the logs as

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

Overriding bean definition for...

This behaviour allows you to override previously supplied bean definitions. It affects the static assembly of your app, and doesn't relate to threading/clustering as suggested in your question.

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

Note that the DefaultListableBeanFactoryallows you to configure this behaviour via setAllowBeanDefinitionOverriding()

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

回答by RP-

This is valid and useful especially when you try to change the implementation of a third party bean (I mean, where you are not allowed to change the implementation of a bean) and Where you need to provide/configure some extra (merge) properties for the bean.

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

The overriding of the bean depends upon the order of the xmls you provide to build the ApplicationContextthrough web.xml or stand-alone. The latest bean definition will win the game.

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

回答by ParagFlume

I know it is very very late to reply, But sill want to add something...

我知道现在回复已经很晚了,但还是想补充一些...

It valid as long as you are defining two bean definitions with same id of same bean on two different spring configuration files. And you are importing one configuration file into another (kind of merging), does not matter how you importing (kind of merging). The later one or the last one bean definition will be override by the first one(s).

只要您在两个不同的 spring 配置文件上定义具有相同 bean 的相同 id 的两个 bean 定义,它就有效。并且您将一个配置文件导入到另一个配置文件(一种合并),与您如何导入(某种合并)无关。后一个或最后一个 bean 定义将被第一个 (s) 覆盖。

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

e.g # 1

例如#1

spring-config1.xml

spring-config1.xml

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

spring-config2.xml

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>

e.g # 2

例如#2

spring-config1.xml

spring-config1.xml

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

spring-config1.xml

spring-config1.xml

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

web.xml

网页.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>

But if you are defining the two bean definitions with same bean id of same bean in same file you will find spring application start up failed. Spring would not let you define multiple bean definitions of same bean with same name in the same spring configuration file.

但是,如果您在同一个文件中使用相同 bean 的相同 bean id 定义两个 bean 定义,您会发现 spring 应用程序启动失败。Spring 不会让你在同一个 spring 配置文件中定义多个同名 bean 的定义。

e.g # 3 spring-config3.xml

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

错误 :

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)

回答by H.?.T

From Spring Boot version 2.1 it is disabled by default. (link)

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

Bean Overriding:Bean overriding has been disabled by default to prevent a bean being accidentally overridden. If you are relying on overriding, you will need to set spring.main.allow-bean-definition-overridingto true.

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