一、问题描述

在 Spring Boot 项目中引入 dynamic-datasource-spring-boot-starter 多数据源依赖后,本地 IDEA 运行正常,但打包部署后却抛出以下错误:

java.lang.NoClassDefFoundError: io/seata/rm/datasource/SeataDataSourceProxy
2024-12-25 17:13:14.037 ERROR 38788 --- [           main] o.s.boot.SpringApplication               : Application run failed

java.lang.NoClassDefFoundError: io/seata/rm/datasource/SeataDataSourceProxy
        at java.lang.Class.getDeclaredConstructors0(Native Method) ~[na:1.8.0_181]
        at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671) ~[na:1.8.0_181]
        at java.lang.Class.getDeclaredConstructors(Class.java:2020) ~[na:1.8.0_181]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBindConstructorProvider.findConstructorBindingAnnotatedConstructor(ConfigurationPropertiesBindConstructorProvider.java:62) ~[spring-boot-2.3.0.RELEASE.jar!/:2.3.0.RELEASE]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBindConstructorProvider.getBindConstructor(ConfigurationPropertiesBindConstructorProvider.java:48) ~[spring-boot-2.3.0.RELEASE.jar!/:2.3.0.RELEASE]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBean$BindMethod.forType(ConfigurationPropertiesBean.java:311) ~[spring-boot-2.3.0.RELEASE.jar!/:2.3.0.RELEASE]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator.validate(ConfigurationPropertiesBeanDefinitionValidator.java:63) ~[spring-boot-2.3.0.RELEASE.jar!/:2.3.0.RELEASE]
        at org.springframework.boot.context.properties.ConfigurationPropertiesBeanDefinitionValidator.postProcessBeanFactory(ConfigurationPropertiesBeanDefinitionValidator.java:45) ~[spring-boot-2.3.0.RELEASE.jar!/:2.3.0.RELEASE]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:291) ~[spring-context-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
        at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:175) ~[spring-context-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
        at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:706) ~[spring-context-5.2.6.RELEASE.jar!/:5.2.6.RELEASE]
        at 

错误发生在应用启动阶段,具体堆栈信息显示与 DynamicDataSourceCreatorAutoConfiguration 类相关,表明程序在运行时无法找到 Seata 的数据源代理类。

二、问题根源分析

通过查阅 dynamic-datasource 开源项目的 GitHub Issues(#328) dynamic-datasource/issues/328 发现,3.3.0 版本存在强依赖 Seata 的问题

  • dynamic-datasource-spring-boot-starter 3.3.0 在代码中直接引用了 Seata 的 SeataDataSourceProxy 类
  • 本地开发时因依赖传递可能包含 Seata,但打包时未正确包含相关类
  • 该版本的 DefaultDataSourceCreator 类强制依赖 Seata,导致未使用 Seata 的项目也受影响

 

三、解决方案

核心修复方案:升级 dynamic-datasource 依赖版本
将项目中的依赖从 3.3.0 升级至 3.3.1 及以上版本:

<!-- 原依赖(存在问题) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>

<!-- 升级后的依赖(修复了 Seata 强依赖问题) -->
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>dynamic-datasource-spring-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>
四、补充说明:NoClassDefFoundError 与 ClassNotFoundException 的区别
  • NoClassDefFoundError:运行时无法找到编译时存在的类,通常由依赖冲突、版本不兼容或打包遗漏导致
  • ClassNotFoundException:编译时即无法找到类,一般是依赖未正确引入

此案例中,本地运行正常但打包后报错,说明:

  1. 本地开发环境可能通过其他依赖间接引入了 Seata
  2. 打包工具(如 Maven)未正确处理 transitive dependency(传递依赖)
  3. 3.3.0 版本设计上对 Seata 的强依赖不符合「按需引入」原则
五、拓展建议:多数据源与分布式事务的整合

若项目确实需要使用 Seata 实现分布式事务,建议在升级 dynamic-datasource 后,额外引入 Seata 依赖:

<!-- Seata 核心依赖 -->
<dependency>
    <groupId>io.seata</groupId>
    <artifactId>seata-spring-boot-starter</artifactId>
    <version>1.7.0</version> <!-- 根据项目需求调整版本 -->
</dependency>

同时,需在 application.yml 中配置 Seata 客户端:

seata:
  enabled: true
  application-id: your-application-name
  tx-service-group: your-tx-group
  client:
    rm:
      datasource-proxy-mode: AT  # 使用 AT 模式代理数据源
六、小提示
  • 定期检查依赖版本:保持依赖库的更新,避免已知问题。

  • 阅读官方文档和发布说明:了解依赖库的变更和已知问题。

  • 使用版本控制:在升级依赖前,确保代码在版本控制系统中有备份。

七、总结
  1. dynamic-datasource 3.3.0 版本存在设计缺陷,强依赖 Seata 导致非 Seata 项目打包报错
  2. 升级至 3.3.1+ 版本是最直接的解决方案,该版本已修复依赖强制引入问题
  3. 遇到类找不到的错误时,可通过以下步骤排查:
  • 检查 Maven 依赖树(mvn dependency:tree
  • 查看打包后的 jar 包中是否包含目标类(jar -tf your-project.jar | grep SeataDataSourceProxy
  • 确认依赖版本是否与开源项目的 Issues 或 Release Notes 匹配

如果升级后仍有问题,可进一步检查项目的类加载顺序或联系 dynamic-datasource 社区获取支持。

参考资料

Logo

北京人形旗下天工造物具身智能开源社区,聚焦具身天工与慧思开物两大平台

更多推荐