当使用了传递依赖,也就是使用了没有显示声明的依赖时,如果继承的<dependencyManagement/>中声明了使用的传递依赖的版本,那么最终使用的依赖是<dependencyManagement/>中声明的版本。

Spring举一个栗子:

1.mvn dependency:tree

先看下项目依赖的基础组件使用的Spring版本。

maven不同环境依赖不同jar包版本号 maven传递依赖不同版本_Management

可以看到基础组件使用的Spring版本为3.1.3,不能lambda表达式(被坑过)。

 

2.mvn dependency:analyze

接下来分析下依赖,关注Spring的相关依赖。

maven不同环境依赖不同jar包版本号 maven传递依赖不同版本_Management_02

可以看到Spring作为传递依赖使用,版本是基础组件使用的版本3.1.3

 

3.parent module

然后在项目的parent module<dependencyManagement/>加入一个spring-framework-bom来管理Spring的版本。

maven不同环境依赖不同jar包版本号 maven传递依赖不同版本_ci_03

${springframework.version}5.0.4.RELEASE

 

4.重新执行mvn dependency:tree

maven不同环境依赖不同jar包版本号 maven传递依赖不同版本_ci_04

可以看到Spring的版本变为了5.0.4.RELEASE

maven不同环境依赖不同jar包版本号 maven传递依赖不同版本_ci_05

在执行mvn dependency:analyze后看到使用的Spring版本也变成了5.0.4.RELEASE

 

5.文档

  • Dependency management - this allows project authors to directly specify the versions of artifacts to be used when they are encountered in transitive dependencies or in dependencies where no version has been specified. In the example in the preceding section a dependency was directly added to A even though it is not directly used by A. Instead, A can include D as a dependency in its dependencyManagement section and directly control which version of D is used when, or if, it is ever referenced.

 

文档连接:maven.apache.org/guides/intr… 作者:虎纹咸鱼
链接:
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

 

 

Maven 父pom中dependencyManagement版本优先级高于传递依赖版本
直接上例子:

父pom

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
</dependencyManagement>

该工程beanutils将会传递依赖logging 1.1.1

<dependency>
    <groupId>commons-beanutils</groupId>
    <artifactId>commons-beanutils</artifactId>
    <version>1.9.2</version>
</dependency>

此时该工程中logging的版本将是1.2,即父pom dependencyManagement中的版本

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

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。

可以看到,只有通过 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>

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

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

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

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

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

依赖优先级
父 pom 中的 dependencyManagement 是允许被子模块的 dependencyManagement 覆盖的。

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

因此,结合 dependencies 来看:

1.dependencies 优先级高于 dependencyManagement。

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

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