Maven - 管理依赖

Maven 一个核心的特性就是依赖管理。当我们不得不出来多模块的项目(包含成百个模块或者子项目),管理依赖就变成一项困难的任务。Maven 展示出了它对处理这种情形的高度控制。

可传递性依赖发现

一种相当常见的情况,当一个库,比如说 A 依赖于其他库 B。假如,另外一个项目 C 想要使用 A ,那么项目也需要使用库 B。

Maven 帮助避免这种要查明所有所需库的要求。Maven 通过读取描述依赖的项目文件(pom.xml),找出它们的依赖诸如此类,来完成这项工作。

我们只需要做的是在每个项目的 pom 中定义好直接的依赖。Maven 会自动处理剩下的事情。

通过可传递性的依赖,被包含库的关系图可以迅速增加到一个很大的程度。当有多个库时可能就会有状况发生。Maven 提供一些特性来控制可传递性依赖的大小。

特性 描述
依赖调解(Dependency mediation) 当遇到多个版本的 artifact 的时候,决定使用那个版本的依赖。如果两个版本的依赖在依赖树种处于同一深度时,第一个被声明的依赖将被使用。
依赖管理(Dependency management) 当在传递性依赖中遇到时,直接指定要使用的构件版本。举个例子,项目 C 可以在 dependencyManagement 部分配置包含 B 作为依赖,并且直接控制引用 B时使用那个版本的 B。
依赖作用域(Dependency scope) 按照当前构建的阶段,配置包含的依赖。
排除依赖(Excluded dependencies) 任何传递性的依赖都可以通过使用“exclusion”节点来排除。举个例子,A 依赖于 B 并且 B 依赖于 C, 那么 A 可以标记 C 为排除在外的。
可选依赖(Optional dependencies) 任何传递性的依赖都可以通过使用“optional”节点来标记为可选的。举个例子,A 依赖于 B 并且 B 依赖于 C, 现在 B 标记 C 为可选的,那么 A 可以不使用 C。

依赖作用域(Dependency Scope)

可传递性依赖发现可以通过下面提到的各种依赖作用域来限制。

作用域(Scope) 描述
compile 此作用域表示项目 classpath 中的依赖可以使用,为默认作用域。
provided 此作用域表示依赖将由 JDK 或者 运行时的Web 服务器或容器提供。
runtime 此作用域表示依赖在编译时不需要,但在执行时需要。
test 此作用域表示依赖只在测试编译和执行阶段可用。
system 此作用域表示你必须提供系统路径。
import 此作用域只在依赖是 pom 类型时使用。此作用域表示特定的 POM 需要替换成被引入的 POM 的 部分中的依赖。

依赖管理(Dependency Management)

通常我们有基于某个通用项目的一组项目。 在此情形下, 我们可以创建一个通用的 pom 来把所有的通用的依赖包含进来,并把这个 pom 作为子项目 pom 的父 pom。下面的例子将帮助你理解这个概念。

dependency graph

接下来是上面依赖图的详情说明:

  • App-UI-WAR 依赖于 App-Core-lib 和 App-Data-lib。

  • Root 是 App-Core-lib 和 App-Data-lib 的父项目。

  • Root 在它的依赖部分定义了 Lib1、lib2 和 Lib3 作为依赖。

App-UI-WAR

<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
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.companyname.groupname</groupId>
      <artifactId>App-UI-WAR</artifactId>
      <version>1.0</version>
      <packaging>war</packaging>
      <dependencies>
         <dependency>
            <groupId>com.companyname.groupname</groupId>
            <artifactId>App-Core-lib</artifactId>
            <version>1.0</version>
         </dependency>
      </dependencies>  
      <dependencies>
         <dependency>
            <groupId>com.companyname.groupname</groupId>
            <artifactId>App-Data-lib</artifactId>
            <version>1.0</version>
         </dependency>
      </dependencies>  
</project>

App-Core-lib

<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
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <parent>
         <artifactId>Root</artifactId>
         <groupId>com.companyname.groupname</groupId>
         <version>1.0</version>
      </parent>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.companyname.groupname</groupId>
      <artifactId>App-Core-lib</artifactId>
      <version>1.0</version> 
      <packaging>jar</packaging>
</project>

App-Data-lib

<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
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <parent>
         <artifactId>Root</artifactId>
         <groupId>com.companyname.groupname</groupId>
         <version>1.0</version>
      </parent>
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.companyname.groupname</groupId>
      <artifactId>App-Data-lib</artifactId>
      <version>1.0</version>   
      <packaging>jar</packaging>
</project>

Root

<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
   http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>com.companyname.groupname</groupId>
      <artifactId>Root</artifactId>
      <version>1.0</version>
      <packaging>pom</packaging>
      <dependencies>
         <dependency>
            <groupId>com.companyname.groupname1</groupId>
            <artifactId>Lib1</artifactId>
            <version>1.0</version>
         </dependency>
      </dependencies>  
      <dependencies>
         <dependency>
            <groupId>com.companyname.groupname2</groupId>
            <artifactId>Lib2</artifactId>
            <version>2.1</version>
         </dependency>
      </dependencies>  
      <dependencies>
         <dependency>
            <groupId>com.companyname.groupname3</groupId>
            <artifactId>Lib3</artifactId>
            <version>1.1</version>
         </dependency>
      </dependencies>  
</project>

现在当我们构建 App-UI-WAR 项目时, Maven 将通过遍历依赖关系图发现所有的依赖,并且构建此应用。

从上面的例子,我们可以学习到下面的几个关键概念:

  • 通用依赖可以使用父 pom 的概念放置在单独的地方。App-Data-libApp-Core-lib 项目的依赖是在 Root 项目中列出的(参见 Root 的打包类型,是 POM)。

  • 在 App-UI-WAR 项目中不需要指定 Lib1、 lib2 和 Lib3 作为依赖。Maven 使用 可传递性依赖机制(Transitive Dependency Mechanism) 可处理这种细节。

results matching ""

    No results matching ""