项目跑着跑着突然报 NoSuchMethodError,或者明明引入了某个包却提示 ClassNotFoundException,这种时候十有八九是依赖冲突在捣鬼。以前我排查这类问题,都是老老实实打开 pom.xml 或者 build.gradle 一行行看,再敲 mvn dependency:tree 慢慢翻,眼睛都看花了还不一定找得准。后来用了 Dependency 依赖项查看器,才发现这事其实可以很省心,一键就能把整个项目的依赖树摊开给你看,哪个版本被覆盖了、哪条路径引进来的,清清楚楚。今天就把我自己的使用经验分享出来,顺便聊聊怎么靠它快速排查依赖冲突。

说白了,依赖冲突就是同一个库被不同路径引入了多个版本。比如你项目里直接依赖了 A 库 1.2 版本,结果 B 库又偷偷依赖了 A 库 1.0 版本,Maven 或者 Gradle 在解析的时候只能选一个,选了谁另一个就可能出问题。这种传递性依赖最坑人,你根本不知道它从哪冒出来的。Dependency 依赖项查看器的好处就在这,它会把所有依赖的来龙去脉都列出来,哪个版本最终生效、哪个版本被忽略了,一眼就能看明白。我之前有个项目,日志框架 slf4j 死活绑不上,用这个查看器一查,发现 log4j 和 logback 各自带了一个 slf4j 版本,冲突得明明白白,手动排除掉多余的依赖就搞定了。
不同的项目类型用的查看器不太一样,Java 项目常见的像 IDEA 自带的 Maven 依赖分析器、Eclipse 的 Dependency Hierarchy,还有独立工具比如 Dependency-Check。前端项目的话,npm 的 npm ls 命令也算是一种依赖项查看器。我平时用得最多的是 IDEA 里的那个,打开 pom.xml 之后右键选 Diagrams 再选 Show Dependencies,整个依赖关系图就出来了。红色的线代表冲突,右键可以直接 Exclude 掉多余的版本,改完刷新一下 Maven 就生效。Dependency 依赖项查看器最实用的功能就是能直接定位到冲突的 jar 包路径,不用你自己去猜。另外像 依赖冲突排查 这种活,用命令行工具 mvn dependency:tree -Dverbose 也能看,但图形化界面确实更直观,尤其是依赖特别多的大项目。

第一个坑,别看到冲突就无脑排除。有些冲突是兼容的,比如同一个库的小版本升级,这种一般没事,真正要处理的是大版本不一致或者包名都变了的那种。第二个坑,排除依赖的时候要看清是哪条路径引进来的,有时候你排除了直接依赖里的,传递依赖里又冒出来一个,得顺着查看器给的路径一层层找。第三个技巧,用 Dependency 依赖项查看器 的时候可以配合搜索功能,直接搜关键包名,比在几百个节点里翻快多了。还有一点,改完依赖之后记得重新构建一下,有时候 IDE 缓存没刷新,看着冲突还在其实已经解决了。我现在养成习惯,每次加新依赖之前都先看一眼依赖树,能省掉后面很多莫名其妙的报错。
总的来说,Dependency 依赖项查看器 算不上什么高大上的东西,但确实是日常开发里很实用的一个小工具。尤其是团队协作的时候,别人引了个什么包导致你这边编译不过,用它一查就能找到源头,不用互相扯皮。如果你还在手动翻依赖文件,真的可以试试这种一键排查的方式,效率提升不是一点半点。
游戏软件