讀古今文學網 > Maven實戰 > 6.6 從倉庫解析依賴的機制 >

6.6 從倉庫解析依賴的機制

第5章詳細介紹了Maven的依賴機制,本章又深入闡述了Maven倉庫,這兩者是如何具體聯繫到一起的呢?Maven是根據怎樣的規則從倉庫解析並使用依賴構件的呢?

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

1)當依賴的範圍是system的時候,Maven直接從本地文件系統解析構件。

2)根據依賴坐標計算倉庫路徑後,嘗試直接從本地倉庫尋找構件,如果發現相應構件,則解析成功。

3)在本地倉庫不存在相應構件的情況下,如果依賴的版本是顯式的發佈版本構件,如1.2、2.1-beta-1等,則遍歷所有的遠程倉庫,發現後,下載並解析使用。

4)如果依賴的版本是RELEASE或者LATEST,則基於更新策略讀取所有遠程倉庫的元數據groupId/artifactId/maven-metadata.xml,將其與本地倉庫的對應元數據合併後,計算出RELEASE或者LATEST真實的值,然後基於這個真實的值檢查本地和遠程倉庫,如步驟2)和3)。

5)如果依賴的版本是SNAPSHOT,則基於更新策略讀取所有遠程倉庫的元數據groupId/artifactId/version/maven-metadata.xml,將其與本地倉庫的對應元數據合併後,得到最新快照版本的值,然後基於該值檢查本地倉庫,或者從遠程倉庫下載。

6)如果最後解析得到的構件版本是時間戳格式的快照,如1.4.1-20091104.121450-121,則複製其時間戳格式的文件至非時間戳格式,如SNAPSHOT,並使用該非時間戳格式的構件。

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

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

回顧一下前面提到的RELEASE和LATEST版本,它們分別對應了倉庫中存在的該構件的最新發佈版本和最新版本(包含快照),而這兩個「最新」是基於groupId/artifactId/maven-metadata.xml計算出來的,見代碼清單6-5。

代碼清單6-5 基於groupId和artifactId的maven-metadata.xml

該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就非常不可靠了,為此,Maven 3不再支持在插件配置中使用LATEST和RELEASE。如果不設置插件版本,其效果就和RELEASE一樣,Maven只會解析最新的發佈版本構件。不過即使這樣,也還存在潛在的問題。例如,某個依賴的1.1版本與1.2版本可能發生一些接口的變化,從而導致當前Maven構建的失敗。

當依賴的版本設為快照版本的時候,Maven也需要檢查更新,這時,Maven會檢查倉庫元數據groupId/artifactId/version/maven-metadata.xml,見代碼清單6-6。

代碼清單6-6 基於groupId、artifactId和version的maven-metadata.xml

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

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