Maven 依赖的 Scope 元素

原文(简单修改):Maven 依赖中的 Scope 详解

scope 元素的作用:控制 dependency 元素的使用范围。通俗的讲,就是控制 jar 包在哪些范围被加载和使用。

compile(默认)

compile 是默认值,如果没有指定 scope 值,该依赖的 scope 为 compile。被依赖项目需要参与到当前项目的编译,测试,打包,运行等阶段。打包的时候通常会包含被依赖项目。

provided

被依赖项目理论上可以参与编译、测试、运行等阶段,相当于 compile,但是再打包阶段做了 exclude 的动作。

适用场景:例如,如果我们在开发一个 web 应用,在编译时我们需要依赖 servlet-api.jar,但是在运行时我们不需要该 jar 包,因为这个 jar 包已由应用服务器提供,此时我们需要使用 provided 进行范围修饰。再比如,Lombok 的作用是在编译阶段处理编译结果,而在正式编译完成之后,是不需要 Lombok 的,所以 Lombok 的 scope 为 provided。

runtime

表示被依赖项目无需参与项目的编译,但是会参与到项目的测试和运行。与 compile 相比,被依赖项目无需参与项目的编译。

适用场景:例如,在编译的时候我们只需要 JDBC API 的 jar 包,而在运行的时候我们才需要 JDBC 驱动包,所以 MySQL 等数据库供应商提供的驱动包的 scope 为 provided。

test

表示被依赖项目仅仅参与测试相关的工作,包括测试代码的编译,执行。

适用场景:例如,Junit 测试。

system

system 元素与 provided 元素类似,但是被依赖项不会从 maven 仓库中查找,而是从本地系统中获取,systemPath 元素用于制定本地系统中 jar 文件的路径。例如:

<dependency>
    <groupId>org.open</groupId>
    <artifactId>open-core</artifactId>
    <version>1.5</version>
    <scope>system</scope>
    <systemPath>${basedir}/WebContent/WEB-INF/lib/open-core.jar</systemPath>
</dependency>

import

它只使用在<dependencyManagement>中,表示从其它的 pom 中导入 dependency 的配置。

在 SpringBoot 项目中,常会看到如下 pom 内容:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.6.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
 
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
</dependencies>

其中spring-boot-dependencies是用来做依赖版本管理的。这里 import scope 的作用是,把spring-boot-dependencies中的内容导入到dependencyManagement中。实际上我们可以自己在dependencyManagement中做依赖版本管理:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.16</version>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
    </dependency>
</dependencies>

但是spring-boot-dependencies已经把 SpringBoot 相关的许多依赖版本管理好了,所以,我们直接导入即可。

scope 的依赖传递

A–>B–>C。当前项目为 A,A 依赖于 B,B 依赖于 C。知道 B 在 A 项目中的 scope,那么怎么知道 C 在 A 中的 scope 呢?答案是:

当 C 是 test 或者 provided 时,C 直接被丢弃,A 不依赖 C;否则 A 依赖 C,C 的 scope 继承于 B 的 scope。

  • testprovided的处理

    • test:C 只在测试阶段可用,A 在其运行时不需要 C,因此 C 被丢弃。
    • provided:C 由外部环境提供(例如,容器或应用服务器),A 也不需要 C,因此 C 被丢弃。
  • 范围继承

    • 当 C 的范围是compileruntime时,A 依赖于 C,并且 C 的范围会继承 B 的范围。这意味着:

      • 如果 B 的范围是compile,则 C 的范围也是compile
      • 如果 B 的范围是runtime,则 C 的范围也是runtime
      • 如果 B 的范围是test,则 C 的范围是test
posted @ 2024-11-30 11:08  Higurashi-kagome  阅读(12)  评论(0编辑  收藏  举报