Maven依赖冲突调解

175 阅读2分钟

最短路径优先原则

  • 依赖冲突产生的原因——依赖传递

    假设你的项目依赖jar包A,jar包A又依赖jar包B。当添加jar包A时,Maven会把jar包B也自动加入到项目中。比如刚刚我们添加了junit依赖,junit又依赖hamcrest,所以Maven会将junit和hamcrest都加入项目中。这时就可能会产生依赖冲突问题,比如依赖A会引入依赖C,依赖B也会引入依赖C。如果不进行调解则会引入两个依赖C,那么Maven是如何解决依赖冲突问题的呢?

image.png

依赖冲突调解 我们以Spring依赖为例,spring-webmvc依赖spring-aop,spring-context也依赖spring-aop,如果两个同时引入,会引入哪个版本的spring-aop呢?

    <dependency>

       <groupId>org.springframework</groupId>

       <artifactId>spring-context</artifactId>

       <version>5.2.12.RELEASE</version>

    </dependency>

    <dependency>

       <groupId>org.springframework</groupId>

       <artifactId>spring-webmvc</artifactId>

       <version>4.2.4.RELEASE</version>

    </dependency>
  • Maven调解依赖冲突的第一原则是最短路径优先原则:

    也就是说项目依赖关系树中路径最短的版本会被使用。例如,假设有几个jar包之间的依赖关系是: A->B->C->D(2.0) 和 E->F->D(1.0) ,如果同时引入A和E,那么D(1.0)会被使用,因为E到D的路径更短。 查看依赖路径的方式如下:

image.png spring-webmvc到spring-aop的路径如下:

image.png spring-context到spring-aop的路径如下:

image.png

可以看到,spring-webmvc到spring-aop的路径为:

spring-webmvc -> spring-context -> spring-aop

而spring-context到spring-aop的路径为:

spring-context -> spring-aop

spring-context到spring-aop的路径更短,所以spring-aop会按照spring-context的版本引入。

image.png

最先声明原则

最短路径优先原则不能解决所有问题,比如这样的依赖关系: A–>B–>C(1.0) 和 D–>E–>C(2.0) ,同时引入A和D之后,C(1.0)和C(2.0)的依赖路径长度都为2。此时第一原则将不能解决问题。 在依赖路径长度相等的前提下,在POM中依赖声明的顺序靠前的会被解析使用。比如:以上案例中,spring-webmvc和spring-context到spring-core的路径都为1。谁声明在上方,spring-core会按照谁的版本引入。

image.png

image.png

排除依赖、锁定版本

如果不想使用Maven默认的冲突调解方式,有两种方式可以手动进行冲突调解。

  • 排除依赖

比如以上案例中,想使用spring-webmvc的spring-aop包,那么可以让spring-context引入时排除引入spring-aop包,这样就可以使用spring-webmvc的spring-aop包了,写法如下:

<dependency>

   <groupId>org.springframework</groupId>

   <artifactId>spring-webmvc</artifactId>

   <version>4.2.4.RELEASE</version>

</dependency>

<dependency>

   <groupId>org.springframework</groupId>

   <artifactId>spring-context</artifactId>

   <version>5.2.12.RELEASE</version>

   <exclusions>

       <exclusion>

         

<groupId>org.springframework</groupId>

           <artifactId>spring-aop</artifactId>

       </exclusion>
       </exclusions>

</dependency>

  • 锁定版本

在Maven中为某个jar包配置锁定版本后,不考虑依赖的声明顺序和依赖路径,以锁定的版本的为准添加到工程中,此方法在企业开发中常用。以下可以直接配置spring-aop锁定的版本。

<dependencyManagement>

   <dependencies>

       <dependency>

         

<groupId>org.springframework</groupId>

           <artifactId>spring-aop</artifactId>

           <version>4.2.4.RELEASE</version>

       </dependency>

   </dependencies>

</dependencyManagement>