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