2014-09-10 72 views
1

想象一下,正在編寫一個具有2個依賴關係的應用程序;我們稱它們爲依賴項A和依賴項B。你無法控制這些依賴關係中的任何一個;他們不是你的圖書館,但你的應用程序依賴於他們。事實證明,依賴關係A依賴於依賴關係X(版本1.0); B依賴於X(版本2.0)。爲什麼在Maven中包含相同依賴項的多個版本是不可能的?

按照Maven documentation,將用於依賴調解來決定哪些依賴使用方法:

依賴調解 - 這決定了當工件的多個版本是什麼版本的依賴 將用於遇到。 目前,Maven 2.0僅支持使用「最接近定義」 ,這意味着它將使用與依賴關係樹中項目最接近的版本 。您可以始終通過在項目的POM中明確聲明 版本來保證。請注意,如果 兩個依賴項版本在依賴關係樹中處於相同深度 ,直到Maven 2.0.8未定義哪一個會獲勝,但自從 Maven 2.0.9它是聲明中的順序:第一個 宣告勝利。

所以,假設我們聲明依賴A,再X 1.0版將在我們的應用中使用。這意味着依賴關係B將在運行時使用X版本1.0,其中編譯爲針對版本2.0的X。如果B正在使用某些2.0版功能,那麼我們將得到運行時錯誤(NoSuchMethodError,ClassNotFoundException等),這並不好。所以爲了「解決」這個問題,我們可以從依賴關係A中排除依賴關係X,以便使用版本2.0代替X。但是哦,不! X版本2.0不向後兼容,所以我們最終得到的運行時錯誤來自A

據我所知,沒有辦法用Maven正確解決這個問題。你所能做的只是希望獲得其中一個庫的源代碼並修復它自己。那是對的嗎?

爲什麼不可能爲X的兩個版本打包到我的應用程序,使得A使用1.0 X版本,B使用X 2.0版本,並在我的應用程序的X可用的版本是什麼Maven的選擇通過依賴調解。它是Java的限制還是Maven的限制?這種情況很普遍嗎?還有其他可能的解決方案嗎?所有圖書館是否應保證向後兼容以避免此問題?

回答

2

具有相同名稱的兩個類無法加載到一個類加載器中。如果Maven允許你有多個版本的相同的工件,這無疑會發生。所以這是Maven正在適應的Java問題。

我不確定這有一個全面的解決方案。如果您控制了AB,則可以使用底紋將您的使用X重命名爲不會發生衝突的內容,如What is the maven-shade-plugin used for, and why would you want to relocate java packages?中所述。

一般而言,人們必須希望在庫之間保持向後兼容性,並對產生的應用程序進行測試以確保沒有問題。很明顯,您希望將Maven配置爲包含x-2.0而不是x-1.0,可以先列出B或在您的POM中明確列出X

一句警告:大多數版本命名方案允許在1.x.x和2.x.x之間切換更改,因此您可能會遇到問題。一些Maven項目(例如Apache Commons Lang)在更改主要版本時將使用新的工件標識和包結構,以避免這些衝突。

相關問題