1. 程式人生 > >Maven實戰(書籍閱讀1)- 依賴

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依賴調接的第二原則:第一宣告者優先

,那麼Y(1.0)就會被解析使用了。

可選依賴

  假設有這樣一個依賴關係,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依賴的版本的時候,只需要修改一處即可。

優化依賴

顯式的宣告任何專案中直接用到的依賴。

  專案中直接使用到的,而沒有顯示宣告的依賴,意味著潛在的風險,當前專案直接在使用他們,而這種依賴是通過傳遞性依賴進來的,當升級直接依賴的時候,傳遞性依賴的版本也可能發生改變,這種變化不易察覺,但有可能導致當前專案出錯。這種隱藏的、潛在的威脅一旦出現,就往往需要耗費大量的時間來查明真相。因此,顯式的宣告任何專案中直接用到的依賴。