前言

当前的团队工程项目是一个 maven 工程,里面有多模块,包含了父 pom 与子 pom。而在父 pom 中,我见到了 dependencyManagement 这个东西。我们知道一个 maven 工程肯定少不了与各种依赖的 jar 包打交道,pom 中的 dependencies 就是用来对项目的依赖进行配置和管理。那么 dependencyManagement 和 dependencies 有什么区别呢?本文对此进行了简单的介绍。

 

dependencies

先来说说 dependencies。这个大家应该都非常熟悉,它是用来放置各种依赖配置的地方。dependencies 中存放了多个 dependency,代表着多个 jar 包,就像下面这样:

<dependencies>
<dependency>
<groupId>com.san.trip</groupId>
<artifactId>message</artifactId>
<version>1.4.0-SNAPSHOT</version>
</dependency>
</dependencies>

另外,在多模块工程中,可能会有一个父 pom 与多个子 pom。这时候,如果在父 pom 中定义了某个依赖,那么所有子 pom 都会自动继承这个依赖。例如:

<!-- 父 pom -->
<dependencies>
<dependency>
<groupId>com.san.trip</groupId>
<artifactId>message</artifactId>
<version>1.4.0-SNAPSHOT</version>
</dependency>
</dependencies>

<!-- 子 pom -->
<!-- 默认继承,也可以使用其他版本覆盖 -->

子模块中的 pom 可以什么都不做,就会默认从父 pom 中继承所有的依赖。另外子模块也可以使用不同版本的依赖进行覆盖。

 

dependencyManagement

上面的依赖继承中,父 pom 中定义的依赖,可以直接被子 pom 继承,子 pom 中不用再次声明。这听起来不错,但是仔细想想还是有一些不好的地方:

  • 父 pom 定义的依赖,会被所有模块继承。即使有的模块可能根本不需要这个依赖,这就导致打包后的 jar 臃肿,甚至产生 jar 冲突的问题。
  • 子模块的 pom 中可以覆盖继承的依赖,这可能导致依赖版本管理出现混乱。

而使用 dependencyManagement 的话,便可以很好的解决上面两个问题:

  • dependencyManagement 中声明的依赖,仅仅是声明,并没有真正的引入依赖。这样子模块可以从声明的依赖中,选择自己需要的,而不会继承所有父 pom 中的依赖。
  • dependencyManagement 中除了声明依赖,还指定了依赖的版本。这样在子模块的依赖中,就无须指定版本,而是使用 dependencyManagement 指定的版本。

dependencyManagement 往往定义在父 pom 中,其使用方式与 dependencies 很像:

</dependencyManagement>
</dependencies>
<dependency>
<groupId>com.san.trip</groupId>
<artifactId>message</artifactId>
<version>1.4.0-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>

然而这里不同的地方在于,这里仅仅是对依赖进行了声明,并没有实际的引入这个依赖。假如这时候我们在 IDE 中观察项目依赖的 jar 包,可以发现并没有这个包。此时我们可以通过在子 pom 中再次加入这个依赖,才会真正的引入。

举例来说。假如一个多模块工程,模块 A 需要依赖 dependencyA,模块 B 需要 dependencyB,那么使用 dependencyManagement 来管理的化,最终各自的 pom 可以是下面这样:

<!-- 父 pom -->
</dependencyManagement>
</dependencies>
<dependency>
<groupId>x.xx.xxx</groupId>
<artifactId>xxx.A</artifactId>
<version>A.version</version>
</dependency>
</dependencies>
</dependencies>
<dependency>
<groupId>x.xx.xxx</groupId>
<artifactId>xxx.B</artifactId>
<version>B.version</version>
</dependency>
</dependencies>
</dependencyManagement>

<!-- 子模块 A pom -->
<dependencies>
<dependency>
<groupId>x.xx.xxx</groupId>
<artifactId>xxx.A</artifactId>
<!-- 版本自动继承 A.version -->
</dependency>
</dependencies>

<!-- 子模块 B pom -->
<dependencies>
<dependency>
<groupId>x.xx.xxx</groupId>
<artifactId>xxx.B</artifactId>
<!-- 版本自动继承 B.version -->
</dependency>
</dependencies>

通过这个例子大概就能理解了,也就是说 dependencyManagement 并没有真正的引入依赖,而是对依赖以及依赖的版本进行了声明;这样在子模块中,可以各取所需,使用需要的依赖,同时无需指定版本,因为版本已经在 dependencyManagement 指定好了。这样既可以避免版本混乱的问题,又可以避免子模块中引入多余无效的依赖。

 

区别总结

最后再来总结一下 dependencyManagement 与 dependencies 的区别:

dependencyMent

dependencies

使用位置

通常是父 pom。

父 pom 与子 pom。

版本

定义版本,子模块继承时无需指定版本,避免版本混乱。当然也可以使用别的版本进行覆盖,不过一般不这么用。

子模块可以什么也不做来继承父 pom 的依赖,也可以使用别的版本的依赖进行覆盖。

继承方式

子模块需要在自己的 dependencies 中指定要继承哪些依赖。

子模块什么都不做即可默认继承。

是否被子模块继承

可以被子模块选择性的继承,避免无效继承。

所有父 pom 中定义的依赖会被所有子模块继承。

是否引入依赖

只是声明,没有引入依赖,只有在子模块中继承才会真正的引入依赖。

是。

 

参考资料