Maven依赖版本冲突报告

Author:  Wang, Yunfeng.

简介

依赖版本冲突是一个一直以来困扰Build系统的问题,众所周知,依赖版本冲突会带来很多运行时的问题,如果能够在开发和编译阶段就识别出这些问题,将会大大提高开发人员的工作效率,并且提高产品的稳定性。

本文将着重分析一下Maven依赖版本冲突的问题,然后介绍一下目前的常见的检测和报告工具。然后提出一个依赖版本冲突报告的增强。

目前这个功能已经贡献到开源社区。

什么是依赖版本冲突

依赖版本冲突指的是一个应用在开发和编译阶段拥有多个版本的依赖,在运行时选择其中一个版本,但是该版本可能无法满足所有用户的要求,看一下下面的例子:

Application有两个依赖,lib1和lib2。Lib1有一个高版本的间接依赖:spring-expression:3.2.3.RELEASE,lib2有一个低版本的依赖:spring-expression:3.1.3.RELEASE。Lib1在使用3.2.3.RELEASE的一个特有的类。开发和编译阶段没有任何问题,但是运行时会报出ClassNotFoundException。为什么会这样呢?

原来Maven在做依赖解析的时候依据“就近”原则,3.1.3.RELEASE版本的spring-expression是二级依赖,而3.2.3.RELEASE版本的spring-expression是三级依赖。Maven理所当然的会选择低版本的spring-expression。所以在运行时就会出现ClassNotFoundException。

这种类似的问题在运行时非常常见,那有什么办法能尽快检测出此类问题呢?

现存两种依赖版本冲突检测工具的不足

目前Maven社区提供了两种方式检测依赖版本冲突。

Enforcer Maven Plugin – Dependency Convergence Rule

Enforcer Maven插件能够基于定义的校验规则对目标工程做检测,识别出潜在的问题。Dependency Convergence就是其中一条校验规则。关于如何使用请参照:

http://maven.apache.org/enforcer/enforcer-rules/dependencyConvergence.html

这种方式有以下缺点:

  • 版本冲突报告输出在控制台中,不是很清晰
  • 有些时候即使有版本冲突问题,用户也不希望会导致编译失败,但是如果忽略问题,仅仅是将冲突报告输出到控制台中,绝大多数用户也会选择忽略掉

 

Project Info Report Plugin – Dependency Convergence Report

Project Info Report插件是Maven社区提供出来,可以用来生成工程相关信息报告,并且以HTML形式展示给用户。Dependency Convergence是其中一个报告,它会将当前工程的依赖冲突信息以直观的形式展示给用户。

但是它有如下缺点:

  • 只适用于多模块工程。也就是说,单工程项目不适用
  • 只分析项目的直接依赖,不分析项目的间接依赖。问题是大部分的依赖版本冲突都是发生在间接依赖部分,所以这意味着这个报告只能识别出一小部分依赖版本冲突问题。
  • 报告仅仅展示冲突的依赖所在的工程,没有提供详细的依赖树结构。这给开发人员解决依赖版本冲突问题带来很大的困难。

可见虽然Project Information Report插件提供了更好的结果展示方式,但是Dependency Convergence报告的内容并不十分精确,展示的信息也不够详细,下面看一下如何增强Dependency Convergence报告。

 

增强版依赖版本冲突检测报告

 增强版Dependency Convergence报告是基于上述Project Information Report插件提供的Dependency Convergence报告做进一步增强,针对上面提到的问题做了以下增强:

  • 分析当前项目的全部依赖,包括直接依赖和间接依赖
  • 适用于单模块项目和多模块项目
  • 对于版本冲突的依赖,会提供详细的依赖树

 

如何使用

1. 把maven-project-info-reports-plugin作为maven-site-plugin的一个report plugin加入到工程的pom.xml。

2. 到工程目录下,运行”mvn clean site”,生成报告

3. 打开”target/site/dependency-convergence.html”

这个增强已经合并到maven-project-info-reports-plugin中,将被包含在2.8版本当中。

如何解决依赖版本冲突

Maven提供两种方式解决依赖版本冲突问题。

1. 使用exclusions

依据上面增强版Dependency Convergence报告可以知道哪个依赖引入了冲突的依赖。

那么就可以在引入依赖的定义中添加exclusion,把冲突的依赖排除掉。

这种方式的缺点是你需要在所有的引入冲突依赖的地方加入exclusion才可以把冲突依赖彻底排除掉。

2. 在中指定冲突依赖的版本

在父项目pom.xml中指定一个统一的冲突依赖的版本会更加简便和清楚一些。

可以依据上面依赖版本冲突报告中的依赖树选择合适的父节点,在它的pom中指定统一的冲突依赖的版本。

结论

依赖版本冲突是Maven工程的一个严重问题,通过增强后的Dependency Convergence报告能够更准确,更清晰地暴露这些问题,并且该报告提供的依赖树可以帮助开发人员快速定位和解决问题。

 

* 本文版权和/或知识产权归eBay Inc所有。如需引述,请和联系我们[email protected]。本文旨在进行学术探讨交流,如您认为某些信息侵犯您的合法权益,请联系我们[email protected],并在通知中列明国家法律法规要求的必要信息,我们在收到您的通知后将根据国家法律法规尽快采取措施。

你可能感兴趣的:(开发)