Java gradle将可传递的运行时依赖项包括为编译依赖项
我正在体验gradle依赖项管理中的一个奇怪行为,其中项目a引用项目B作为编译依赖项,项目B引用库C作为运行时依赖项。现在我可以在我的项目A中使用库C中的类 我的问题:(为什么)这是一个bug还是一个功能? 使用gradle 2.9和2.10以及以下最小设置可以重现该问题:Java gradle将可传递的运行时依赖项包括为编译依赖项,java,gradle,dependency-management,Java,Gradle,Dependency Management,我正在体验gradle依赖项管理中的一个奇怪行为,其中项目a引用项目B作为编译依赖项,项目B引用库C作为运行时依赖项。现在我可以在我的项目A中使用库C中的类 我的问题:(为什么)这是一个bug还是一个功能? 使用gradle 2.9和2.10以及以下最小设置可以重现该问题: //settings.gradle 包括:A',':B' //build.gradle 所有项目{ 应用插件:“java” 应用插件:“maven” 存储库{ mavenLocal() mavenCentral() } }
//settings.gradle
包括:A',':B'
//build.gradle
所有项目{
应用插件:“java”
应用插件:“maven”
存储库{
mavenLocal()
mavenCentral()
}
}
项目(“:A”){
依赖关系{
编译项目(':B')
}
}
项目(':B'){
依赖关系{
运行时“org.slf4j:slf4j-log4j12:1.7.13”
}
}
如您所见,显示一个渐变:a:dependencies
[...]
compile - Compile classpath for source set 'main'.
\--- project :B
\--- org.slf4j:slf4j-log4j12:1.7.13
+--- org.slf4j:slf4j-api:1.7.13
\--- log4j:log4j:1.2.17
[...]
在项目A中的java代码中使用log4j是完全可能的。请参阅Q&A。如果不指定配置,Gradle将选择从运行时扩展的默认配置。快速修复方法是使用
compile project(path: ":B", configuration: "compile")
对于Android库(aar)的可传递运行时依赖项,从5.0开始使用Gradle解决了这一问题。默认的配置扩展自运行时,这意味着,根据Q&A上的解释,“它包含运行时
配置的所有依赖项和工件,可能还有更多。”运行时配置中project“:B”的依赖项是运行时
。这仍然不能解释为什么依赖项slf4j api
在project:A中显示为编译
。编译项目(':B')
方法从项目B获得默认配置,并将其添加到项目A的编译
配置中。因此,将B的运行时
依赖项添加到A的编译
依赖项是合乎逻辑的。我与@dmoebius离线讨论了这一点,尽管答案完全正确且有用,应该记住以下几点:明确指定compile
配置确实可以防止项目编译类路径被可传递的运行时依赖项“污染”,但是您的项目运行时类路径现在也缺少这些可传递的运行时依赖项。因此,您可以使用default
正在使用配置,或者您必须添加第二个依赖项,以将运行时
映射到运行时
:运行时项目(路径::B”,配置:“运行时”)
在这种情况下,不需要显式指定运行时
配置。由于默认值
扩展了运行时
您可以使用编译项目(':B')
在依赖项{}
部分中的每一行都配置了一个配置(即编译或运行时),因此它是逻辑的(至少对我而言)您永远不会在一行代码中配置两个配置。我希望maven以相同的方式运行(例如,所有可传递的运行时/编译依赖项都添加到声明的相同范围),感谢您的提问。在这种情况下,gradle的行为完全违反直觉:-(我在这里解释了gradle运行时依赖关系示例: