dependencyManagement:管理Maven依赖

我们知道,子模块可以通过继承获得父模块中声明的全部依赖,这样虽然避免了在各个子模块POM中重复进行依赖声明,但也极有可能造成子模块中引入一些不必要的依赖。为此Maven引入了dependencyManagement来对依赖进行管理。

依赖管理

Maven可以通过dependencyManagement元素对依赖进行管理,它具有以下2大特性:

在该元素下声明的依赖不会实际引入到模块中,只有在dependencies元素下同样声明了该依赖,才会引入到模块中。

该元素能够约束dependencies下依赖的使用,即dependencies声明的依赖若未指定版本,则使用dependencyManagement中指定的版本,否则将覆盖dependencyManagement中的版本。

例如,修改App-Data-lib模块的pom.xml如下。

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <!--由于不是继承,所以必须重新添加 groupId 和 version-->
 <groupId>net.biancheng.www</groupId>
 <artifactId>App-Data-lib</artifactId>
 <version>1.0</version>
 <!--dependencyManagement 标签用于控制子模块的依赖版本等信息 -->
 <!-- 该标签只用来控制版本,不能将依赖引入 -->
 <dependencyManagement>
  <dependencies>
   <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <!--引用的properties标签中定义的属性 -->
 <version>1.2.17</version>
   </dependency>
   <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <!--引用的properties标签中定义的属性 -->
 <version>4.9</version>
 <!-- <scope>test</scope> -->
   </dependency>
   <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <!--引用的properties标签中定义的属性 -->
 <version>5.1.18</version>
 <scope>runtime</scope>
   </dependency>
   <dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <!--引用的properties标签中定义的属性 -->
 <version>0.9.1</version>
   </dependency>
  </dependencies>
 </dependencyManagement>
 <!--声明依赖-->
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
  </dependency>
 </dependencies>
</project>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748复制代码类型:[java]

在以上配置中,由于dependencyManagement元素中已经定义完整的依赖声明,所以在dependencies元素中声明的依赖只配置了groupId和artifactId,省略了version和scope。

在实际的开发过程中,dependencyManagement很少会单独使用,通常它需要与Maven继承或依赖范围import配合使用才能展现它的优势。

继承依赖管理

由于dependencyManagement元素是可以被继承的,因此我们可以在父模块POM中使用dependencyManagement元素声明所有子模块的依赖,然后在各个子模块POM使用dependencies元素声明实际用到的依赖即可。这样既可以让子模块能够继承父模块的依赖配置,还能避免将不必要的依赖引入到子模块中。

1.修改父模块Root的pom.xml如下。

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>net.biancheng.www</groupId>
 <artifactId>Root</artifactId>
 <version>1.0</version>
 <!--定义的父类pom.xml 打包类型使pom -->
 <packaging>pom</packaging>
 <properties>
  <!-- 定义一些 maven 变量 -->
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <log4j.version>1.2.17</log4j.version>
  <junit.version>4.9</junit.version>
  <system.version>1.0</system.version>
  <mysql.connector.version>5.1.18</mysql.connector.version>
  <c3p0.version>0.9.1</c3p0.version>
 </properties>
 <!--dependencyManagement 标签用于控制子模块的依赖版本等信息 -->
 <!-- 该标签只用来控制版本,不能将依赖引入 -->
 <dependencyManagement>
  <dependencies>
   <dependency>
 <groupId>log4j</groupId>
 <artifactId>log4j</artifactId>
 <!--引用的properties标签中定义的变量 -->
 <version>${log4j.version}</version>
   </dependency>
   <dependency>
 <groupId>junit</groupId>
 <artifactId>junit</artifactId>
 <!--引用的properties标签中定义的变量 -->
 <version>${junit.version}</version>
 <!-- <scope>test</scope> -->
   </dependency>
   <dependency>
 <groupId>mysql</groupId>
 <artifactId>mysql-connector-java</artifactId>
 <!--引用的properties标签中定义的变量 -->
 <version>${mysql.connector.version}</version>
 <scope>runtime</scope>
   </dependency>
   <dependency>
 <groupId>c3p0</groupId>
 <artifactId>c3p0</artifactId>
 <!--引用的properties标签中定义的变量 -->
 <version>${c3p0.version}</version>
   </dependency>
  </dependencies>
 </dependencyManagement>
</project>123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051复制代码类型:[java]

注:以上配置中,将所有依赖的版本信息以Maven变量(properties)的形式提取出来,这样不仅消除了一些重复,也使得各个依赖的版本信息更加明显,便于管理。

在父模块Root中使用dependencyManagement元素声明的依赖,既不会给Root模块引入依赖,也不会给其子模块引入依赖,但这段配置是可以被继承的。

2.修改子模块App-Core-lib的pom.xml如下。

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <artifactId>App-Core-lib</artifactId>
 <parent>
  <groupId>net.biancheng.www</groupId>
  <artifactId>Root</artifactId>
  <version>1.0</version>
  <relativePath>../Root</relativePath>
 </parent>
 <dependencies>
  <dependency>
   <groupId>log4j</groupId>
   <artifactId>log4j</artifactId>
  </dependency>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
  </dependency>
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <dependency>
   <groupId>c3p0</groupId>
   <artifactId>c3p0</artifactId>
  </dependency>
 </dependencies>
 <distributionManagement>
  <repository>
   <id>bianchengbang_Release_hosted</id>
   <url>http://localhost:8082/nexus/content/repositories/bianchengbang_Release_hosted/</url>
  </repository>
  <snapshotRepository>
   <id>Snapshot</id>
   <url>http://localhost:8082/nexus/content/repositories/bianchengbang_Snapshot_hosted/</url>
  </snapshotRepository>
 </distributionManagement>
</project>12345678910111213141516171819202122232425262728293031323334353637383940复制代码类型:[java]

3.修改子模块App-Data-lib的pom.xml如下。

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <artifactId>App-Data-lib</artifactId>
 <parent>
  <groupId>net.biancheng.www</groupId>
  <artifactId>Root</artifactId>
  <version>1.0</version>
 </parent>

 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
  </dependency>
 </dependencies>
</project>123456789101112131415161718复制代码类型:[java]

在子模块App-Core-lib和App-Data-lib的POM中,所有在dependencies元素中声明的依赖都只配置了groupId和artifactId,省去了version和scope。之所以能够省略这些信息,是因为它们继承了父模块Root中dependencyManagement的配置,其完整的依赖声明已经包含在父模块的POM中,子模块只需要配置groupId和artifactId就能获得相应的依赖信息,从而引入正确的依赖。

使用这种依赖管理机制似乎并不能减少太多POM配置,但我们仍然推荐使用这种方式,其原因主要有2个:

在父模块中使用dependencyManagement声明依赖能够统一项目内依赖的版本,子模块无须声明版本,也就不会出现多个子模块使用同一依赖项版本不一致的情况,降低依赖冲突的几率。

dependencyManagement声明的依赖不会被实际引入,子模块需要什么依赖就自己引入,增加了灵活性,避免引入一些不必要的依赖。

导入依赖管理

在Maven依赖传递一节介绍依赖范围时,提到了一个名为import的依赖范围,之所以要放在这介绍是因为import依赖范围只能与dependencyManagement元素配合使用才会有效,其功能是将目标pom.xml中的dependencyManagement配置导入合并到当前pom.xml的dependencyManagement中。

例如,App-Data-lib模块想要使用Root模块中的dependencyManagement配置,除了通过继承或者直接复制这两种方式之外,还可以使用import依赖范围将其导入,具体配置如下。

<project xmlns="http://maven.apache.org/POM/4.0.0"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <!--由于不是继承,所以必须重新添加 groupId 和 version-->
 <groupId>net.biancheng.www</groupId>
 <artifactId>App-Data-lib</artifactId>
 <version>1.0</version>
 <!--定义依赖管理-->
 <dependencyManagement>
  <dependencies>
   <!--导入依赖管理配置-->
   <dependency>
 <groupId>net.biancheng.www</groupId>
 <artifactId>Root</artifactId>
 <version>1.0</version>
 <!--依赖范围为 import-->
 <scope>import</scope>
 <!--类型一般为pom-->
 <type>pom</type>
   </dependency>
  </dependencies>
 </dependencyManagement>
 <!--声明依赖-->
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
  </dependency>
 </dependencies>
</project>12345678910111213141516171819202122232425262728293031复制代码类型:[java]

以上配置中,由于import依赖范围的特殊性,一般都是指向打包类型为pom的模块,所以type元素的值一般为pom。

若存在多个模块,它们使用的依赖版本都是一致的,则就可以定义一个使用dependencyManagement专门管理依赖的POM,然后在各个模块中导入这些依赖管理配置。

(0)

相关推荐