幾乎所有基于JVM的項(xiàng)目都會或多或少依賴其他庫,假設(shè)你在開發(fā)一個基于web的項(xiàng)目,你很可能會依賴很受歡迎的開源框架比如Spring MVC來提高效率。Java的第三方庫一般以JAR文件的形式存在,一般用庫名加版本號來標(biāo)識。隨著開發(fā)的進(jìn)行依賴的第三方庫增多小的項(xiàng)目變的越來越大,組織和管理你的JAR文件就很關(guān)鍵。
由于Java語言并沒提供依賴管理的工具,所以你的團(tuán)隊(duì)需要自己開發(fā)一套存儲和檢索依賴的想法。你可能會采取以下幾種常見的方法:
盡管上面的方法都能用,但是這距離理想的解決方案差遠(yuǎn)了,因?yàn)樗麄儧]有提供一個標(biāo)準(zhǔn)化的方法來命名和管理JAR文件。至少你得需要開發(fā)庫的準(zhǔn)確版本和它依賴的庫(傳遞依賴),這個為什么這么重要?
準(zhǔn)確知道依賴的版本
如果在項(xiàng)目中你沒有準(zhǔn)確聲明依賴的版本這將會是一個噩夢,如果沒有文檔你根本無法知道這個庫支持哪些特性,是否升級一個庫到新的版本就變成了一個猜謎游戲因?yàn)槟悴恢滥愕漠?dāng)前版本。
管理傳遞依賴
在項(xiàng)目的早期開發(fā)階段傳遞依賴就會是一個隱患,這些庫是第一層的依賴需要的,比如一個比較常見的開發(fā)方案是將Spring和Hibernate結(jié)合起來這會引入超過20個其他的開發(fā)庫,一個庫需要很多其他庫來正常工作。下圖展示了Hibernate核心庫的依賴圖:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/5-1.png" alt="" />
如果沒有正確的管理依賴,你可以會遇到?jīng)]想到過的編譯期錯誤和運(yùn)行期類加載問題。我們可以總結(jié)到我們需要一個更好的方式來管理依賴,一般來講你想在項(xiàng)目元數(shù)據(jù)中聲明你的依賴和它的版本號。作為一個項(xiàng)目自動化的過程,這個版本的庫會自動從中央倉庫下載、安裝到你的項(xiàng)目中,我們來看幾個現(xiàn)有的開源解決方案。
使用自動化的依賴管理
在Java領(lǐng)域里支持聲明的自動依賴管理的有兩個項(xiàng)目:Apache Ivy(Ant項(xiàng)目用的比較多的依賴管理器)和Maven(在構(gòu)建框架中包含一個依賴管理器),我不再詳細(xì)介紹這兩個的細(xì)節(jié)而是解釋自動依賴管理的概念和機(jī)制。
Ivy和Maven是通過XML描述文件來表達(dá)依賴配置,配置包含兩部分:依賴的標(biāo)識加版本號和中央倉庫的位置(可以是一個HTTP鏈接),依賴管理器根據(jù)這個信息自動定位到需要下載的倉庫然后下載到你的機(jī)器中。庫可以定義傳遞依賴,依賴管理器足夠聰明分析這個信息然后解析下載傳遞依賴。如果出現(xiàn)了依賴沖突比如上面的Hibernate core的例子,依賴管理器會試著解決。庫一旦被下載就會存儲在本地的緩存中,構(gòu)建系統(tǒng)先檢查本地緩存中是否存在需要的庫然后再從遠(yuǎn)程倉庫中下載。下圖顯示了依賴管理的關(guān)鍵元素:
http://wiki.jikexueyuan.com/project/gradleIn-action/images/5-2.png" alt="" />
Gradle通過DSL來描述依賴配置,實(shí)現(xiàn)了上面描述的架構(gòu)。
雖然依賴管理器簡化了手工的操作,但有時也會遇到問題。你會發(fā)現(xiàn)你的依賴圖中會依賴同個庫的不同版本,使用日志框架經(jīng)常會遇到這個問題,依賴管理器基于一個特定的解決方案只選擇其中一個版本來避免版本沖突。如果你想知道某個庫引入了什么版本的傳遞依賴,Gradle提供了一個非常有用的依賴報告來回答這個問題。下一節(jié)我會通過一個例子來講解。