本文概览:介绍了版本冲突是什么,如何解决和避免。

1 何为依赖版本冲突

比如项目直接依赖ab,这两包都依赖c。我们在上线时,假设d模块代码用到了C2.0的代码,修了dc的版本号为2.0,,此时在项目依赖如下:

  • 项目->a->c(1.0)
  • 项目->b->d>->c(2.0)

在编译阶段是没有问题的,因为ad都是独立jar,不参与项目的编译了,所以在编译阶段不会报错,但是在运行阶段会存现错误,因为编译时是加载的c1.0的版本,而d需要c2.0这就是版本冲突。产生版本冲突原因:通过依赖传递,项目所依赖的jar可能有多个版本,但是只会保留一个版本。

2 maven选择jar版本策略

当在项目中依赖的一个jar存多个版本时,此时选择策略是最短路径。在项目依赖如下,此时项目中依赖的c1.02.0有两个版本,此时根据最短路径会选择1.0

  • 项目->a->c(1.0)
  • 项目->b->d>->c(2.0)

假设在路径相同时,如下,

  • 项目->a->c(1.0)
  • 项目->b->c(2.0)

此时早期版本是随机选择一个版本,maven2.0.9开始依赖于maven依赖顺序,如下,此时a依赖早于b依赖先被引用,所以此时会加载c2.0。

通过上面的覆盖策略,理解了自己项目中遇到一个依赖问题,如下app-service依赖关系。

  • app-service->base-service-sdk>core-sdk2.0
  • app-service->corse-sdk1.0

我们修改了base-service-sdkcore-sdk的版本号为2.0,在编译时,没有报错,但是在运行app-service会出现错误,因为此时app-service在编译打包时加载了c-sdk 1.0,而运行时base-model中某些方法依赖c-sdk2.0。为了解决这个问题我们可以升级下app-service-c-sdk的版本为2.0

3 冲突解决

解决冲突目的是:保证依赖的jar是自己想要的版本。有三种方式:

方式1:覆盖方式。这是最高效快速解决冲突方式。

还是上面的例子,项目依赖如下:

  • 项目->a->c(1.0),
  • 项目->b->d>->c(2.0),

此时为了使用到c(2.0),可以直接在项目的pom.xml中直接引入c2.0,即此时依赖如下:

  • 项目->c(2.0)   ##直接覆盖,根据路径最短原则此时会选择c.20版本
  • 项目->a->c(1.0)
  • 项目->b->d>->c(2.0)

方式2  exclude。这是最常用的方式

还是上面的实例,项目依赖如下:

  • 项目->a->c(1.0),
  • 项目->b->d>->c(2.0),

此时可以通过exclude方式在a中排除掉c1.0,如下

方式3 将版本的冲突的jar升级为相同的版本。

还是上面的实例,项目依赖如下:

  • 项目->a->c(1.0),
  • 项目->b->d>->c(2.0),

此时可以通过在a中奖c版本升级到2.0来解决。

4 冲突避免

冲突都是在编译时候无法发现,只有运行时,才可以发现,所以要在编译时期时期发现,有如下措施: 在引入一个新的包时,可以在打包完成之后,解压包看看这个jar的版本是不是自己想要的版本。 如果不是自己想要的jar,可以通过IDE插件 Dependency Analyzer来查看冲突的jar有哪些,通过覆盖或者exclude等手段保证依赖的包是自己的版本。

分类&标签