调用gradle idea时如何将本地依赖项放在首位?

时间:2018-08-03 10:52:41

标签: 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的目的是部分覆盖外部库。

使用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是非常可定制的,但是对于我来说,这是一个很新的尝试,使失败。如何进行?

1 个答案:

答案 0 :(得分:1)

我不是定期使用IntelliJ,而是在此问题的上下文中进行了尝试,我的印象是gradle的idea插件和IntelliJ的gradle插件不能很好地配合使用。那就是您应该使用idea gradle插件并将其导入为纯Java项目,或者使用IntelliJ的gradle插件将其导入为gradle项目。主要原因是idea插件和IntelliJ插件生成的iml文件略有不同(这些文件保存了项目依赖关系,其中包括其他内容),这在将两个插件一起使用时会引起很多混乱。当您特别要求gradle idea插件时,我使用了此插件并将其作为纯Java项目导入到IntelliJ中。

但是要回答您的问题,我发现没有证据表明在使用dependencies存储库时,类路径上的库顺序与gradle文件的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文件夹中,有两个jars aaa-0.0.0.jarzzz-0.0.0.jar都是guava-24.0-jre.jar的副本。那就是两个罐子中都存在所有番石榴类。由于zzz:zzz-0.0.0是gradle文件中的第一个依赖项,因此可以预期是从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中的外部依赖项列表没有显示本地库。更令人困惑的是,库是按字母顺序排列的,并且没有在类路径上反映出实际的顺序,这可能会造成很大的混乱:

IntelliJ External Dependencies

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

IntelliJ Module Dependencies

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

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