IS是Spring.main.Allow-Bean-Definition-Overriding = true是不良练习



我正在构建春季启动REST API服务器,以更强大的框架将旧应用程序移植。那是我使用这些技术的第一个项目。到目前为止,我已经使用2个API建立了一个概念证明,该示范回答" Hello World!"在Json。一个是开放的,另一个是用oauth2固定的。我已经完成了要求的安全性。

我还使用了用于集成测试的休息和Spring MockMVC的组合建立了强大的测试结构,以进行单位测试,因此我有信心使用TDD方法开始实现Real API。

我们正在使用Maven。我的问题是,一旦我对现有工件有依赖性,我就会得到以下堆栈。我明白这意味着什么,但是我们的代码库很大,我找不到它来自哪里。当我向Google询问此问题时,我经常发现结果只是建议将spring.main.allow-bean-definition-overriding=true添加到我的属性中。这不是只在地毯下扫除问题吗?我猜想默认情况下春季不允许这样做有很好的理由。简单地使用便利的应用程序属性忽略该错误的可能后果是什么?

堆栈:

*************************** APPLICATION FAILED TO START
***************************
Description:
The bean 'org.springframework.transaction.config.internalTransactionAdvisor', defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class], could not be registered. A bean with that name has already been defined in null and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
[WARNING]  java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558)
    at java.lang.Thread.run (Thread.java:748) Caused by: org.springframework.beans.factory.support.BeanDefinitionOverrideException: Invalid bean definition with name 'org.springframework.transaction.config.internalTransactionAdvisor' defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]: Cannot register bean definition [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration; factoryMethodName=transactionAdvisor; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/transaction/annotation/ProxyTransactionManagementConfiguration.class]] for bean 'org.springframework.transaction.config.internalTransactionAdvisor': There is already [Root bean: class [org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor]; scope=; abstract=false; lazyInit=false; autowireMode=0; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null] bound.
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.registerBeanDefinition (DefaultListableBeanFactory.java:897)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod (ConfigurationClassBeanDefinitionReader.java:274)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass (ConfigurationClassBeanDefinitionReader.java:141)
    at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions (ConfigurationClassBeanDefinitionReader.java:117)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions (ConfigurationClassPostProcessor.java:327)
    at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry (ConfigurationClassPostProcessor.java:232)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors (PostProcessorRegistrationDelegate.java:275)
    at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors (PostProcessorRegistrationDelegate.java:95)
    at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors (AbstractApplicationContext.java:705)
    at org.springframework.context.support.AbstractApplicationContext.refresh (AbstractApplicationContext.java:531)
    at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh (ServletWebServerApplicationContext.java:142)
    at org.springframework.boot.SpringApplication.refresh (SpringApplication.java:775)
    at org.springframework.boot.SpringApplication.refreshContext (SpringApplication.java:397)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:316)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1260)
    at org.springframework.boot.SpringApplication.run (SpringApplication.java:1248)
    at ca.mycompany.oav.ResourceServerApplication.main (ResourceServerApplication.java:22)
    at sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke (Method.java:498)
    at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run (AbstractRunMojo.java:558)
    at java.lang.Thread.run (Thread.java:748)

只是要意识到:通过添加此内容,很难猜测哪个bean具有优先级,因为bean创建顺序是由依赖关系关系确定的,主要在运行时影响。<<<<<<<<<<<</strong>因此,允许豆类覆盖可以产生意外的行为,除非我们足够了解豆的依赖性层次结构。

参考

spring.main.allow-bean-definition-overriding=true涉及使用相同的bean名称作为现有bean的beans 。如果bean在您自己的代码中,您始终可以更改bean名称(如果使用 @Bean,则默认情况为the方法名称或@Component的类名称;但是有不同的方法来设置bean名称,请检查文档(。

因此,设置此标志的唯一合理(据我所知(的原因是,如果您不控制的多个bean(即从第三方代码(加载了相同的名称。

答案是

否不要使用尽可能多的覆盖范围。但有时可能是(但要谨慎(

更好地理解这一点,

启动应用程序时,Spring Boot自动加载了许多Bean(提供现成的功能(,可能需要一些bean。我们有两个选项

选项#1:

  1. 让Spring Boot加载功能
  2. 您稍后覆盖

选项#2:

  1. 问春季靴子不加载不需要的东西。
  2. 只需添加您自己的豆子

示例用例

Spring Boot带有ConfigServicePropertySourcelocator的框云配置。在实时场景中,我们将使用自己的安全配置服务器而不是默认的配置服务器。

选项#1:

  1. 让Spring Boot Load Load ConfigservicePropertySourcelocator bean
  2. 通过指定spring.main.allow-bean-definition-overriding=true
  3. 启用覆盖
  4. 定义您的自定义bean,但请确保添加@Order,@primary等。

选项#2:

  1. 问春季启动不加载configservicePropertysourcelocator,通过添加spring.cloud.config.enabled=false
  2. 只是定义您的自定义bean。

您节省了启动时间也看起来很干净。

参考:https://github.com/spring-cloud/spring-cloud-config/issues/177

最新更新