Maven 版本冲突,试试 dependencyManagement | Java Debug 笔记

1,477 阅读2分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

dependencies

一般我们在 Maven 管理的项目中会看到 dependencies 的使用,通过这个标签,来管理依赖。

<dependencies>
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
      	<version>3.17</version>
    </dependency>
</dependencies>

但是会出现一些弊端:

1.在多模块的项目中,如果父 pom 中引入依赖,则子模块会全盘接受父 pom 中引入的依赖,即使它本身不需要这个依赖。如果子模块单独启动或打包的话,速度变慢、打的jar臃肿。

2.为了避免第一个问题,则在子模块中进行所需依赖。但是如果,其他子模块也需要这个依赖时,不注意就容易造成版本冲突。

因此才有了 dependencyManagement。

dependencyManagement

这个标签在多模块的项目尤其好用。

使用位置

一般是用在父 pom 中的。

使用示例

父模块 pom
<dependencies>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <version>2.1.9.RELEASE</version>
    <scope>test</scope>
    <exclusions>
      <exclusion>
        <groupId>com.vaadin.external.google</groupId>
        <artifactId>android-json</artifactId>
      </exclusion>
    </exclusions>
  </dependency>
</dependencies>

<dependencyManagement>
  <dependencies>
      <dependency>
          <groupId>org.apache.poi</groupId>
          <artifactId>poi-ooxml</artifactId>
          <version>3.17</version>
      </dependency>
  </dependencies>
</dependencyManagement>

在父 pom 中声明了上述的依赖,实际不会直接真实导入依赖。而只是一个声明的作用。

使用 Maven Helper 查看一下父级 pom。

image-20200514183448632

可以看到,只有通过 dependencies 引入的依赖。

子模块 pom

子模块 pom 可以根据需要,只声明对应的 groupId 和 artifactId 来引入依赖。而省略的 version 和 scope,会沿着树向上层 pom 查找最近的 dependencyManagement 声明的 groupId 和 artifactId,并使用其声明的 version 和 scope。

<dependencies>
    <!-- external -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
    </dependency>
</dependencies>

image-20200514184032552

子模块覆盖

允许子模块声明 version 和 scope, 来覆盖父级继承的配置。

<dependencies>
    <!-- external -->
    <dependency>
        <groupId>org.apache.poi</groupId>
        <artifactId>poi-ooxml</artifactId>
         <version>3.18</version>
    </dependency>
</dependencies>

image-20200514184352853

明确传递依赖版本

使用 dependencyManagement 时,如果项目中出现了多个传递依赖的版本,会被 dependencyManagement 声明的版本覆盖。有好处也有坏处。

如果版本兼容的话,就剩了我们去排除版本的麻烦。

缺点是,出现版本冲突的时候,不是很容易被注意到。

依赖优先级

父 pom 中的 dependencyManagement 是允许被子模块的 dependencyManagement 覆盖的。

沿着树向上层 pom 查找最近的 dependencyManagement 声明的 groupId 和 artifactId。这也就说明了如果子类 dependencyManagement 声明了与父 dependencyManagement 相同的 groupId 和 artifactId,则以最近的为准。如果层次相同,则先声明的优先级更高。

因此,结合 dependencies 来看:

1.dependencies 优先级高于 dependencyManagement。

2.在依赖树上,离引入位置越近的层次,则优先级越高。

3.层次相同,则先声明的优先级更高。