Maven依賴中scope的含義

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>1.3.3.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>1.3.3.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>

這樣配置的話,自己的項目裡面就不需要繼承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畫的圖。

 到此這篇關於Maven依賴中scope的含義的文章就介紹到這瞭,更多相關Maven scope內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: