Maven 简明教程

Maven - Manage Dependencies

Maven 的核心功能之一是依赖项管理。一旦我们开始处理多模块项目(包含数百个模块/子项目),那么管理依赖项就会成为一项困难的任务。Maven 提供了高度的控制来管理此类场景。

One of the core features of Maven is Dependency Management. Managing dependencies is a difficult task once we’ve to deal with multi-module projects (consisting of hundreds of modules/sub-projects). Maven provides a high degree of control to manage such scenarios.

Transitive Dependencies Discovery

通常一种情况是,一个库(例如 A)依赖于另一个库(例如 B)。如果另一个项目 C 要使用 A,那么该项目需要使用库 B。

It is pretty often a case, when a library, say A, depends upon other library, say B. In case another project C wants to use A, then that project requires to use library B too.

Maven 帮助避免此类要求以发现所有必需的库。Maven 通过读取依赖项的项目文件 (pom.xml)、找出它们的依赖项等来做到这一点。

Maven helps to avoid such requirements to discover all the libraries required. Maven does so by reading project files (pom.xml) of dependencies, figure out their dependencies and so on.

我们只需要在每个项目 pom 中定义直接依赖。Maven 会自动处理其余部分。

We only need to define direct dependency in each project pom. Maven handles the rest automatically.

使用传递依赖项,包含的库的图形可能会迅速增长到很大程度。当出现重复库时,可能会出现这种情况。Maven 提供了一些功能来控制传递依赖项的范围。

With transitive dependencies, the graph of included libraries can quickly grow to a large extent. Cases can arise when there are duplicate libraries. Maven provides few features to control extent of transitive dependencies.

Sr.No.

Feature & Description

1

Dependency mediation Determines what version of a dependency is to be used when multiple versions of an artifact are encountered. If two dependency versions are at the same depth in the dependency tree, the first declared dependency will be used.

2

Dependency management Directly specify the versions of artifacts to be used when they are encountered in transitive dependencies. For an example project C can include B as a dependency in its dependency Management section and directly control which version of B is to be used when it is ever referenced.

3

Dependency scope Includes dependencies as per the current stage of the build.

4

Excluded dependencies Any transitive dependency can be excluded using "exclusion" element. As example, A depends upon B and B depends upon C, then A can mark C as excluded.

5

Optional dependencies Any transitive dependency can be marked as optional using "optional" element. As example, A depends upon B and B depends upon C. Now B marked C as optional. Then A will not use C.

Dependency Scope

可以使用各种依赖项范围来限制传递依赖项发现,如下所述。

Transitive Dependencies Discovery can be restricted using various Dependency Scope as mentioned below.

Sr.No.

Scope & Description

1

compile This scope indicates that dependency is available in classpath of project. It is default scope.

2

provided This scope indicates that dependency is to be provided by JDK or web-Server/Container at runtime.

3

runtime This scope indicates that dependency is not required for compilation, but is required during execution.

4

test This scope indicates that the dependency is only available for the test compilation and execution phases.

5

system This scope indicates that you have to provide the system path.

6

import This scope is only used when dependency is of type pom. This scope indicates that the specified POM should be replaced with the dependencies in that POM’s <dependencyManagement> section.

Dependency Management

通常,在通用项目下,我们有一组项目。在这种情况下,我们可以创建一个具有所有通用依赖项的通用 pom,然后将此 pom 设为子项目 pom 的父级。下面的示例将帮助你理解此概念。

Usually, we have a set of project under a common project. In such case, we can create a common pom having all the common dependencies and then make this pom, the parent of sub-project’s poms. Following example will help you understand this concept.

dependency graph

以下是上述依赖项关系图的详细信息 -

Following are the detail of the above dependency graph −

  1. App-UI-WAR depends upon App-Core-lib and App-Data-lib.

  2. Root is parent of App-Core-lib and App-Data-lib.

  3. Root defines Lib1, lib2, Lib3 as dependencies in its dependency section.

App-UI-WAR

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

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

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

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 将通过遍历依赖项关系图来发现所有依赖项,并构建应用程序。

Now when we build App-UI-WAR project, Maven will discover all the dependencies by traversing the dependency graph and build the application.

从以上示例中,我们可以了解以下关键概念 -

From above example, we can learn the following key concepts −

  1. Common dependencies can be placed at single place using concept of parent pom. Dependencies of App-Data-lib and App-Core-lib project are listed in Root project (See the packaging type of Root. It is POM).

  2. There is no need to specify Lib1, lib2, Lib3 as dependency in App-UI-WAR. Maven use the Transitive Dependency Mechanism to manage such detail.