从我们所见,用另一个 bean 定义覆盖一个 bean 定义(通过提供两个具有相同名称的定义)通常是意外发生的。完成后,信息日志消息几乎总是会丢失,导致难以诊断行为。我们应该默认禁用 bean 覆盖,并提供一个配置属性来将其重新打开,同时对异常进行故障分析,清楚地描述问题并建议将该属性设置为可能的操作。
[spring-projects/spring-boot]默认情况下禁用 bean 覆盖并提供配置属性来启用它
回答
目前,拒绝的覆盖尝试会导致BeanDefinitionStoreException
.如果抛出特定异常并提供对现有 bean 定义和重写 bean 定义的访问,这对于故障分析将非常有用。我已经打开https://jira.spring.io/browse/SPR-16982。
我们在 Spring Cloud 中类似地处理了一些与此相关的问题
这破坏了构建,修复它被 #13737 阻止。
Spring Data REST 中的问题已在其最新快照中得到修复。
@wilkinsona 嗨安迪,刚刚注意到这发生了变化。我们经常使用 Primary 注解来覆盖一些 bean 进行集成测试(我想这是一种正常的方法)。我花了几个小时才发现这个功能从 2.1.0 开始默认被禁用。 :(
听到这个消息我很遗憾。对默认值的更改是2.1 发行说明中描述的首要内容之一。它们总是值得在升级之前阅读,如果您在升级时遇到问题,也值得再次阅读。
很高兴知道您何时意外覆盖了 Bean,但如果能够将特定的 Bean 专门标记为故意覆盖其他 Bean,以便允许它们使用,那就太好了。
当我大量使用 spring 自动配置时,我经常发现有些 bean 需要定制,所以我得到了它的好处,它大部分是自动配置的,只有一些变化。在这些情况下,当我不小心“覆盖”一个 bean 时,它会出错,这是非常有用的,但是如果能够故意告诉框架这个特定的 bean 仍然是我想要覆盖的东西,那就太好了。这样,此功能可以捕获我将来犯的错误,同时让我保留之前所做的决定。
也许我正在提出功能请求或建议...也许是像 @OverridesExistingBean 这样的新注释或 @'Bean' 上具有相似名称的附加参数。
这个问题给我带来了问题,因为几个月前我将单个 bean 定义 XML 文件分解为多个文件。我收到错误是因为我多次重新定义同一个 bean。发生这种情况是因为多个 XML 文件包含相同的其他 XML 文件,以获取它从其他文件引用的 bean 的定义。我这样做是为了可以使用不同的 Bean 定义文件组合,并确保依赖的 Bean 定义始终可供参考。它在我的 IDE 中也很有帮助,因为它没有一个 XML 文件被包含在另一个文件中的上下文,因此它认为后一个文件缺少引用的 bean 的定义。我正在做的事情在 2.1 之前都运行良好。
我的解决方法是设置 spring.main.allow-bean-definition-overriding=true 。这解决了问题。但如果我真的用不同的 bean 覆盖了一个 bean,我希望得到警告。我打算看看是否可以重新组织我的 bean 文件以避免禁用检查并仍然获得我想要的功能,但这很痛苦。我只是想把这个特殊问题记录下来。我并不是说我正在做的事情是正确的做法。
我想知道如果有问题的覆盖 bean 与原始 bean 具有相同的源坐标,或者框架是否可以识别这种情况,是否可以例外......同一 bean 的重复定义。
如果您的 bean 定义有一个id
框架,则不应多次重新定义相同的 bean 定义,这应该会自动解决您的问题。如果这不能解决问题,请考虑使用一个小示例创建一个 Spring 框架问题,以重现您所描述的行为。
感谢斯蒂芬的回复。我将尝试用一个简单的例子来重现这一点。我希望我可以在这里提供更多信息,以便在我进入新问题之前可以提供一些线索:
我的 bean defs 都有 id。这是我击中的第一个:
<bean id="identity" class="com.filethis.common.bluegreen.InstanceIdentity">
<property name="name" value="${filethis.identity.name}"/>
<property name="service" value="${filethis.identity.service}"/>
<property name="cluster" value="${filethis.identity.cluster}"/>
<property name="baseDomain" value="${filethis.identity.baseDomain}"/>
<property name="address" value="${filethis.identity.address}"/>
</bean>
这是我得到的错误:
Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException:
Invalid bean definition with name 'identity'
defined in URL [file:/Users/steve/Development/inlet/inletfetch_if2/common/common-jutil/target/classes/beanDefinitionFiles/identity.xml]:
Cannot register bean definition [Generic bean: class [com.filethis.common.bluegreen.InstanceIdentity];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null;
defined in URL [file:/Users/steve/Development/inlet/inletfetch_if2/common/common-jutil/target/classes/beanDefinitionFiles/identity.xml]] for bean 'identity':
There is already [Generic bean: class [com.filethis.common.bluegreen.InstanceIdentity];
scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null;
defined in URL [file:/Users/steve/Development/inlet/inletfetch_if2/common/common-jutil/target/classes/beanDefinitionFiles/identity.xml]] bound.
@inletfetch 感谢您的反馈。在我看来,核心容器BeanDefinitionOverrideException
在这种情况下抛出 a 看起来很奇怪。您能创建一个Spring 框架问题吗?
会做