1. 概述

Maven 是 Java 生态中最流行的构建工具之一,其核心特性之一就是依赖管理。本文将深入探讨 Maven 项目中管理传递性依赖的关键机制——依赖范围(Dependency Scopes)

2. 传递性依赖

Maven 中的依赖分为两类:

  • 直接依赖:项目中显式声明的依赖
  • 传递性依赖:被直接依赖所需的其他依赖

直接依赖通过 <dependency> 标签声明:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>

而传递性依赖由 Maven 自动引入。使用 mvn dependency:tree 命令可查看完整依赖树(含传递依赖)。

3. 依赖范围

依赖范围能限制依赖的传递性,并影响不同构建任务的类路径。Maven 提供了 6 种默认依赖范围,除 import 外均会影响传递性依赖。

3.1. compile

默认范围(未指定范围时生效)。特点: ✅ 所有构建任务都可用
✅ 会传递给依赖项目
✅ 具有传递性

示例:

<dependency> 
    <groupId>org.apache.commons</groupId> 
    <artifactId>commons-lang3</artifactId> 
    <version>3.14.0</version> 
</dependency>

3.2. provided

标记由 JDK 或容器在运行时提供的依赖。典型场景:

  • Web 应用部署到 Servlet 容器(如 Tomcat)
  • 容器已提供 Servlet API 等库

特点: ⚠️ 仅编译和测试类路径可用
❌ 不具有传递性

示例:

<dependency>
    <groupId>jakarta.servlet</groupId>
    <artifactId>jakarta.servlet-api</artifactId>
    <version>6.0.0</version>
    <scope>provided</scope>
</dependency>

3.3. runtime

运行时必需但编译时不需要的依赖。特点: ✅ 运行时和测试类路径可用
❌ 编译类路径不可用
✅ 具有传递性

典型场景:JDBC 驱动

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
    <scope>runtime</scope>
</dependency>

3.4. test

仅用于测试的依赖。特点: ⚠️ 仅测试和执行类路径可用
❌ 不具有传递性

典型场景:JUnit 等测试框架

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
    <scope>test</scope>
</dependency>

3.5. system

与 provided 类似,但需显式指定本地 JAR 路径。⚠️ 已废弃,谨慎使用!

特点: ⚠️ 依赖本地文件系统路径
❌ 跨机器构建可能失败

示例:

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>custom-dependency</artifactId>
    <version>1.3.2</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/libs/custom-dependency-1.3.2.jar</systemPath>
</dependency>

3.6. import

仅适用于 pom 类型的依赖。作用: ✅ 将目标 POM 的 <dependencyManagement> 依赖导入当前项目

示例:

<dependency>
    <groupId>com.baeldung</groupId>
    <artifactId>custom-project</artifactId>
    <version>1.3.2</version>
    <type>pom</type>
    <scope>import</scope>
</dependency>

4. 范围与传递性

不同范围对传递性依赖的影响规则如下(providedtest 范围的依赖不会传递到主项目):

当前范围 传递依赖范围 项目中实际范围
compile compile compile
compile runtime runtime
provided compile/runtime provided
test compile/runtime test
runtime compile/runtime runtime

简单粗暴记忆法:

  • compile 范围会保留原传递依赖的范围
  • provided/test 范围会"传染"给所有传递依赖
  • runtime 范围会将所有传递依赖降级为 runtime

5. 总结

Maven 依赖范围是控制依赖传递性和类路径的核心机制。合理使用范围可以: ✅ 避免依赖冲突
✅ 优化构建性能
✅ 明确依赖边界

想深入理解?官方文档是最佳起点:Maven 依赖机制


原始标题:Maven Dependency Scopes