🔍 Maven dependency:tree 的 8 个高级用法
💡 摘要: 本文深入讲解 Maven dependency:tree 命令的 8 个高级用法,涵盖依赖冲突排查、传递依赖分析、版本升级建议等实战场景。通过企业级真实案例,展示如何利用这个强大工具快速定位和解决复杂的依赖问题。提供可视化分析方法、自动化脚本工具和企业级依赖管理规范,让你掌握专业级的依赖分析技能。
🎯 前言:为什么你需要掌握 dependency:tree?
1.1 依赖冲突那些痛
真实案例一:诡异的 ClassCastException
现象:运行时抛出 ClassCastException
错误信息:com.google.common.collect.ImmutableList cannot be cast to ...
排查过程:
- 检查代码,类型转换没问题
- 查看依赖,发现 Guava 有两个版本
- A 依赖引入 Guava 20.0
- B 依赖引入 Guava 31.1-jre
- Maven 选择了 20.0(较近的)
- 但代码是按 31.1 的特性写的
结果:类型转换失败
解决:排除旧版本,强制使用新版本
如果早点掌握 dependency:tree,这个问题 5 分钟就能解决!
真实案例二:jar Hell 地狱
项目启动报错:
NoSuchMethodError: XXX.method()
排查发现:
- spring-core 有 4 个不同版本
- spring-beans 有 3 个不同版本
- 总共 50+ 个 Spring 相关 jar
- 各种版本交叉依赖
就像一锅粥,谁也说不清谁依赖谁
用 dependency:tree 一看,一目了然!
1.2 dependency:tree 能帮你什么
graph TB
A[dependency:tree] --> B[查看完整依赖树]
A --> C[查找特定依赖]
A --> D[分析依赖冲突]
A --> E[识别冗余依赖]
A --> F[优化依赖结构]
B --> G[了解项目全貌]
C --> H[快速定位问题]
D --> I[解决版本冲突]
E --> J[精简依赖体积]
F --> K[提升构建性能]
🌟 用法一:基础查看依赖树 ⭐⭐⭐⭐⭐
2.1 基本命令
# 查看当前项目的完整依赖树
mvn dependency:tree
# 输出示例
[INFO] --- maven-dependency-plugin:3.5.0:tree (default-cli) @ my-project ---
[INFO] com.example:my-project:jar:1.0.0
[INFO] +- org.springframework.boot:spring-boot-starter:jar:3.2.0:compile
[INFO] | +- org.springframework.boot:spring-boot:jar:3.2.0:compile
[INFO] | +- org.springframework.boot:spring-boot-autoconfigure:jar:3.2.0:compile
[INFO] | +- org.springframework:spring-core:jar:6.1.1:compile
[INFO] | \- org.springframework:spring-context:jar:6.1.1:compile
[INFO] +- com.google.guava:guava:jar:31.1-jre:compile
[INFO] \- junit:junit:jar:4.13.2:test
2.2 读懂依赖树符号
符号说明:
+- 直接依赖(第一层)
| +- 传递依赖(第二层)
| | +- 传递依赖(第三层)
\- 最后一个直接依赖
\- 它的传递依赖
Scope 标识:
compile: 编译和运行时都需要
provided: 仅需编译,运行时由容器提供
runtime: 仅运行时需要
test: 仅测试时需要
system: 系统提供的本地 jar
2.3 输出到文件
# 输出到文本文件
mvn dependency:tree -DoutputFile=deps.txt
# 查看文件
cat deps.txt
# 或用编辑器打开
code deps.txt # VS Code
notepad deps.txt # Windows
🔍 用法二:包含过滤(includes)⭐⭐⭐⭐⭐
3.1 查找特定依赖
# 查找所有包含"spring"的依赖
mvn dependency:tree -Dincludes=org.springframework:*
# 输出
[INFO] +- org.springframework.boot:spring-boot-starter:jar:3.2.0:compile
[INFO] | +- org.springframework.boot:spring-boot:jar:3.2.0:compile
[INFO] | +- org.springframework:spring-core:jar:6.1.1:compile
3.2 精确匹配
# 查找特定的 artifact
mvn dependency:tree -Dincludes=com.google.guava:guava
# 查找特定版本
mvn dependency:tree -Dincludes=junit:junit:4.13.2
3.3 通配符匹配
# 使用通配符
mvn dependency:tree -Dincludes="*:spring-*"
# 查找所有 spring 开头的依赖
mvn dependency:tree -Dincludes="org.springframework:**"
3.4 实战场景
场景一:想知道哪里引入了某个依赖
问题:项目中出现了 slf4j,但我不记得在哪里引入的
解决:
mvn dependency:tree -Dincludes=org.slf4j:*
输出会显示完整的引入路径:
A → B → C → slf4j
这样就知道是哪个依赖带来的了
🚫 用法三:排除过滤(excludes)⭐⭐⭐⭐
4.1 排除特定依赖
# 查看依赖树,但不包含某些依赖
mvn dependency:tree -Dexcludes=org.slf4j:slf4j-simple
# 排除多个依赖
mvn dependency:tree \
-Dexcludes=org.slf4j:slf4j-simple,junit:junit
4.2 实战应用
场景:怀疑某个依赖有问题,想临时排除它测试
步骤:
1. 先用 excludes 排除该依赖
mvn dependency:tree -Dexcludes=com.xxx:problem-lib
2. 运行测试
mvn test
3. 如果问题解决,说明确实是该依赖的问题
4. 在 pom.xml 中正式排除或升级
📊 用法四:详细模式(verbose)⭐⭐⭐⭐⭐
5.1 启用详细模式
# 显示被省略的版本
mvn dependency:tree -Dverbose
# 输出示例
[INFO] +- org.springframework:spring-core:jar:6.1.1:compile
[INFO] | \- (org.springframework:spring-jcl:jar:6.1.1:compile - omitted for duplicate)
5.2 理解"omitted"
常见省略原因:
omitted for duplicate:
重复的依赖,Maven 选择了其中一个
omitted for conflict with version X.X:
版本冲突,Maven 选择了另一个版本
omitted as scope 'test' is closer than 'compile':
scope 冲突,选择了更近的 scope
5.3 实战价值
通过 verbose 模式,你可以:
1. 发现隐藏的依赖冲突
2. 理解 Maven 的仲裁机制
3. 找到被意外覆盖的版本
4. 优化依赖结构
这是排查复杂依赖问题的利器!
🎯 用法五:指定模块(pl)⭐⭐⭐⭐
6.1 单模块分析
# 只看某个模块的依赖树
mvn dependency:tree -pl user-service
# 多模块项目非常有用
# 避免输出太长看不清
6.2 连带依赖一起看
# 包含依赖该模块的其他模块
mvn dependency:tree -pl user-service -am
# -am = --also-make
# 同时显示父模块和依赖的模块
6.3 组合使用
# 查看特定模块中包含 spring 的依赖
mvn dependency:tree -pl order-service \
-Dincludes=org.springframework:* \
-Dverbose
📈 用法六:生成可视化图表 ⭐⭐⭐
7.1 生成 DOT 格式
# 安装 graphviz(用于渲染 DOT 文件)
# Mac
brew install graphviz
# Ubuntu
sudo apt-get install graphviz
# 生成 DOT 文件
mvn dependency:tree -DoutputType=dot -DoutputFile=deps.dot
# 转换为图片
dot -Tpng deps.dot -o deps.png
# 打开查看
open deps.png # Mac
xdg-open deps.png # Linux
start deps.png # Windows
7.2 在线可视化工具
推荐工具:
1. Gource: https://gource.io/
动态展示项目演化
2. Deps.dev: https://deps.dev/
Google 提供的依赖分析工具
3. Snyk: https://snyk.io/
安全漏洞扫描 + 依赖分析
🔬 用法七:深度控制(depth)⭐⭐⭐
8.1 限制显示深度
# 只显示前 2 层
mvn dependency:tree -Ddepth=2
# 只显示直接依赖
mvn dependency:tree -Ddepth=1
# 显示完整深度(默认)
mvn dependency:tree -Ddepth=999
8.2 适用场景
深度=1:
只想看直接引入了哪些库
深度=2:
想看直接依赖 + 它们的主要依赖
深度=3+:
深入分析传递依赖
排查复杂的依赖冲突
💡 用法八:结合其他命令 ⭐⭐⭐⭐
9.1 与 analyze 结合
# 分析未使用的依赖
mvn dependency:analyze
# 先分析,再看树状结构
mvn dependency:tree -Dincludes=未使用的依赖
9.2 与 purge 结合
# 清理本地仓库后重新分析
mvn dependency:purge-local-repository
mvn dependency:tree -Dverbose
9.3 与 resolve 结合
# 解析并下载所有依赖
mvn dependency:resolve
mvn dependency:tree
🏢 企业级实战案例
案例一:Spring 版本冲突排查
问题背景:
项目启动时报错:
Caused by: java.lang.ClassNotFoundException:
org.springframework.util.StringUtils
排查过程:
步骤 1: 查看完整依赖树
mvn dependency:tree -Dverbose > tree.txt
步骤 2: 搜索 Spring 相关
grep "spring-core" tree.txt
发现:
- spring-boot-starter 引入 spring-core 6.1.1
- 第三方库引入 spring-core 5.3.20
步骤 3: 找出是谁引入的旧版本
mvn dependency:tree -Dincludes=org.springframework:spring-core -Dverbose
输出:
[INFO] +- com.thirdparty:old-lib:jar:1.0.0:compile
[INFO] | \- (org.springframework:spring-core:jar:5.3.20:compile - omitted for conflict with 6.1.1)
步骤 4: 解决方案
方案 A: 升级 old-lib 到支持 Spring 6 的版本
方案 B: 强制指定 Spring 版本
方案 C: 排除旧版本,显式引入新版本
最终选择方案 B:
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>6.1.1</version>
</dependency>
</dependencies>
</dependencyManagement>
案例二:日志框架冲突解决
问题:
日志不输出,控制台一片空白
排查:
mvn dependency:tree -Dincludes=org.slf4j:* -Dverbose
发现:
- slf4j-api 1.7.36
- slf4j-simple 1.7.36
- logback-classic 1.4.11 (依赖 slf4j-api 2.0.x)
- log4j-slf4j-impl 2.20.0 (也依赖 slf4j-api)
问题根源:
SLF4J 有多个实现,互相冲突
解决:
统一使用 logback:
1. 排除其他实现
2. 只保留 logback
<dependencies>
<!-- 排除 log4j -->
<dependency>
<groupId>xxx</groupId>
<artifactId>xxx</artifactId>
<exclusions>
<exclusion>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 统一使用 logback -->
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.4.11</version>
</dependency>
</dependencies>
🛠️ 自动化脚本
依赖分析报告生成器
#!/bin/bash
# dependency-report.sh
echo "📊 开始生成 Maven 依赖分析报告..."
PROJECT_NAME=$(basename $(pwd))
REPORT_DIR="dependency-report"
mkdir -p $REPORT_DIR
# 1. 完整依赖树
echo "1. 生成完整依赖树..."
mvn dependency:tree -DoutputFile=$REPORT_DIR/full-tree.txt
# 2. 详细模式
echo "2. 生成详细依赖树..."
mvn dependency:tree -Dverbose -DoutputFile=$REPORT_DIR/verbose-tree.txt
# 3. 按 groupId 分类
echo "3. 按组织分类统计..."
for group in org.springframework org.apache.commons com.google; do
mvn dependency:tree -Dincludes=$group:\* \
-DoutputFile=$REPORT_DIR/${group}.txt 2>/dev/null
done
# 4. 依赖统计
echo "4. 统计依赖数量..."
mvn dependency:count-plugins \
-DoutputFile=$REPORT_DIR/plugin-count.txt
# 5. 生成 HTML 报告(如果有依赖插件)
echo "5. 生成 HTML 报告..."
mvn dependency:tree -DoutputType=dot \
-DoutputFile=$REPORT_DIR/tree.dot
if command -v dot &> /dev/null; then
dot -Thtml $REPORT_DIR/tree.dot \
-o $REPORT_DIR/tree.html
fi
echo ""
echo "✅ 报告生成完成!"
echo "报告目录:$(pwd)/$REPORT_DIR"
echo ""
echo "查看报告:"
echo " cat $REPORT_DIR/full-tree.txt"
echo " open $REPORT_DIR/tree.html"
📊 依赖健康检查清单
✅ 检查项:
1. 版本一致性
□ 同一库没有多个版本
□ Spring 系列版本匹配
□ Log4j/SLF4J 版本统一
2. 依赖必要性
□ 没有未使用的依赖
□ 测试依赖 scope 正确
□ 没有循环依赖
3. 安全性
□ 无已知安全漏洞
□ 版本不是太老
□ 定期更新依赖
4. 性能优化
□ 没有过大的依赖
□ 传递依赖合理
□ 构建时间可接受
🎁 福利:常用命令速查表
# 基础命令
mvn dependency:tree # 查看完整依赖树
mvn dependency:tree -DoutputFile=deps.txt # 输出到文件
# 过滤命令
mvn dependency:tree -Dincludes=groupId:artifactId # 包含过滤
mvn dependency:tree -Dexcludes=groupId:artifactId # 排除过滤
mvn dependency:tree -Dverbose # 详细模式
# 模块控制
mvn dependency:tree -pl module-name # 指定模块
mvn dependency:tree -pl module -am # 包含依赖
# 深度控制
mvn dependency:tree -Ddepth=1 # 只看直接依赖
mvn dependency:tree -Ddepth=2 # 看前两层
# 高级组合
mvn dependency:tree -pl xxx -Dincludes=yyy -Dverbose
🕳️ 避坑指南:依赖树分析的 6 个致命错误
⚠️ 错误 1:只看直接依赖,不管传递依赖
现象:pom.xml 看起来很干净,但项目问题不断
实际情况:
❌ 错误认知:
我的 pom.xml 只有 10 个直接依赖,很简洁!
✅ 残酷现实:
mvn dependency:tree 一看
├─ 直接依赖:10 个
└─ 传递依赖:150+ 个
├─ Spring 相关:30 个
├─ Jackson 相关:20 个
└─ 其他传递依赖:100+ 个
问题:
- 传递依赖版本冲突
- 重复的类定义
- 不必要的依赖引入
- 安全隐患传递
案例分析:
<!-- 你的 pom.xml -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
<!-- 看起来很简单?实际上传递依赖很复杂 -->
<!-- 运行以下命令查看真相 -->
mvn dependency:tree -Dverbose
✅ 正确做法:
# 每次修改依赖后都检查完整树
mvn dependency:tree
# 特别关注传递依赖
mvn dependency:tree -Dincludes=*
# 分析是否有冲突
mvn dependency:analyze
# 识别未使用的依赖
mvn dependency:analyze-unused
最佳实践:
- ✅ 定期(每周)检查依赖树
- ✅ 重点关注传递依赖的版本
- ✅ 使用 BOM 统一管理框架依赖
- ✅ 排除不必要的传递依赖
⚠️ 错误 2:忽视 Maven 的"就近原则"
现象:明明指定了版本,但运行时不是这个版本
风险等级: 🔴 高危
Maven 仲裁规则:
路径最短优先(就近原则):
项目 → A 依赖 → commons-lang3:2.7
项目 → B 依赖 → C 依赖 → commons-lang3:3.12
结果:Maven 选择 2.7 版本(路径更短)
即使 3.12 版本更新!
声明优先原则:
如果路径长度相同
先声明的依赖获胜
<dependencies>
<dependency>A</dependency> <!-- 先声明,获胜 -->
<dependency>B</dependency>
</dependencies>
真实案例:
<!-- ❌ 问题配置 -->
<dependencies>
<!-- 引入旧版 Guava -->
<dependency>
<groupId>com.example</groupId>
<artifactId>library-a</artifactId>
<version>1.0.0</version>
<!-- 传递依赖:guava 20.0 -->
</dependency>
<!-- 想引入新版 Guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
</dependencies>
<!-- 结果:由于 library-a 先声明,Guava 20.0 获胜 -->
✅ 解决方案:
方案 A:使用 dependencyManagement 强制管理
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version> <!-- 强制使用此版本 -->
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<!-- 这里不需要写 version -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
</dependencies>
方案 B:排除传递依赖
<dependency>
<groupId>com.example</groupId>
<artifactId>library-a</artifactId>
<exclusions>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 单独引入新版本 -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>31.1-jre</version>
</dependency>
⚠️ 错误 3:滥用 optional 依赖
现象:为了减少传递依赖,把所有依赖都设为 optional
风险等级: 🟡 中危
错误示范:
<!-- ❌ 过度使用 optional -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional> <!-- 不该用 -->
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<optional>true</optional> <!-- 不该用 -->
</dependency>
<!-- 所有依赖都 optional... -->
</dependencies>
结果:
- 子模块无法继承依赖
- 运行时 ClassNotFound
- 打包后缺少必要 jar
optional 的正确理解:
optional=true 的含义:
✅ 适用场景:
- 可选功能依赖(如插件系统)
- 测试工具依赖
- 特定场景才需要的依赖
❌ 不适用场景:
- 核心业务依赖
- 运行时必需的依赖
- 框架基础依赖
传递规则:
A (optional) → B
↓
C 依赖 A
↓
C 不会自动获得 B
需要 C 显式声明依赖 B
✅ 正确使用示例:
<!-- ✅ 核心依赖(不设置 optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- ✅ 可选功能依赖(设置 optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- ✅ 测试依赖(使用 test scope) -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
⚠️ 错误 4:不看依赖的 scope
现象:编译通过,运行时失败
典型场景:
场景一:provided 依赖误用
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope> <!-- 仅编译时需要 -->
</dependency>
问题:
- 本地开发(Tomcat 提供 servlet API)✅ 正常
- 打成 fat jar 独立运行 ❌ 失败
- 原因:provided 依赖不会打包
场景二:test 依赖误用
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope> <!-- 仅测试时需要 -->
</dependency>
问题:
- 在 main 代码中引用了测试类
- 编译报错:找不到符号
- 因为 junit 只在测试 classpath
Scope 详解:
| Scope | 编译 | 测试 | 运行 | 打包 | 传递 |
|---|---|---|---|---|---|
| compile | ✅ | ✅ | ✅ | ✅ | ✅ |
| provided | ✅ | ✅ | ❌ | ❌ | ❌ |
| runtime | ❌ | ✅ | ✅ | ✅ | ✅ |
| test | ❌ | ✅ | ❌ | ❌ | ❌ |
| system | ✅ | ✅ | ❌ | ❌ | ❌ |
记忆口诀:
compile 全都要
provided 容器给
test 只测不用跑
runtime 跑时才要
✅ 最佳实践:
<!-- ✅ 默认使用 compile(不写就是 compile) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!-- scope 默认为 compile -->
</dependency>
<!-- ✅ Tomcat 等容器提供的依赖 -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<scope>provided</scope>
</dependency>
<!-- ✅ 数据库驱动(运行时才需要) -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- ✅ 测试框架 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
⚠️ 错误 5:依赖树输出太多就不管
现象:依赖树太长(500+ 行),直接放弃分析
实际问题:
大型项目依赖树:
mvn dependency:tree > deps.txt
wc -l deps.txt
结果:800+ 行!
开发者反应:😱 太多了,不看!
后果:
- 隐藏的版本冲突
- 冗余依赖浪费空间
- 安全风险传递
- 构建时间增加
✅ 高效分析方法:
方法一:分层过滤
# 第一步:只看直接依赖
mvn dependency:tree -Ddepth=0
# 输出:只显示第一层依赖(通常 20-30 个)
# 第二步:查看有问题的特定依赖
mvn dependency:tree -Dincludes=com.google.guava
# 第三步:深度分析特定模块
mvn dependency:tree -pl :problem-module -Dverbose
方法二:可视化工具
# 生成 DOT 文件(Graphviz 格式)
mvn dependency:tree -DoutputFile=deps.dot
# 转换为 PNG 图片(需要安装 Graphviz)
dot -Tpng deps.dot -o deps.png
# 或用在线工具查看
# https://dreampuf.github.io/GraphvizOnline/
方法三:IDEA 插件
推荐插件:
1. Maven Helper (⭐⭐⭐⭐⭐)
- 可视化依赖树
- 快速搜索依赖
- 一键解决冲突
2. Dependency Analyzer
- 图形化展示
- 识别循环依赖
- 统计依赖大小
使用技巧:
- 右键 pom.xml → Open Dependency Visualization
- Ctrl+F 搜索特定依赖
- 红色标记表示冲突
方法四:自动化脚本
#!/bin/bash
# check-dependencies.sh
echo "=== 依赖统计 ==="
mvn dependency:tree | grep -c "^\[INFO\]" | xargs echo "总行数:"
echo -e "\n=== 直接依赖 ==="
mvn dependency:tree -Ddepth=0 | grep "^\[INFO\] +-" | wc -l | xargs echo "数量:"
echo -e "\n=== 检查冲突 ==="
mvn dependency:analyze | grep -E "(CONFLICT|WARNING)" | head -20
echo -e "\n=== 未使用依赖 ==="
mvn dependency:analyze-unused | grep "Unused declared dependencies" -A 10
⚠️ 错误 6:不建立依赖审查机制
现象:随便引入依赖,不考虑后果
团队协作灾难:
真实案例:
开发 A:引入一个新库(没告诉团队)
开发 B:又引入类似的库(功能重复)
开发 C:发现冲突,手动排除
开发 D:不知道为什么要排除,跟着改
半年后:
- pom.xml 面目全非
- 各种奇怪的 exclusion
- 没人知道为什么这样配
- 构建时间从 5 分钟变 20 分钟
✅ 建立依赖审查流程:
流程一:引入新依赖前检查清单
□ 必要性评估
- 是否真的需要这个依赖?
- 能否用现有依赖实现?
- 是否值得为此增加复杂度?
□ 质量评估
- GitHub Star 数 > 100?
- 最后更新时间 < 6 个月?
- 下载量 > 10000/月?
- 有无重大安全漏洞?
□ 兼容性评估
- 与现有依赖版本兼容吗?
- 会引入冲突吗?
- 需要排除传递依赖吗?
□ 许可证检查
- 开源协议是什么?
- 能商用吗?
- 需要公开源码吗?
流程二:PR/MR 审查要点
Code Review 检查清单:
✅ pom.xml 变更
□ 新增依赖是否必要?
□ 版本号是否明确?
□ 是否需要 exclusion?
□ scope 是否正确?
✅ 影响评估
□ 构建时间影响?
□ 包体积增加?
□ 是否有破坏性变更?
□ 需要更新文档吗?
✅ 验证步骤
□ mvn dependency:tree 检查
□ mvn dependency:analyze 分析
□ 本地构建测试
□ CI/CD流水线验证
流程三:定期依赖审计
# 每月执行一次依赖健康检查
# 1. 检查过期依赖
mvn versions:display-dependency-updates
# 2. 检查安全漏洞
mvn org.owasp:dependency-check-maven:check
# 3. 清理未使用依赖
mvn dependency:analyze-unused
# 4. 生成依赖报告
mvn dependency:resolve -Dclassifier=sbom
流程四:依赖管理规范
团队规范文档:
1. 版本管理
- 所有依赖必须明确版本号
- 使用 properties 统一管理
- 禁止使用 LATEST/RELEASE
2. 引入流程
- 提交依赖引入申请
- Tech Lead 审批
- 更新依赖清单文档
3. 维护责任
- 谁引入谁负责
- 定期更新版本
- 及时修复漏洞
4. 文档记录
- 维护依赖清单
- 记录引入原因
- 标注注意事项
💡 避坑总结
mindmap
root(dependency:tree 避坑指南)
分析视角
不仅看直接依赖
重视传递依赖
定期全面检查
版本仲裁
理解就近原则
使用 dependencyManagement
合理排除冲突
依赖属性
慎用 optional
正确设置 scope
理解传递规则
方法技巧
分层过滤分析
使用可视化工具
自动化脚本辅助
团队协作
建立审查流程
Code Review 把关
定期依赖审计
规范管理
版本统一管理
引入要审批
文档要完善
💬 互动环节
你在依赖管理中遇到过哪些奇葩问题?
欢迎在评论区分享你的排查经历和独门技巧!
常见问题 TOP5:
- 依赖冲突导致 ClassCastException 怎么排查?
- 如何快速找到传递依赖的来源?
- dependency:tree 输出太多怎么看?
- 如何排除不需要的传递依赖?
- 多模块项目中依赖冲突如何处理?
💡 我会在评论区持续答疑,欢迎留言!