Maven之scope(指定依賴範圍)

1.一些Pom依賴的元素

<?xml version="1.0" encoding="UTF-8"?>
<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>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                //用來排除傳遞依賴性
                <exclusion>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>所引依賴的包版本</version>
            <type>依賴的類型,對應於項目中的packing,默認是jar類型的依賴</type>
            <optional>true</optional>//標記爲是否爲可選依賴
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>system</scope>//表示依賴的範圍
            <systemPath>${java.home}/../lib/tools.jar</systemPath>
        </dependency>
    </dependencies>
</project>

2. 依賴範圍(scope)的幾個種類

  • compile(編譯範圍):compile是默認的範圍;如果沒有提供一個範圍,那該依賴的範圍就是編譯範圍。編譯範圍依賴在所有的classpath 中可用,同時它們也會被打包。對於編譯,測試,運行三個狀態都有效。
  • provided(JDK或者容器已經提供的範圍):provided 依賴只有在當JDK 或者一個容器已提供該依賴之後才使用。例如,如果你開發了一個web 應用,你可能在編譯 classpath 中需要可用的Servlet API 來編譯一個servlet,但是你不會想要在打包好的WAR 中包含這個Servlet API;這個Servlet API JAR 由你的應用服務器或者servlet 容器提供。已提供範圍的依賴在編譯classpath (不是運行時)可用。它們不是傳遞性的,也不會被打包。對於編譯和測試時有效,但運行時無效。
  • test(測試範圍): test範圍依賴在一般的編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。
  • runtime(運行時有效):runtime 依賴在運行和測試系統的時候需要,但在編譯的時候不需要。比如,你可能在編譯的時候只需要JDBC API JAR,而只有在運行的時候才需要JDBC驅動實現。對測試和運行時有效,編譯時無效。
  • system(系統依賴): system範圍依賴與provided 類似,但是你必須顯式的提供一個對於本地系統中JAR 文件的路徑。這麼做是爲了允許基於本地對象編譯,而這些對象是系統類庫的一部分。這樣的構件應該是一直可用的,Maven 也不會在倉庫中去尋找它。如果你將一個依賴範圍設置成系統範圍,你必須同時提供一個 systemPath 元素。注意該範圍是不推薦使用的(你應該一直儘量去從公共或定製的 Maven 倉庫中引用依賴)。而且system必須顯示的指定依賴文件,通過<systemPath>來進行指定,是與本機綁定的,所以基本很少用到。
  • import僅支持在<dependencyManagement>中的類型依賴項上。它表示要在指定的POM <dependencyManagement>部分中用有效的依賴關係列表替換依賴關係。該scope類型的依賴項實際上不會參與限制依賴項的可傳遞性。

3. Scope依賴的傳遞性

A ——> B ——> C:表示項目A依賴於項目B的同時項目B依賴於項目C,此時的項目A與項目C的關係如下:

項目A與項目C的依賴關係表
第一列A與B的依賴,第一行B與C的依賴 compile provided runtime test
compile compile   runtime  
provided provided provided provided  
runtime runtime   runtime  
test test   test  

結論:

  • 當B對C的依賴的scope是test或者provided,則A不依賴C。
  • 當B對C的依賴是scope是runtime或者compile,則A依賴C。
  • 傳遞依賴的scope的規則:如果A對B的依賴是compile,那麼A對C的依賴和B對C的依賴相同,否則和A對B的依賴保持一致。

4.Scope中import的使用

       該類型只在dependencyManagement內使用生效,它可以用來管理模塊依賴,也就是針對包含了一系列子依賴的模塊導入到當前項目中進行管理使用,而不是把需要用到的依賴一個一個的加入到項目中進行管理,可以理解爲多繼承模式。

       比如在一些場景中:我們只是想單純加入springboot模塊的依賴,而不想將springboot作爲父模塊引入項目中,此時就可以使用import來處理。

一般我們將Springboot作爲父模塊引入到項目中:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.9.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

一個項目中一般只能有一個父依賴模塊,可實際開發中會定義自己的父模塊,這樣就會出現衝突,這種情況下我們可以使用import來將springboot作爲依賴模塊導入自己的項目中。

<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.example.demo</groupId>
    <artifactId>MyService</artifactId>
    <version>1.0.0</version>
    <packaging>pom</packaging>
    <description>demo springboot</description>
    <inceptionYear>2019</inceptionYear>
    <organization>
        <name>calm_encode</name>
        <url>http://baidu.com</url>
    </organization>
    <licenses>
        <license>
            <name>The Apache Software License, Version 2.0</name>
            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
        </license>
    </licenses>

    <modules>
        <module>service</module>
        <module>common</module>
        <module>util</module>
    </modules>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <!-- 注入組件定義的第三方依賴 -->
    <dependencyManagement>
        <dependencies>
            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-dependencies</artifactId>
            <version>2.1.9.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
            ......
        </dependencies>
    </dependencyManagement>

    <!-- 遠程倉庫配置 -->
    <distributionManagement> 
        <repository> 
            <id>releases</id> 
            <url>http://ali/nexus/content/repositories/releases</url> 
        </repository> 
        <snapshotRepository> 
            <id>snapshots</id> 
            <url>http://ali/nexus/content/repositories/snapshots/nexus/content/repositories/snapshots</url> 
        </snapshotRepository> 
    </distributionManagement>

    <build>
        <pluginManagement>
            <plugins>
                <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!--使用-Dloader.path需要在打包的時候增加<layout>ZIP</layout>,不指定的話-Dloader.path不生效-->
                    <layout>ZIP</layout>
                    <!-- 指定該jar包啓動時的主類[建議] -->
                    <mainClass>com.common.util.CommonUtilsApplication</mainClass>
                    <!--<includes>-->
                        <!--&lt;!&ndash;依賴jar不打進項目jar包中&ndash;&gt;-->
                        <!--<include>-->
                            <!--<groupId>nothing</groupId>-->
                            <!--<artifactId>nothing</artifactId>-->
                        <!--</include>-->
                    <!--</includes>-->
                    <!--配置的 classifier 表示可執行 jar 的名字,配置了這個之後,在插件執行 repackage 命令時,
                    就不會給 mvn package 所打成的 jar 重命名了,這樣就可以被其他項目引用了,classifier命名的爲可執行jar-->
                    <!--<classifier>myexec</classifier>-->
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <!-- 剔除spring-boot打包的org和BOOT-INF文件夾(用於子模塊打包) -->
                    <!--<skip>true</skip>-->
                    <source>1.8</source>
                    <target>1.8</target>
                    <!--<encoding>UTF-8</encoding>-->
                </configuration>
            </plugin>
            <!--拷貝依賴到jar外面的lib目錄-->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>
                <executions>
                    <execution>
                        <id>copy</id>
                        <phase>package</phase>
                        <goals>
                            <goal>copy-dependencies</goal>
                        </goals>
                        <configuration>
                            <outputDirectory>
                                ${project.build.directory}/lib
                            </outputDirectory>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>${plugin.assembly.version}</version>
                <configuration>
                    <finalName>myservice</finalName>
                    <descriptor>deploy/assembly.xml</descriptor>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

上述就可以將springboot模塊作爲依賴導入到項目中,然後就可以繼承自己的父模塊了,如果要加入其它類似springboot這樣的模塊的話就和加入springboot一樣,這樣就可以使模塊管理看起來更簡潔了,也實現了多繼承的效果。

5. 補充在maven中經常會使用的<optional>true</optional>參數

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <optional>true</optional>
</dependency>

參數解釋:<optional>true</optional>的作用是讓依賴只被當前項目使用,而不會在模塊間進行傳遞依賴。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章