删除 gradle 中的传递类路径依赖项
Posted
技术标签:
【中文标题】删除 gradle 中的传递类路径依赖项【英文标题】:Remove transitive classpath dependency in gradle 【发布时间】:2016-05-04 10:39:06 【问题描述】:我们正在运行一个带有 gradle 的 spring-boot 应用程序。
为了包含 spring-boot 插件,我们将其添加为依赖项:
buildscript
dependencies
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE")
不幸的是,这个插件附带了一个依赖项
org.apache.logging.log4j:log4j-slf4j-impl:2.4.1
我想排除。
已经尝试过添加:
dependencies
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE")
exclude group: 'org.apache.logging.log4j'
这不起作用。
同时添加:
configurations
classpath.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
没有任何作用。
欢迎任何提示。
【问题讨论】:
【参考方案1】:如果您尝试排除
org.apache.logging.log4j:log4j-slf4j-impl:2.4.1
试试
dependencies
classpath("org.springframework.boot:spring-boot-gradle-plugin:1.3.2.RELEASE")
exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
【讨论】:
等一下! spring-boot-gradle-plugin 没有 log4j-slf4j-impl 作为传递依赖。它来自其他地方。 嗯不,一旦我从 gradle 脚本中删除它,依赖关系也消失了。 使用 gradle 依赖任务查看所有传递依赖:gist.github.com/foragerr/3dcd361f8f277d100325 抱歉,gradle 插件根本没有出现在依赖关系图中。我认为它是插件的原因是,一旦我删除它,依赖关系也消失了。在依赖关系树中,我只看到带有 (*) 的版本 2.4.1,这意味着由规则强制执行。 你能不能也试试:configurations.classpath.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
buildscript 块内外。【参考方案2】:
当我想确保从未将依赖项添加到项目中时,我通常会回退到此。
configurations
all*.exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl', version '2.4.1'
但是你确定你需要排除依赖吗?它不应该是构建 jar/war 的一部分。 您可以使用“gradlew dependencies”检查所有依赖项。
【讨论】:
这行不通,因为我想使用它的 2.5 版。抱歉,我没有在问题中提到这一点。 我以前没用过,但你也可以将版本添加到排除项中。我相应地更新了答案。 不,这是不可能的【参考方案3】:问题是我将 log4j 声明为运行时依赖项:
ext
log4jVersion="2.5"
runtime (
"org.apache.logging.log4j:log4j-slf4j-impl:$log4jVersion",
"org.apache.logging.log4j:log4j-api:$log4jVersion",
"org.apache.logging.log4j:log4j-core:$log4jVersion"
)
这导致版本 2.4.1 被某些编辑器魔术获取为编译依赖项。
然后我在类路径上有 2.4.1 和 2.5。
一旦我将 log4j 声明为编译依赖,2.4.1 就消失了...
【讨论】:
【参考方案4】:两步,追踪传递依赖,然后将其从负责的库中排除。
gradle dependencies
为您提供包括传递的完整列表。如果您的项目很小,这可能会有所帮助,但对于大型企业构建......它的信息太多。请随意搜索,但我们会从dependencyInsight
获得更多相关信息。
gradle dependencyInsight --dependency someDependency
查找依赖项可能进入构建的所有位置。如果您有多个版本,这将有助于明确这些版本的来源。
在我的用例中,日志记录被明确声明为编译时依赖项,因此如下所示。如果log4j
在其他任何地方,您会看到有问题的库以及 v2.5
的编译时声明。
我必须在每个子模块上显式运行它。
$ gradle util:dependencyInsight --dependency org.apache.logging.log4j
Configuration on demand is an incubating feature.
:util:dependencyInsight
org.apache.logging.log4j:log4j-api:2.5
+--- compile
\--- org.apache.logging.log4j:log4j-core:2.5
\--- compile
org.apache.logging.log4j:log4j-core:2.5
\--- compile
(*) - dependencies omitted (listed previously)
BUILD SUCCESSFUL
Total time: 0.933 secs
现在,一旦您知道从哪里排除依赖项,就可以像以前一样删除它。您可以再次运行dependencyInsights
进行确认
dependencies
// found through `gradle dependencyInsight --dependency org.apache.logging.log4j`
classpath("someOtherGroup:someOtherArtifactId:1.0")
exclude group: 'org.apache.logging.log4j', module: 'log4j-slf4j-impl'
另一种解决方案可能是覆盖依赖解析器并将版本强制为2.5
configurations.all
resolutionStrategy.eachDependency DependencyResolveDetails details ->
if (details.requested.group == "org.apache.logging.log4j")
println "Updating version for: $details.requested.group:$details.requested.name:$details.requested.version --> 2.5"
details.useVersion '2.5'
我的意见是,我可能不想一直在resolutionStrategy
中添加检查,所以最好在dependencyInsights
中跟踪它。这也意味着在两个地方更新版本,如果另一个开发人员不知道 gradle 的 resolutionStrategy
是如何工作的,那么他们将有“奇怪”的行为......例如。我将log4j
更新为2.7
,但它仍然与2.5
一起构建?!?!
但两者都是有效的方法
【讨论】:
以上是关于删除 gradle 中的传递类路径依赖项的主要内容,如果未能解决你的问题,请参考以下文章
Gradle 中获取 gradle 依赖项缓存中 jar 文件路径的最简洁方法