第3章 依赖树分析工具

3.1 gradle dependencies 命令详解

gradle dependencies 是 Gradle 内置的依赖树命令,以树形结构展示项目所有配置(compileClasspath、runtimeClasspath、testCompileClasspath 等)下的直接与传递依赖。在大型多模块项目中,该命令是发现冲突、冗余和循环依赖的首选入口。

提示:在 build.gradle 或 settings.gradle 中添加 --scan 参数可生成在线构建扫描报告,包含更多依赖分析维度。

常用变体命令

命令作用域输出内容
gradle dependencies默认配置列出所有配置(compile、runtime、test 等)的完整树
gradle dependencies --configuration runtimeClasspath指定配置仅输出 runtimeClasspath 的依赖树
gradle :subproject:dependencies子项目只打印指定子项目的依赖树
gradle dependencies --offline离线模式使用本地缓存输出,跳过网络解析

输出格式解读

+--- com.example:lib-core:1.0.0
|    |    +--- com.example:lib-utils:1.2.0
|    |    |    \--- org.slf4j:slf4j-api:1.7.30
|    |    \--- com.fasterxml.jackson:jackson-core:2.12.3
|    |         \--- (c) com.fasterxml.jackson:jackson-annotations:2.12.3
|    \--- (x) com.example:lib-deprecated:0.9.0 -> 1.0.0
\--- junit:junit:4.13.2 (testRuntimeClasspath)

符号含义:+--- 表示第一个直接依赖,\--- 表示最后一个直接依赖,| 表示延续父级分支。括号标识:(c) 表示冲突被解决(显示实际使用的版本),(x) 表示动态版本被解析。

3.2 在线依赖报告

Gradle 提供两种在线依赖报告方式:构建扫描(Build Scan) 和 Gradle Enterprise 依赖面板。构建扫描通过 --scan 参数上传至 scans.gradle.com,生成包含依赖树、模块版本、冲突统计的交互式 Web 页面。

gradle build --scan
# 终端输出:Publishing build scan...
# 点击链接:https://scans.gradle.com/s/abcd1234

在线报告优势:支持按模块搜索、展开/折叠、版本对比和冲突定位;可分享给团队成员,无需本地日志。Gradle Enterprise 还提供“依赖洞察”板块,自动标记冗余依赖和违规版本。

3.3 过滤冗余依赖

冗余依赖指同一个模块在依赖树中出现多次(不同版本)或强制被提升到更高版本后不再被使用的低版本分支。过滤冗余的流程包括:

  1. 使用 gradle dependencies --configuration compileClasspath > deps.txt 导出完整树
  2. 通过 grep "->" 或 findstr "->"(Windows)筛选出有版本提升的依赖
  3. 使用 gradle dependencyInsight --dependency <模块名> 分析单个库的版本选定原因
  4. 在 build.gradle 中通过 constraints 或 force 消除无用的低版本分支

实际命令组合

# 列出所有被提升的依赖(版本冲突解决结果)
gradle dependencies | grep "->"
# 或使用 --scan 后在线查看 "Dependency versions" 面板

# 检查特定模块为何被选择 2.0.0 而不是 1.8.0
gradle dependencyInsight --dependency com.fasterxml.jackson:jackson-databind --configuration runtimeClasspath
关键指标:冗余依赖每消除一个,可减少构建解析阶段约 5%–15% 的元数据处理开销,并在多模块中降低插件冲突风险。

3.4 常见错误与调试

错误现象可能原因解决办法
依赖树输出为空配置名称拼写错误或项目无该配置检查 --configuration 参数是否正确,或先运行 gradle projects 确认模块路径
大量 -> 提升但构建失败多个子模块声明了冲突版本,且存在不兼容的 API 变化使用 dependencyInsight 定位冲突源,统一使用 constraints 锁定版本
在线扫描链接无法打开企业环境禁止外网连接或 Gradle Enterprise 未配置使用 --offline 本地分析,或在 gradle.properties 中设置代理
依赖树过大导致控制台截断子模块过多或传递依赖深度过大重定向到文件:gradle dependencies > full_tree.txt,再用编辑器搜索
注意:在 CI 环境中执行 gradle dependencies 可能因依赖解析超时(默认 30 分钟)而失败。建议设置 dependencyResolutionManagement.repositories 为本地镜像,并增加 org.gradle.internal.dependency.resolution.timeout=600000。
依赖树分析工具工作流程 gradle dependencies 导出/重定向文本 grep / --scan 定位冗余依赖 dependencyInsight 分析 修复(force/constraints) 重新执行验证 反馈回路:若修复后仍有冗余,返回节点4或5再次分析,直至依赖树收敛。