Maven實戰(書籍閱讀1)- 依賴
依賴性傳遞
何為傳遞性依賴:假設專案A的pom中依賴spring-core:2.5.6,而spring-core的pom中依賴commons-logging,都沒有宣告依賴範圍,那麼其依賴範圍預設為compile,如此commons-logging就是專案A的一個傳遞性依賴。
依賴範圍
。 | compile | test | provided | runtime |
---|---|---|---|---|
compile | compile | – | – | runtime |
test | test | – | – | test |
provided | provided | – | provided | provided |
runtime | runtime | – | – | runtime |
最左面一行 : 第一直接依賴範圍
最上邊一列 : 第二直接依賴範圍
A專案所依賴的spring-core為第一直接依賴,依賴範圍為compile,spring-core所依賴的common-logging為第二直接依賴,依賴範圍為compile,common-logging為A專案的傳遞性依賴,依賴範圍為compile。
總結:當第二直接依賴範圍是compile的時候,依賴傳遞範圍與第一直接依賴相同。當第二直接依賴範圍為test的時候,依賴不會得到傳遞。當為provided的時候,只傳遞第一直接依賴範圍為provided的依賴,且依賴範圍同樣為provided。
依賴調解
Maven引入的傳遞性依賴機制,再有的時候,會出現版本衝突或者別的問題,這個時候我們就需要知道該傳遞性依賴是從哪一條路徑引入的。
例如,專案A有這樣的依賴關係,A->B->C-X(1.0) 和 A->D->X(2.0),X是A的傳遞性依賴,但是這兩條路徑上有兩個版本的X,那麼哪個X會被Maven解析使用呢?Maven依賴調解的第一原則就是:路徑最近者優先,因此X(2.0)會被解析使用。
依賴調解的第一原則不能解決所有的問題,比如這樣的依賴關係:A->B->Y(1.0) 和 A->C->Y(2.0),這兩個Y的依賴路徑範圍都是 一樣的,那麼到底誰會被解析使用呢?Maven依賴調接的第二原則:第一宣告者優先
可選依賴
假設有這樣一個依賴關係,A->B,B->X(可選),B->Y(可選),假設三個都是compile傳遞範圍,那麼X和Y也是A的傳遞性依賴,但是X和Y是可選依賴,因為依賴講不會得到任何傳遞。如果要使用,必須在主專案中顯式的宣告這一依賴。
- B的依賴清單
<project>
<modelVersion>4.0</modelVersion>
<groupId></groupId>
<artifactId>B</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>4</groupId>
<artifactId>X</artifactId>
...
<optional>true</optional>
</dependency>
<dependency>
<groupId>4</groupId>
<artifactId>Y</artifactId>
...
<optional>true</optional>
</dependency>
</dependencies>
</project>
A若想使用B中的X依賴,必須在pom中顯式的宣告。
- A的依賴清單
<project>
<modelVersion>4.0</modelVersion>
<groupId></groupId>
<artifactId>A</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>4</groupId>
<artifactId>B</artifactId>
...
</dependency>
<dependency>
<groupId>4</groupId>
<artifactId>X</artifactId>
...
</dependency>
</dependencies>
</project>
排除依賴
傳遞性依賴會隱式的引入很多依賴,這極大的簡化了專案依賴的故案例,但也容易造成很多問題。比如,傳遞性依賴中有SNAPSHOP不穩定版本,而它的不穩定性會直接影響到當前專案,這是就需要排除掉該SNAPSHOP,並在當前專案中宣告該類庫的某個正式釋出的版本。
- pom清單
<project>
<modelVersion>4.0</modelVersion>
<groupId>com.teng.book</groupId>
<artifactId>project-a</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>com.teng.book</groupId>
<artifactId>project-b</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>com.teng.book</gropId>
<artifactId>projejct-c</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.teng.book</groupId>
<artifactId>project-c</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
</project>
在exclusion中,我們只需要知道groupId和artifactId兩個元素即可,因為在maven解析後的依賴中,不可能出現groupId和artifactId相同,而version不同的兩個依賴。
歸類依賴
<project>
<modelVersion>4.0</modelVersion>
<groupId>com.teng.book</groupId>
<artifactId>project-a</artifactId>
<version>1.0</version>
<properties>
<springframework.version>2.5.6</springframework.version>
</properties>
<dependencies>
<dependency>
<groupId>org.spring.core</groupId>
<artifactId>project-b</artifactId>
<version>{springframework.version}</version>
</dependency>
<dependency>
<groupId>com.spring.beans</groupId>
<artifactId>project-c</artifactId>
<version>{springframework.version}</version>
</dependency>
</dependencies>
</project>
在升級spring依賴的版本的時候,只需要修改一處即可。
優化依賴
顯式的宣告任何專案中直接用到的依賴。
專案中直接使用到的,而沒有顯示宣告的依賴,意味著潛在的風險,當前專案直接在使用他們,而這種依賴是通過傳遞性依賴進來的,當升級直接依賴的時候,傳遞性依賴的版本也可能發生改變,這種變化不易察覺,但有可能導致當前專案出錯。這種隱藏的、潛在的威脅一旦出現,就往往需要耗費大量的時間來查明真相。因此,顯式的宣告任何專案中直接用到的依賴。