「M4」- 概念术语:依赖(dependency)

依赖范围(scope)

编译、测试、运行,在这三个阶段中,会使用不同的 classpath,而 Scope 则用于控制依赖与这三种 classpath 的关系;

Maven 具有如下几种 Scope:

compile:编译依赖范围。如果没有指定,就会默认使用该依赖范围。使用此依赖范围的 Maven 依赖,对于编译、测试、运行三种 classpath 都有效;
例如 spring-core,在编译 、测试、运行的时候都需要使用该依赖;

test:测试依赖范围。使用此依赖范围的 Maven 依赖,只对于测试 classpath 有效,在编译主代码或者运行项目的使用时将无法使用此类依赖;
例如 JUnit,它只有在编译测试代码及运行测试的时候才需要;

provided:已提供依赖范围。使用此依赖范围的 Maven 依赖,对于编译和测试 classpath 有效,但在运行时无效;
例如 servlet-api,编译和测试项目的时候需要该依赖,但在运行项目的时候,由于容器已经提供,就不需要 Maven 重复引入;

runtime:运行时依赖范围。使用此依赖范围的 Maven 依赖,对于测试和运行 classpath 有效,但在编译主代码时无效;
例如 JDBC 驱动实现,项目主代码的编译只需要 JDK 提供的 JDBC 接口,只有在执行测试或运行项目的时候才需要实现上述接口的具体 JDBC 驱动;

system:系统依赖范围。该依赖与三种 classpath 的关系,和 provided 依赖范围完全一致. 但是,使用 system 范围的依赖时必须通过 systemPath 元素显式地指定依赖文件的路径。 由于此类依赖不是通过 Maven 仓库解析的,而且往往与本机系统绑定,可能造成构建的不可移植因此应该谨慎使用。systemPath 元素可以引用环境变量;

import ( Maven 2. 0.9 及以上):导入依赖范围。该依赖范围不会对三种 classpath 产生实际的影响;

依赖传递

假设 A 依赖于 B,B 依赖于 C,我们说 A 对于 B 是第一直接依赖,B 对于 C 是第二直接依赖,A 对于 C 是传递性依赖。

Scope

第一直接依赖的范围和第二直接依赖的范围决定了传递性依赖的范围。即 C 的 Scope 由 A B 的 Scope 决定;

Maven – Introduction to the Dependency Mechanism

依赖调节

当依赖出现冲突时
1)最优路径优先:即传递的层次少,即最先出现的依赖;
2)第一声明优先:即最先定义的依赖;

可选依赖(optional)

optional:标记该依赖是否为可选依赖;

X -> Y -> Z(optional),此时 X 将不会得到 Z,但是 X 可以在依赖中显式声明 Z;

将可选依赖理解为”默认排除“即可;

依赖排除(exclusion)

exclusions:其用于排除某个传递依赖;

应用场景:排除某个传递依赖;替换传递依赖;

替换传递依赖:

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>group-a</groupId>
      <artifactId>artifact-a</artifactId>
      <version>1.0</version>
      <exclusions>
        <exclusion>
          <groupId>group-c</groupId>
          <artifactId>excluded-artifact</artifactId>
          <version>0.9</version>
        </exclusion>
      </exclusions>
    </dependency>
    <dependency>
      <groupId>group-a</groupId>
      <artifactId>excluded-artifact</artifactId>
      <version>1.0</version>
      <type>bar</type>
      <scope>runtime</scope>
    </dependency>
  </dependencies>
</project>

归类依赖

其指通过变量的方式来定义依赖,然后引用变量,以便于管理;

通过变量来统一版本字段的定义,以实现统一版本管理:

<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.test</groupId>
  <artifactId>bom</artifactId>
  <version>1.0.0</version>
  <packaging>pom</packaging>
  <properties>
    <project1Version>1.0.0</project1Version>
    <project2Version>1.0.0</project2Version>
  </properties>
 
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>com.test</groupId>
        <artifactId>project1</artifactId>
        <version>${project1Version}</version>
      </dependency>
      <dependency>
        <groupId>com.test</groupId>
        <artifactId>project2</artifactId>
        <version>${project2Version}</version>
      </dependency>
    </dependencies>
  </dependencyManagement>
 
  <modules>
    <module>parent</module>
  </modules>
</project>

优化依赖

# mvn dependency:analyze
... Used undeclared dependencies:传递性依赖,而非直接声明;
... Unused declared dependencies:未使用的依赖;其也有可能是动态加载的依赖;

# mvn dependency:tree
# mvn dependency:tree