如何在调用gradleidea时将本地依赖放在首位?

How to put local dependencies first when calling gradle idea?

当调用 gradle idea 时,相对于本地 Jar 包含,外部依赖项在 class 路径中排在第一位。因此:

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

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

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

我在研究时发现了几个提到的问题,例如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 中。

但是为了回答您的问题,我没有发现 class 路径上库的顺序与 gradle 文件的 dependencies 部分中声明的顺序不同的证据,使用 flatDir 回购时。使用 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 classes 都存在于两个罐子中。由于 zzz:zzz-0.0.0 是 gradle 文件中的第一个依赖项,因此预期是从 zzz-0.0.0.jar 而不是 guava-24.0-jre.jaraaa-0.0.0.jar。我使用以下主要 class 来测试这个:

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 class 确实是从本地加载的 libs/zzz-0.0.0.jar 而不是 guava-24.0-jre.jar.

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

要获得 class 路径上元素的实际顺序,您必须查看模块设置中的模块依赖项部分 ("Open Module Settings" > "Project" > "Modules" > "Dependencies Tab") 看起来像这样:

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

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