原文地址 譯者:Tyrianhtml
依賴機制是Maven最爲用戶熟知的特性之一,同時也是Maven所擅長的領域之一。單個項目的依賴管理並不難,
可是當你面對包含數百個模塊的多模塊項目和應用時,Maven能幫你保證項目的高度控制力和穩定性。java
大綱:web
傳遞性依賴是Maven2.0的新特性。假設你的項目依賴於一個庫,而這個庫又依賴於其餘庫。你沒必要本身去找出全部這些依賴,你只須要加上你直接依賴的庫,Maven會隱式的把這些庫間接依賴的庫也加入到你的項目中。這個特性是靠解析從遠程倉庫中獲取的依賴庫的項目文件實現的。通常的,這些項目的全部依賴都會加入到項目中,或者從父項目繼承,或者經過傳遞性依賴。
傳遞性依賴的嵌套深度沒有任何限制,只是在出現循環依賴時會報錯。
傳遞性依賴會致使包含庫的依賴圖增加的很是大。爲了解決這個問題,Maven也提供了額外的機制,能讓你指定哪些依賴會被包含:redis
依賴範圍會影響傳遞性依賴,同時也會影響項目構建任務中使用的classpath。
Maven有如下6種依賴範圍:spring
每類依賴範圍(除了import)經過不一樣方式影響傳遞性依賴,具體以下表所示。最左側一列表明瞭直接依賴範圍,最頂層一行表明了傳遞性依賴的範圍,行與列的交叉單元格就表示最終的傳遞性依賴範圍。表中的「-「表示該傳遞性依賴將會被忽略。sql
compile | provided | runtime | test | |
compile | compile(*) | – | runtime | – |
provided | provided | – | provided | – |
runtime | runtime | – | runtime | – |
test | test | – | test | – |
(*)注意:這裏原本應該是compile範圍,那樣的話compile範圍都必須顯式指定-然而,有這樣一種狀況,你依賴的、繼承自其它庫中的類的庫必須在編譯時可用。考慮到這個緣由,即便在依賴性傳遞狀況下,編譯時依賴仍然是compile範圍。mongodb
Maven提供了一個機制來集中管理依賴信息,叫作依賴管理元素」<dependencyManagement>」。假設你有許多項目繼承自同一個公有的父項目,那能夠把全部依賴信息放在一個公共的POM文件,而且在子POM中簡單第引用該構件便可。經過一些例子能夠更好的解釋這個機制。下面是兩個繼承自同一個父項目的POM:apache
項目A編程
<project>
…
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>api
項目B
<project>
…
<dependencies>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
這兩個POM都依賴於同一個模塊,同時每一個POM又各自依賴於一個無關的模塊。父項目的POM詳細信息以下所示:
<project>
…
<dependencyManagement>
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
<version>1.0</version><exclusions>
<exclusion>
<groupId>group-c</groupId>
<artifactId>excluded-artifact</artifactId>
</exclusion>
</exclusions></dependency>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>war</type>
<scope>runtime</scope>
</dependency><dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<version>1.0</version>
<type>bar</type>
<scope>runtime</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
這樣兩個子項目的POM文件就簡單多了。
<project>
…
<dependencies>
<dependency>
<groupId>group-a</groupId>
<artifactId>artifact-a</artifactId>
</dependency><dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<!– This is not a jar dependency, so we must specify type. –>
<type>bar</type>
</dependency>
</dependencies>
</project><project>
…
<dependencies>
<dependency>
<groupId>group-c</groupId>
<artifactId>artifact-b</artifactId>
<!– This is not a jar dependency, so we must specify type. –>
<type>war</type>
</dependency><dependency>
<groupId>group-a</groupId>
<artifactId>artifact-b</artifactId>
<!– This is not a jar dependency, so we must specify type. –>
<type>bar</type>
</dependency>
</dependencies>
</project>
注意:在這兩個POM文件的依賴中,咱們必須指定<type/>元素。由於與依賴管理元素匹配的依賴引用最小信息集是{groupId, artifactId, type, classfier}。許多狀況下,依賴指向的jar不須要指定classfier。由於默認type是jar,默認classfiler爲空,因此咱們能夠把信息集設置爲{groupId, artifactId}。
依賴管理元素第二個很是有用的功能是控制傳遞性依賴中構件的版本。例子以下
項目A:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>A</artifactId>
<packaging>pom</packaging>
<name>A</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
項目B:
<project>
<parent>
<artifactId>A</artifactId>
<groupId>maven</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>B</artifactId>
<packaging>pom</packaging>
<name>B</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
當在maven中有項目依賴B時,無論它們的pom文件中指定的版本是什麼,構件a,b,c和d的版本都是1.0。
依賴管理的標籤詳細描述信息能夠從這裏獲取項目描述符引用
這個章節描述的特性只在Maven2.0.9及以後的版本纔有。這意味着更早版本的Maven不會解析包含import元素的pom文件。所以在使用該特性前,你必須慎重考慮。若是你打算使用這個特性,咱們建議你使用enforcer插件來強制使用Maven2.0.9及以上版本。
前面的例子描述了怎麼經過繼承來指定管理的依賴。然而,這對於更大的項目一般會更復雜,由於一個項目只能繼承自一個父項目。爲了解決這個問題,項目能夠導入其餘項目的管理依賴,這能夠經過聲明依賴一個包含值爲」import」的<scope>元素的構件來實現。
項目B:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>B</artifactId>
<packaging>pom</packaging>
<name>B</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>maven</groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>d</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.0</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
假設A就是上一個例子中定義的POM,那麼最終的結果也是一致的。除了在B中定義的d模塊,全部A的管理依賴都會導入到B中。
項目X:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>X</artifactId>
<packaging>pom</packaging>
<name>X</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.1</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>b</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
項目Y:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>Y</artifactId>
<packaging>pom</packaging>
<name>Y</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>test</groupId>
<artifactId>a</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>test</groupId>
<artifactId>c</artifactId>
<version>1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
項目Z:
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>maven</groupId>
<artifactId>Z</artifactId>
<packaging>pom</packaging>
<name>Z</name>
<version>1.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>maven</groupId>
<artifactId>X</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>maven</groupId>
<artifactId>Y</artifactId>
<version>1.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
在上面的例子中,Z導入了X和Y的管理依賴。不過有個問題,X和Y都包含了依賴a。在這裏,會使用1.1版本的a,由於X先被聲明,而且a沒有在Z的依賴管理中聲明。
這個過程是遞歸進行的。假如X導入了另外的POM,Q,那麼當解析Z的時候,全部Q的管理依賴看上去就都像在X中定義的同樣。
當定義一個用於構建多項目的包含一些相關構件的依賴「庫」時,導入依賴就十分有效。從「庫」中引用一個或多個構件到項目中,是一種很常見的作法。然而,
保持項目中使用的依賴版本與庫中發佈的版本一致會有點麻煩。下面的模式描述了怎麼生成一個供其它項目使用的「物料清單」(BOM)。
項目的根元素是BOM pom文件。它定義了庫中建立的全部構件版本。其它要使用該庫的項目必須將該pom導入到其pom文件中的<dependencyManagement>元素中。
<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.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project1Version>1.0.0</project1Version>
<project2Version>1.0.0</project2Version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project1Version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>parent</module>
</modules>
</project>
parent子項目將BOM pom做爲它的父項目。這是一個簡單的多項目pom。
<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.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<project1Version>1.0.0</project1Version>
<project2Version>1.0.0</project2Version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project1Version}</version>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>parent</module>
</modules>
</project>
接下來是真正的pom文件。
<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>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
<version>${project1Version}</version>
<packaging>jar</packaging><dependencies>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</dependency>
</dependencies>
</project><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>com.test</groupId>
<version>1.0.0</version>
<artifactId>parent</artifactId>
</parent>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
<version>${project2Version}</version>
<packaging>jar</packaging><dependencies>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
</dependencies>
</project>
下面的例子說明了怎麼在項目中使用「庫」,而沒必要指定依賴模塊的版本。
<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.test</groupId>
<artifactId>use</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging><dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>com.test</groupId>
<artifactId>project1</artifactId>
</dependency>
<dependency>
<groupId>com.test</groupId>
<artifactId>project2</artifactId>
</dependency>
</dependencies>
</project>
最後,當建立引入依賴的項目時,須要注意如下幾點:
系統範圍的依賴應該是一直可用,而且Maven不會去倉庫中查找。系統範圍依賴一般是指JDK或者VM提供的依賴。因此,系統依賴適用於這種狀況:之前能夠單獨獲取,但如今是由JDK提供的依賴。典型的例子就是JDBC標準擴展或者Java認證和受權服務(JAAS)。一個簡單的例子以下:
<project>
…
<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
…
</project>
若是你的構件依賴於JDK的tools.jar,那麼系統路徑的值以下所示:
<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>
原創文章,轉載請註明: 轉載自併發編程網 – ifeve.com本文連接地址: 《Maven官方文檔》-Maven依賴機制簡介
Software Engineerat TP-LINK