java - 调用gradle idea时如何将本地依赖放在第一位?

标签 java gradle intellij-idea jar classpath

当调用gradle idea时,外部依赖项在类路径中相对于本地 Jar 包含首先排序。因此:

dependencies {
    compile fileTree(dir: 'libs', include:['*.jar'])
    compile group: 'foo', name:'bar', version:'1.0.0'
}

最后将包括我本地的 jar 。这是我的项目中的一个问题,因为这些 jar 的目的是部分覆盖外部库。

使用 flatDir 将存储库指定为依赖项源并在不使用 fileTree 的情况下加载 jar 时,会观察到相同的行为。它被放在类路径的最后。

我在研究时发现了几个提到这个问题的地方,例如https://discuss.gradle.org/t/gradle-messes-up-the-classpath-order-in-generated-projects-when-there-are-mixed-dependency-types/13130 ,但没有解决方法。

我想这些是存在的,gradle 是非常可定制的,但我对它很陌生,我的尝试失败了。如何进行?

最佳答案

我没有定期使用 IntelliJ,但在这个问题的背景下尝试过它,我的印象是 gradle 的 idea 插件和 IntelliJ 的 gradle 插件不能很好地结合在一起。也就是说,您应该使用 idea gradle 插件并导入为普通 Java 项目,或者使用 IntelliJ 的 gradle 插件导入为 gradle 项目。主要原因是 idea 插件和 IntelliJ 插件生成的 IML 文件略有不同(这些文件包含项目依赖项等),这会在同时使用这两个插件时导致很多困惑。由于您特别要求使用 gradle idea 插件,我使用了该插件并将其作为纯 java 项目导入到 IntelliJ 中。

但是为了回答你的问题,我没有发现任何证据表明在使用 flatDir< 时,类路径上的库的顺序与 gradle 文件的 dependency 部分中声明的顺序不同。/ repo 协议(protocol)。当使用 compile fileTree(dir: 'libs', include:['*.jar']) 时,顺序实际上被破坏了,如您的问题中所述。也就是说,您应该坚持使用 flatDir 存储库。

我使用的是 gradle 4.9 和 IntelliJ 2018.2。

这是我的 gradle 文件

apply plugin: 'java'
apply plugin: 'idea'

repositories {
    jcenter()
    flatDir {
        dirs 'libs'
    }
}

dependencies {
    compile 'zzz:zzz-0.0.0'
    compile 'aaa:aaa-0.0.0'
    compile 'com.google.guava:guava:24.0-jre'
    compile group: 'javax.websocket', name: 'javax.websocket-api', version: '1.1'
}

task wrapper(type: Wrapper) {
    gradleVersion = '4.9'
    distributionUrl = "http://services.gradle.org/distributions/gradle-${gradleVersion}-bin.zip"
}

在我的libs文件夹中,有两个jar文件aaa-0.0.0.jarzzz-0.0.0.jar都是副本guava-24.0-jre.jar。也就是说,所有 Guava 类都存在于两个 jar 中。由于 zzz:zzz-0.0.0 是 gradle 文件中的第一个依赖项,因此预期 guava 类将从 zzz-0.0.0.jar 加载guava-24.0-jre.jaraaa-0.0.0.jar。我使用以下主类来测试这一点:

package test;

import com.google.common.math.LongMath;

public class Test {

    public static void main(String[] args) throws  Exception {
        System.out.println(LongMath.class.getProtectionDomain().getCodeSource().getLocation().toURI());
    }
}

从 IntelliJ 运行它时的输出是

文件:/C:/ws/gradle-idea-test/libs/zzz-0.0.0.jar

这就是 com.google.common.math.LongMath 类确实是从本地 libs/zzz-0.0.0.jar 加载的,而不是 guava-24.0-jre.jar

我注意到 IntelliJ 中的外部依赖项列表不显示本地库。更令人困惑的是,库按字母顺序排序,并没有反射(reflect)类路径上的实际顺序,这可能会非常令人困惑:

IntelliJ External Dependencies

要获取类路径上元素的实际顺序,您必须查看模块设置中的模块依赖项部分(“打开模块设置”>“项目”>“模块”>“依赖项选项卡”),如下所示这个:

IntelliJ Module Dependencies

正如您所看到的,依赖项以正确的顺序列出,并且还包括本地库。该对话框中的库顺序与生成的 iml 文件中的顺序基本相同。

当使用 IntelliJ gradle 插件而不是 gradle 的 idea 插件时,IntelliJ 的行为方式基本相同,但生成的 iml 文件看起来不同,并且外部库以不同的格式显示。但类路径顺序没有区别。

关于java - 调用gradle idea时如何将本地依赖放在第一位?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51671037/

相关文章:

java - 这是循环死锁还是循环等待?

java - 如何在 Java Berkeley DB 中存储 ArrayList 字段?

scala - 使用 shadowJar 和 Scala 依赖项时如何修复丢失的 conf 文件?

java - Intellij 格式化程序链式方法调用

java - IntelliJ 可以为 Java 类生成可链接的 setter /修改器吗?

java - 如何自动添加struts action后缀

java - 用于内部方法和私有(private)方法的 AOP Java

android - Crashlytics 不显示 native 崩溃

java - Hello World Ear : NoModuleFileException: A file does not exist for module element having uri: core-api. jar

android - Holo.Light 给出 "Resource not public"错误