关于程序员:Maven依赖中的Scope详解

62次阅读

共计 3120 个字符,预计需要花费 8 分钟才能阅读完成。

scope 元素的作用 :管制 dependency 元素的应用范畴。艰深的讲,就是管制 Jar 包在哪些范畴被加载和应用。
scope 具体含意如下:

compile(默认)

含意:compile 是默认值,如果没有指定 scope 值,该元素的默认值为 compile。被依赖我的项目须要参加到以后我的项目的编译,测试,打包,运行等阶段。打包的时候通常会蕴含被依赖我的项目。

provided

含意:被依赖我的项目实践上能够参加编译、测试、运行等阶段,相当于 compile,然而再打包阶段做了 exclude 的动作。
实用场景:例如,如果咱们在开发一个 web 利用,在编译时咱们须要依赖 servlet-api.jar,然而在运行时咱们不须要该 jar 包,因为这个 jar 包已由应用服务器提供,此时咱们须要应用 provided 进行范畴润饰。

runtime

含意:示意被依赖我的项目无需参加我的项目的编译,然而会参加到我的项目的测试和运行。与 compile 相比,被依赖我的项目无需参加我的项目的编译。
实用场景:例如,在编译的时候咱们不须要 JDBC API 的 jar 包,而在运行的时候咱们才须要 JDBC 驱动包。

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 的配置,例如 (B 我的项目导入 A 我的项目中的包配置):

想必大家在做 SpringBoot 利用的时候,都会有如下代码:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.6.RELEASE</version>
</parent>

继承一个父模块,而后再引入相应的依赖。
如果说,我不想继承,或者我想继承多个,怎么做?

咱们晓得 Maven 的继承和 Java 的继承一样,是无奈实现多重继承的,如果 10 个、20 个甚至更多模块继承自同一个模块,那么依照咱们之前的做法,这个父模块的 dependencyManagement 会蕴含大量的依赖。如果你想把这些依赖分类以更清晰的治理,那就不可能了,import scope 依赖能解决这个问题。你能够把 dependencyManagement 放到独自的专门用来治理依赖的 pom 中,而后在须要应用依赖的模块中通过 import scope 依赖,就能够引入 dependencyManagement。例如能够写这样一个用于依赖治理的 pom:

<project>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.test.sample</groupId>
    <artifactId>base-parent1</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0-SNAPSHOT</version>
    <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>
</project>

而后我就能够通过非继承的形式来引入这段依赖治理配置

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.test.sample</groupId>
            <artifactid>base-parent1</artifactId>
            <version>1.0.0-SNAPSHOT</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>
 
<dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
</dependency>
<dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
</dependency>

留神:import scope 只能用在 <dependencyManagement> 外面

这样,父模块的 pom 就会十分洁净,由专门的 packaging 为 pom 来治理依赖,也符合的面向对象设计中的繁多职责准则。此外,咱们还可能创立多个这样的依赖治理 pom,以更细化的形式治理依赖。这种做法与面向对象设计中应用组合而非继承也有点类似的滋味。

那么,如何用这个办法来解决 SpringBoot 的那个继承问题呢?

配置如下:

<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>
</dependencies>

这样配置的话,本人的我的项目外面就不须要继承 SpringBoot 的 module 了,而能够继承本人我的项目的 module 了。

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。

上面是一张 nexus 画的图:

正文完
 0