groupId,artifactId和version:依賴的基本座標,對於任何一個依賴來講,基本座標是最重要的,Maven根據座標才能找到須要的依賴
type: 依賴的類型,對應於項目座標定義的packaging。大部分狀況下,該元素沒必要聲明,其默認值是jar
scope: 依賴的範圍,下面會進行詳解
optional: 標記依賴是否可選
exclusions: 用來排除傳遞性依賴,下面會進行詳解
大部分依賴聲明只包含基本座標。java
maven依賴分爲傳遞依賴,可選依賴,排除依賴,歸類依賴。spring
Maven在編譯主代碼的時候須要使用一套classpath,在編譯和執行測試的時候會使用另外一套classpath,實際運行項目的時候,又會使用一套classpath。sql
依賴範圍就是用來控制依賴與這三種classpath(編譯classpath、測試classpath、運行classpath)的關係,Maven有如下幾種依賴範圍:apache
compile: 編譯依賴範圍。若是沒有指定,就會默認使用該依賴範圍。使用此依賴範圍的Maven依賴,對於編譯、測試、運行三種classpath都有效。api
test: 測試依賴範圍。使用此依賴範圍的Maven依賴,只對於測試classpath有效,在編譯主代碼或者運行項目的使用時將沒法使用此類依賴。典型的例子就是JUnit,它只有在編譯測試代碼及運行測試的時候才須要。app
provided: 已提供依賴範圍。使用此依賴範圍的Maven依賴,對於編譯和測試classpath有效,但在運行時無效。典型的例子是servlet-api,編譯和測試項目的時候須要該依賴,但在運行項目的時候,因爲容器已經提供,就不須要Maven重複地引入一遍。maven
runtime: 運行時依賴範圍。使用此依賴範圍的Maven依賴,對於測試和運行classpath有效,但在編譯主代碼時無效。典型的例子是JDBC驅動實現,項目主代碼的編譯只須要JDK提供的JDBC接口,只有在執行測試或者運行項目的時候才須要實現上述接口的具體JDBC驅動。ide
system: 系統依賴範圍。該依賴與三種classpath的關係,和provided依賴範圍徹底一致。可是,使用system範圍依賴時必須經過systemPath元素顯式地指定依賴文件的路徑。因爲此類依賴不是經過Maven倉庫解析的,並且每每與本機系統綁定,可能形成構建的不可移植,所以應該謹慎使用。systemPath元素能夠引用環境變量,如:測試
<dependency> <groupId>javax.sql</groupId> <artifactId>jdbc-stdext</artifactId> <version>2.0</version> <scope></scope> <systemPath>${java.home}/lib/rt.jar</systemPath> </dependency>
import(Maven 2.0.9及以上): 導入依賴範圍。該依賴範圍不會對三種classpath產生實際的影響,稍後會介紹到。spa
A->B A依賴B,B->C B依賴C,則A和C之間存在傳遞依賴,依賴範圍控制着傳遞依賴產生的影響。如account-email對於spring-core的依賴範圍是compile,spring-core對於commons-logging的依賴範圍是compile,那麼account-email對於commons-logging這一傳遞性依賴的範圍也就是compile。
假設A依賴B,B依賴C,咱們說A對於B是第一直接依賴,B對於C是第二直接依賴,A對於C是傳遞性依賴。第一直接依賴的範圍和第二直接依賴的範圍決定了傳遞性依賴的範圍,以下圖,最左邊一列表示第一直接依賴範圍,最上面一行表示第二直接依賴範圍,中間交叉單元格表示傳遞性依賴範圍。
傳遞依賴深度不一樣
A->B->C->X(1.0)
A->D->X(2.0)
因爲只能引入一個版本的包,此時Maven按照最短路徑選擇導入x(2.0)。
傳遞依賴深度相同
A->B->X(1.0)
A->D->X(2.0)
路徑長度一致,則優先選擇pom文件中先聲明的,此時導入x(1.0)。
有時候咱們不想讓依賴傳遞,那麼可配置該依賴爲可選依賴,將元素optional設置爲true便可,例如:
<dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> <optional>true<optional> </dependency>
那麼依賴該項目的另以項目將不會獲得此依賴的傳遞。
當咱們引入第三方jar包的時候,不免會引入傳遞性依賴,有些時候這是好事,然而有些時候咱們不須要其中的一些傳遞性依賴。
好比上例中的項目,咱們不想引入傳遞性依賴commons-logging,咱們可使用exclusions元素聲明排除依賴,exclusions能夠包含一個或者多個exclusion子元素,所以能夠排除一個或者多個傳遞性依賴。須要注意的是,聲明exclusions的時候只須要groupId和artifactId,而不須要version元素,這是由於只須要groupId和artifactId就能惟必定位依賴圖中的某個依賴。換句話說,Maven解析後的依賴中,不可能出現groupId和artifactId相同,可是version不一樣的兩個依賴。
以下是一個排除依賴的例子:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>2.5.6</version> <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> </dependency>
若是咱們項目中用到不少關於Spring Framework的依賴,它們分別是org.springframework:spring-core:2.5.6, org.springframework:spring-beans:2.5.6,org.springframework:spring-context:2.5.6,它們都是來自同一項目的不一樣模塊。所以,全部這些依賴的版本都是相同的,並且能夠預見,若是未來須要升級Spring Framework,這些依賴的版本會一塊兒升級。所以,咱們應該在一個惟一的地方定義版本,而且在dependency聲明引用這一版本,這一在Spring Framework升級的時候只須要修改一處便可。
<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.mycompany.app</groupId> <artifactId>my-app-simple</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>my-app-simple</name> <properties> <springframework.version>2.5.6</springframework.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${springframework.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${springframework.version}</version> </dependency> </dependencies> </project>