【问题标题】:Failing to understand Gradle's default dependency resolution strategy无法理解 Gradle 的默认依赖解析策略
【发布时间】:2020-12-03 19:07:58
【问题描述】:

我已经构建了一个 Java 库并将其上传到一个私人 Artifactory 空间。假设该库的 Gradle 标识符为 com.mycompany:MyLibrary:1.0.0,已上传到 https://artifactory.mycompany.com/artifactory/libs-release,并且在 JCenter 中不存在。这个库依赖于另一个库,该库没有上传到https://artifactory.mycompany.com/artifactory/libs-release,但可以从 JCenter 公开获得。假设第二个库的 Gradle 标识符为 com.google.code.findbugs:jsr305:3.0.0

作为 Java 应用程序中 Java 库的使用者,我的依赖项列表如下:

dependencies {
    implementation 'com.mycompany:MyLibrary:1.0.0'
}

值得注意的是,我不需要显式声明 com.google.code.findbugs:jsr305:3.0.0 依赖项,因为它将被传递解析。

另外,为了安全起见,我想在JCenter上面订购我的私有Artifactory仓库,如下:

repositories {
    maven {
        url 'https://artifactory.mycompany.com/artifactory/libs-release'
    }
    jcenter()
}

但是,当我尝试构建我的 Java 应用程序时,我遇到了以下错误:

Execution failed for task ':bootJar'.
> Could not resolve all files for configuration ':runtimeClasspath'.
   > Could not find jsr305-3.0.0.jar (com.google.code.findbugs:jsr305:3.0.0).
     Searched in the following locations:
         https://artifactory.mycompany.com/artifactory/libs-release/com/google/code/findbugs/jsr305/3.0.0/jsr305-3.0.0.jar

从这个错误看来,jsr305-3.0.0 工件仅在我的私有 Artifactory 存储库中搜索,而不在 JCenter 中搜索。如果在我的私有 Artifactory 存储库中找不到 jsr305-3.0.0 工件,我本来希望 Gradle 会在 JCenter 中搜索它。

如果我重新排序存储库以便首先声明 JCenter,如下所示...

repositories {
    jcenter()
    maven {
        url 'https://artifactory.mycompany.com/artifactory/libs-release'
    }
}

...然后构建成功完成。

Gradle 解决依赖关系的方式是我所遇到的预期行为,还是这是一个错误?如果这是预期的行为,我可以做些什么来更改依赖解析策略,以便我可以在 JCenter 上方声明我的私有 Artifactory 存储库?

【问题讨论】:

    标签: gradle artifactory


    【解决方案1】:

    JCenter 中的元数据优于您自定义的私有 Artifactory 空间中的元数据。

    Gradle 检查所有存储库以找到最佳元数据并使用它。

    查看 Gradle 文档中 Declaring Repositories 页面中的以下引用。

    首先,来自Declaring Multiple Repositories 部分:

    声明的顺序决定了 Gradle 将如何检查 运行时的依赖。如果 Gradle 在 特定的存储库,它将尝试下载所有 来自同一存储库的该模块的工件。你可以了解更多 关于依赖下载的内部工作原理。

    其次,来自Supported Repository Types 部分:

    由于 Gradle 更喜欢使用已创建描述符的模块 来自真实的元数据而不是生成的平面目录 存储库不能用于用真实元数据覆盖工件 来自构建中声明的其他存储库。

    例如,如果 Gradle 在平面目录中仅找到 jmxri-1.2.1.jar 存储库,但 jmxri-1.2.1.pom 在另一个支持的存储库中 元数据,它将使用第二个存储库来提供模块。

    【讨论】:

    • 感谢您的回答。从您的回答和您提供的报价中,我无法理解为什么更改存储库的顺序对于确定依赖项解析是否成功很重要。如果你能提供更多关于这方面的信息,那就太好了。否则,我会花更多时间阅读您分享的链接并阅读“模块描述符”是什么。
    • 再次感谢您的回答以及您提供的报价和链接。它没有直接回答我的问题,但它很有用,帮助我找到了问题的答案。对于其他偶然发现此线程的人,我还发现官方Gradle YouTube channel 中的Dependency Management with Gradle 播放列表非常有用;特别是关于基础知识的第一个视频 (here)。
    【解决方案2】:

    因此,在过去的某个时候,我的私有 Artifactory 实例创建了 JCenter 的部分缓存。我不确定这个缓存是如何产生的,但它似乎包含了我的库所依赖的所有工件。此外,缓存只包括每个工件的 pom 和 sources jar,而不包括其二进制 jar,如下所示:

    那么当我的图书馆的消费者按以下方式订购他/她的存储库时会发生什么......

    repositories {
        maven {
            url 'https://artifactory.mycompany.com/artifactory/libs-release'
        }
        jcenter()
    }
    

    ... Gradle 正在 https://artifactory.mycompany.com/artifactory/libs-release 中找到 com.google.code.findbugs:jsr305:3.0.0 的 pom 文件,并且希望在那里也能找到二进制 jar。当它在那里找不到二进制 jar 时,它会导致构建失败。请特别注意,如果 Gradle 在它检查过的任何先前存储库中都没有找到它的 pom 文件,则只会继续在列表中的下一个存储库(本示例中为 JCenter)中搜索工件。

    我的解决方案是从我的私有 Artifactory 实例中删除 JCenter 缓存或使缓存完整,以便它包含它所拥有的每个工件的二进制 jar 文件。

    【讨论】:

      猜你喜欢
      • 2019-04-24
      • 2015-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      • 2018-03-06
      • 1970-01-01
      • 2015-03-03
      相关资源
      最近更新 更多