1. 程式人生 > >Maven從倉庫解析並使用依賴構建的機制。

Maven從倉庫解析並使用依賴構建的機制。

當本地倉庫沒有依賴構件的時候,Maven會自動從遠端倉庫下載;當依賴版本為快照版本的時候,Maven會自動找到最新的快照。這背後的依賴解析機制可以概括如下:

  1. 當依賴的範圍是system的時候,Maven直接從本地檔案系統解析構件。
  2. 根據依賴座標計算倉庫路徑後,嘗試直接從本地倉庫尋找構件,如果發現相應構件,則解析成功。
  3. 在本地倉庫不存在相應構件的情況下,如果依賴的版本是RELEASE或者LATEST,則基於更新策略讀取所有遠端倉庫的元資料groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元資料合併後,計算出RELEASE或者LATEST真實的值,然後基於這個真實的值檢查本地和遠端倉庫,如步驟2和3。
  4. 如果依賴的版本是SNAPSHOT,則基於更新策略讀取所有遠端倉庫的元資料groupId/artifactId/version/maven-metadata.xml,將其與本地倉庫的對應元資料合併後,得到最新快照版本的值,然後基於該值檢查本地倉庫,或者從遠端倉庫下載。
  5. 如果最後解析得到的構建版本是時間戳格式的快照,如1.4.1-20091104.121450-121,則複製其時間戳格式的檔案至非時間戳格式,如SNAPSHOT,並使用該非時間戳格式的構件。

當依賴的版本不明晰的時候,如RELEASE、LATEST和SNAPSHOT,Maven就需要基於更新遠端倉庫的更新策略來檢查更新。有一些配置與此有關:首先是<releases><enabled>和<snapshots><enabled>,只有倉庫開啟了對於釋出版本的支援時,才能訪問該倉庫的釋出版本構件資訊,對於快照版本也是同理;其次要注意的是<releases>和<snapshots>的子元素<updatePolicy>,該元素配置了檢查更新的頻率,每日檢查更新、永遠檢查更新、從不檢查更新、自定義時間間隔檢查更新等。最後,使用者還可以從命令列加入引數-U,強制檢查更新,使用引數後,Maven就會忽略<updatePolicy>的配置。

當Maven檢查完更新策略,並決定檢查依賴更新的時候,就需要檢查倉庫元資料maven-metadata.xml。

回顧一下前面提到的RELEASE和LATEST版本,他們分別對應了倉庫中存在的該構件的最新發布版本和最新版本(包含快照),而這兩個“最新”是基於groupId/artifactId/maven-metadata.xml計算出來的,如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
    <groupId>org.sonatype.nexus</groupId>
    <artifactId>nexus</artifactId>
    <versioning>
        <latest>1.4.2-SNAPSHOT</latest>
        <release>1.4.0</release>
        <versions>
            <version>1.3.5</version>
            <version>1.3.6</version>
            <version>1.4.0-SNAPSHOT</version>
            <version>1.4.0</version>
            <version>1.4.0.1-SNAPSHOT</version>
            <version>1.4.1-SNAPSHOT</version>
            <version>1.4.2-SNAPSHOT</version>
        </versions>
        <lastUpdated>20091214221557</lastUpdated>
    </versioning>
</metadata>

該XML檔案列出了倉庫中存在的該構件所有可用的版本,同時latest元素指向了這些版本中最新的那個版本,該例中是1.4.2-SNAPSHOT。而release元素指向了這些版本中最新的釋出版本,該例中是1.4.0。Maven通過合併多個遠端倉庫及本地倉庫的元資料,就能計算出基於所有倉庫的latest和release分別是什麼,然後再解析具體的構件。

需要注意的是,在依賴宣告中使用LATEST和RELEASE是不推薦的做法。因為Maven隨時都可能解析到不同的構件,可能今天LATEST是1.3.6,明天就成為1.4.0-SNAPSHOT了,且Maven不會明確告訴使用者這樣的變化。當這種變化造成構件失敗的時候,發現問題會變得比較困難。RELEASE因為對應的是最新發布版構件,還相對可靠,LATEST就非常不可靠了,為此,Maven3不再支援在外掛配置中使用LATEST和RELEASE。如果不設定外掛版本,其效果就和RELEASE一樣,Maven只會解析最新發布版本構件。不過即使這樣,也還存在前在的問題。例如,某個依賴的1.1版本與1.2版本可能發生一些介面的變化,從而導致當前Maven構件的失敗。

當依賴的版本設為快照版本的時候,Maven也需要檢查更新,這時,Maven會檢查倉庫元資料groupId/artifactId/version/maven-metadata.xml,見下面示例。

<?xml version="1.0" encoding="UTF-8" ?>
<metadata>
    <groupId>org.sonatype.nexus</groupId>
    <artifactId>nexus</artifactId>
    <version>1.4.2-SNAPSHOT</version>
    <versioning>
        <snapshot>
            <timestamp>20091214.221414</timestamp>
            <buildNumber>13</buildNumber>
        </snapshot>
        <lastUpdated>20091214221558</lastUpdated>
    </versioning>
</metadata>

該XML檔案的snapshot元素包含了timpestamp和buildNumber兩個子元素,分別代表了這一快照的時間戳和構件號,基於這兩個元素可以得到該倉庫中此快照的最新構件版本實際為1.4.2-20091214.221414-13。通過合併所有遠端倉庫和本地倉庫的元資料,Maven就能知道所有倉庫中該構件的最新快照。

最後,倉庫元資料並不是永遠正確的,有時候當用戶發現無法解析某些構件,或者解析得到錯誤構件的時候,就有可能是出現了倉庫元資料錯誤,這時就需要手工的,或者使用工具(如Nexus)對其進行修復。