Spring Boot Gradle 多项目构建在测试期间看不到内部依赖项

Posted

技术标签:

【中文标题】Spring Boot Gradle 多项目构建在测试期间看不到内部依赖项【英文标题】:Spring Boot Gradle multi-project build not seeing internal dependencies during tests 【发布时间】:2020-03-09 08:31:56 【问题描述】:

我在从 Gradle 4 迁移到 5 的大型多项目构建中遇到问题,并在更小、更简洁的构建上复制了该问题以演示该问题。

我在构建中有 2 个项目。一个是另一个使用的依赖项(基础库)。

demo (root project)
|- build.gradle
|
|--- demo-web
|---|- build.gradle
|
|--- demo-dependency
|---|- build.gradle

demo-web 片段:build.gradle

...
dependencies 
    implementation project(':demo-dependency')
    ...

...

依赖项目定义了一个在 web 项目中使用的类,DownstreamThing

Web 项目尝试使用它来构建自己的对象,但在根项目级别的构建过程中,它失败了。

> ./gradlew build
> Task :demo-web:test

com.example.demo.ThingTest > testThing FAILED
    java.lang.NoClassDefFoundError at ThingTest.java:12
        Caused by: java.lang.ClassNotFoundException at ThingTest.java:12

ThingTest.java

    @Test
    public void testThing() 
        DownstreamThing t =  new DownstreamThing(); //line 12, ClassNotFoundException
        assertTrue(t != null);
    

我在 Gradle 4 中没有遇到任何问题,但只有在 Gradle 5 中。为什么在测试任务期间找不到依赖项?

示例的完整来源在这里:https://bitbucket.org/travelsized/gradle-problem/src/master/

【问题讨论】:

【参考方案1】:

我相信他之所以会出现该异常是因为您已将 Spring Boot 插件应用于demo-dependency 项目。这个插件的作用是将jar文件重新打包成一个fat jar,需要一个特殊的类加载器来加载内容。

你仍然可以在没有插件的依赖项目中使用 Spring Boot 依赖项(例如启动器)。因此,如果可以,请将其删除。

如果有特定原因,您需要保留原始 jar 文件,以便将其用作实际依赖项。对于 Spring Boot 1.5.x,您可以这样做:

bootRepackage 
    classifier = "boot"


bootJar 
    enabled = true

但请注意,我不认为 Spring Boot 1.5 与 Gradle 5 及更高版本完全兼容(目前我们使用的是 6.0),因此您可能需要降级 Gradle 或升级 Spring Boot。

【讨论】:

不错的方向,在 Kotlin 中,当我从根 build.gradle 中删除 apply(plugin = "org.springframework.boot") 并申请每个子模块时,它对我有用,除了 common 模块【参考方案2】:

Bjørn Vester 的回答让我指出了正确的方向。 spring-boot 插件导致 jar 任务出错。我需要确保在启用 jar 任务时为依赖项禁用了 bootJar 任务。

在 Gradle 和 Spring Boot 插件版本之间执行此操作的配置更改导致升级丢失。

以前,我可以在启动后为 jar 指定一个分类器:

bootRepackage  
    classifier = 'exec'

现在,我需要启用和禁用相应的任务:

bootJar 
    enabled = false


jar 
    enabled = true
    archiveBaseName = "demo-dependency"

在较大的项目中,我之前有一个 jar 任务指定了 archiveBaseName,但没有明确启用它来覆盖 bootJar 任务。一旦我进行了上述更改(同时保留启动插件),一切就开始工作了。

【讨论】:

以上是关于Spring Boot Gradle 多项目构建在测试期间看不到内部依赖项的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot gradle 多模块项目未解决的引用错误

使用 Spring Boot 时使用 JaCoCo 代码覆盖率构建 Gradle 多项目失败

Spring boot 和 Gradle 多模块项目,无法正确加载依赖项

Spring-boot 和 Gradle:构建时间太长 - 如何调试?

多模块 Spring Boot 项目中的 Gradle 依赖插件

使用gradle BOM和spring-boot(多模块应用程序)哪种方式更好