一、scope屬性
依賴范圍控制哪些依賴在哪些classpath 中可用,哪些依賴包含在一個應用中。
- compile (編譯)
compile是默認的范圍;如果沒有提供一個范圍,那該依賴的范圍就是編譯范圍。編譯范圍依賴在所有的classpath中可用,同時它們也會被打包。
- provided (已提供)
provided 依賴只有在當JDK 或者一個容器已提供該依賴之后才使用。例如, 如果你開發了一個web 應用,你可能在編譯 classpath 中需要可用的Servlet API 來編譯一個servlet,但是你不會想要在打包好的WAR 中包含這個Servlet API;這個Servlet API JAR 由你的應用服務器或者servlet 容器提供。已提供范圍的依賴在編譯classpath (不是運行時)可用。它們不是傳遞性的,也不會被打包。
- runtime (運行時)
runtime 依賴在運行和測試系統的時候需要,但在編譯的時候不需要。比如,你可能在編譯的時候只需要JDBC API JAR,而只有在運行的時候才需要JDBC
驅動實現。
- test (測試)
test范圍依賴 在一般的編譯和運行時都不需要,它們只有在測試編譯和測試運行階段可用。
- system (系統)
system范圍依賴與provided類似,但是你必須顯式的提供一個對於本地系統中JAR文件的路徑。這么做是為了允許基於本地對象編譯,而這些對象是系統類庫的一部分。這樣的構建應該是一直可用的,Maven 也不會在倉庫中去尋找它。如果你將一個依賴范圍設置成系統范圍,你必須同時提供一個systemPath元素。注意該范圍是不推薦使用的(建議盡量去從公共或定制的 Maven 倉庫中引用依賴)。示例如下:
<project> <dependencies> <dependency> <groupId>sun.jdk</groupId> <artifactId>tools</artifactId> <version>1.5.0</version> <scope>system</scope> <systemPath>${java.home}/../lib/tools.jar</systemPath> </dependency> ... </dependencies> </project>
- import(導入)
import僅支持在<dependencyManagement>
中的類型依賴項上。它表示要在指定的POM <dependencyManagement>
部分中用有效的依賴關系列表替換的依賴關系。該scope類型的依賴項實際上不會參與限制依賴項的可傳遞性。
二、scope的依賴傳遞
A–>B–>C。當前項目為A,A依賴於B,B依賴於C,A與C的依賴關系?
- 當B對C的依賴的scope是test或者provided,則A不依賴C。
- 當B對C的依賴是scope是runtime或者compile,則A依賴C。且傳遞依賴的scope的規則:如果A對B的依賴是compile,那么A對C的依賴和B對C的依賴相同,否則和A對B的依賴保持一致。
三、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>若聲藝美</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>--> <!--<!–依賴jar不打進項目jar包中–>--> <!--<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一樣,這樣就可以使模塊管理看起來更簡潔了,也實現了多繼承的效果。
附注:
在maven中經常會使用<optional>true</optional>參數,如下:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency>
此處的<optional>true</optional>的作用是讓依賴只被當前項目使用,而不會在模塊間進行傳遞依賴。