Spring Boot 2.1 中的 DataSource bean 覆盖

Posted

技术标签:

【中文标题】Spring Boot 2.1 中的 DataSource bean 覆盖【英文标题】:DataSource bean overriding in spring boot 2.1 【发布时间】:2019-04-05 21:06:03 【问题描述】:

我已经升级到 spring boot 2.1 版本,启动应用程序时出现奇怪的异常。

无法注册在类路径资源 [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class] 中定义的 BeanDefinition 中定义的 bean 'dataSource'。已在类路径资源 [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class] 中定义了具有该名称的 bean,并且已禁用覆盖。

完整的错误信息是:

[osbwscAnnotationConfigServletWebServerApplicationContext] 上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.support.BeanDefinitionOverrideException:在类路径资源 [org/springframework/ boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]:无法注册bean定义[根bean:类[org.springframework.aop.scope.ScopedProxyFactoryBean];范围=;摘要=假;懒惰初始化=假;自动线模式=0;依赖检查=0;自动接线候选=真;主要=假;工厂BeanName=空;工厂方法名=空;初始化方法名=空;销毁方法名=空;在类路径资源 [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]] 中定义的 BeanDefinition 中定义 bean 'dataSource':已经存在 [Root bean: class [null];范围=刷新;摘要=假;懒惰初始化=假;自动线模式=3;依赖检查=0;自动接线候选=假;主要=假; factoryBeanName=org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari;工厂方法名=数据源;初始化方法名=空; destroyMethodName=(推断);在类路径资源 [org/springframework/boot/autoconfigure/jdbc/DataSourceConfiguration$Hikari.class]] 中定义。

根据我们的政策,Beans 不能被覆盖,它被禁用:

spring.main.allow-bean-definition-overriding=false

我的应用程序代码中没有任何数据源配置。触发此错误的唯一选项是@EnableAutoConfiguration,在我的应用程序属性中,我已将数据源类型设置为:

spring.datasource.type=com.zaxxer.hikari.HikariDataSource

启动应用程序被初始化为

@SpringBootApplication
@EnableAutoConfiguration
public class MyApplication extends SpringBootServletInitializer 

    public static void main(String[] args) 
        new MyApplication()
            .configure(new SpringApplicationBuilder(MyApplication.class))
            .run(args);
    

还有一个配置类可以导入其他各种配置:

@Configuration
@ImportResource(locations = 
    "classpath*:conf/spring/*.xml",
    "classpath*:conf/spring/core/*.xml",
    "classpath*:conf/spring/plugin/**/*.xml"
)
@EnableAsync
@EnableRetry
@EnableCaching
@EnableBatchProcessing
@EnableCircuitBreaker
public class AppConfig 
    ...

有谁知道可能导致该问题的原因以及在哪里搜索?

在 Spring Boot 2.1(即 2.0.5)之前没有发生。

【问题讨论】:

你不需要设置数据源类型(hikari是默认的)和spring.main.allow-bean-definition-overriding=false是默认的。您能否添加完整的堆栈跟踪并添加您的 @SpringBootApplication 注释类? @M.Deinum 我已经更新了包含完整错误详细信息和应用程序配置类的问题。 删除 @EnableAutoConfiguration 已经被 @SpringBootApplication 隐含的。您的设置也有点奇怪,为什么要扩展 SpringBootServletInitializer 而不实施正确的方法?而且您在主要方法中所做的也不是标准的,只需使用SpringApplication.run(MyuApplication.class, args); 而不是您现在拥有的。 @M.Deinum 应用所有这些更改后仍然是相同的错误。 由于某种原因,DataSource 自动配置似乎被处理了两次。正如@M.Deinum 建议的那样,这可能是由于组件扫描范围太广。如果不查看应用程序的所有相关部分,就无法确定。你能提供一个minimal, complete, and verifiable example吗? 【参考方案1】:

我遇到了同样的问题,我正在寻找更好、更通用的解决方案,结果如下:

1-查看这里查看哪些版本的spring cloud与你的启动版本兼容 spring cloud

2- 之后,去这里选择你喜欢的确切版本spring cloud releases

这些步骤为我解决了问题,无需任何其他配置步骤。但是,对您来说,它可能是另一个不兼容的依赖项。不一定非要春云。

【讨论】:

【参考方案2】:

当我尝试在我的项目中配置 Redis 时遇到了这个问题,最后我使用以下方法解决了它:

@SpringBootApplication(exclude =  DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class)

我使用的是 SpringBoot 2.4.2

【讨论】:

【参考方案3】:

我遇到了类似的问题,它非常通用(有时有重复的注解,有时是重复的 bean)。如果您复制了 @EnableJpaRepository 之类的注释,则错误消息根本不会提及此注释。找出问题所在的最佳方法:

打开类 DefaultListableBeanFactory 应该有这样的代码:

BeanDefinition existingDefinition = (BeanDefinition)this.beanDefinitionMap.get(beanName);
        if (existingDefinition != null) 
            if (!this.isAllowBeanDefinitionOverriding()) 
                throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
            

在 throw new 中放置一个断点。然后 existingDefinition.source.className 指向已经注册的配置,这就是问题所在。当您检查 beanDefinition.source.className 时,您将比较两个类并找到重复代码或注释的位置,只需删除/修复它们。

【讨论】:

【参考方案4】:

在 application.properties 中添加以下属性可以解决问题。

spring.main.allow-bean-definition-overriding=true

另外一个人可能需要添加另一个属性来解决提到的另一个问题: https://github.com/openzipkin/zipkin/issues/2043

ma​​nagement.metrics.web.server.auto-time-requests=false

【讨论】:

【参考方案5】:

对于 Spring Boot 2+,您可以排除自动配置

@SpringBootApplication(exclude = ElasticsearchDataAutoConfiguration.class)
     public class YourApplication 
 ... 

【讨论】:

【参考方案6】:

org.springframework.cloud:spring-cloud-context:2.0.2.RELEASE

RefreshAutoConfiguration 在刷新 HikariDatasource 时会导致此问题

一个可能的解决办法是

spring.cloud.refresh.enabled = false

【讨论】:

【参考方案7】:

我今天遇到了类似的问题,以下 spring 云配置问题帮助了我:Issue 1142。

我们使用的 Spring Cloud Config 目前与 Spring Boot 2.1.0 不兼容。 Spring Cloud 的 Greenwich release train 将与 Spring Boot 2.1.0 兼容。

您的 @EnableCircuitBreaker 注释让我相信您可能还在使用与 Spring Boot 2.1.0 版本不兼容的 Spring Cloud 版本。

【讨论】:

就我而言,我的项目中有两次@EnableGlobalMethodSecurity。但它类似于***.com/questions/54059222/…

以上是关于Spring Boot 2.1 中的 DataSource bean 覆盖的主要内容,如果未能解决你的问题,请参考以下文章

spring boot 定时备份数据库

Spring Boot 2.1 中的 DataSource bean 覆盖

spring boot jpa 多数据源配置

Spring Boot 2.1 和 Java 11 中的 Bean 生命周期

多模块 Gradle 项目 - 从 Spring-Boot 1.5 迁移到 2.1

使用 Spring-Boot 2.1 从 .yml 读取对象列表 [重复]