Maven的依賴可以真的很難解決沖突账锹。 這篇文章的目的是讓讀者更好地理解什么是版本沖突,為什么最好避免它們柿顶。 我將開始一個短篇故事,大多數(shù)讀者可能涉及到监徘。
這個故事
首先,想象你已經(jīng)開始致力于一個大型和有趣的項目,它使用許多不同的技術庫,使你的生活更容易為工程師忘巧。 作為一個額外的好處,Maven管理圖書館下載的庫版本的選擇; 所以他們可以很容易地更新曲横。 開發(fā)的項目繼續(xù)下去,直到有一天你遇到一個庫,減少了驗證的復雜性顯著發(fā)展; 然后決定包括在您的項目。
但突然間,你得到一個錯誤的2223行代碼,這是一條不同的你踩蔚。 那些浮現(xiàn)在你腦海的第一件事是,“多么奇怪! 這行代碼沒有失敗; 它必須是一個錯誤在我的代碼; 我必須創(chuàng)建/配置不正確”棚放。 然而,你意識到的代碼沒有任何問題。 更徹底的調(diào)試過程“可能”顯示,有一個NullPointerException或NoSuchMethodException庫類,您不知道存在馅闽。 第一反應是更新新版本的庫依賴關系; 但這并不能解決問題飘蚯。 接下來你要做的就是看看圖書館類本身的代碼; 發(fā)現(xiàn)該方法/類不存在; 即使更新新庫添加到您的項目馍迄。
此外,事情變得更加不可思議當你決定訪問本地Maven存儲庫.m2,你發(fā)現(xiàn)有兩個不同版本的庫。 您的項目使用的是舊版本,不知道為什么…
恭喜你! 你剛剛和版本庫沖突發(fā)現(xiàn)撞您的項目孝冒。
請注意:你把它當你添加身份驗證庫的故事柬姚。
它為什么會發(fā)生?
由于依賴關系可以與其他依賴不同的版本,可以產(chǎn)生沖突。 在此基礎上,我們可以畫一個依賴樹為我們的項目計劃X解釋:
![Image title](https://dzone.com/storage/temp/6202396-dependencies-example-1-e1473694110436.jpg)
從上面的樹方案中,很明顯,我們的項目X將使用的所有庫(Y,Z,H)即使在POM我們沒有顯式地指定它們庄涡。
實際上,在這種情況下,圖書館Z將導入到你的項目作為一個Maven依賴庫,即使你不知道圖書館的存在。 這種依賴是更好的被稱為過渡依賴搬设。
自Y和G取決于不同版本的Z,我們已經(jīng)創(chuàng)建了一個庫版本沖突穴店。 這個項目可以使用只有一個版本的Z在運行時庫(1.0或2.0); 但不能兩者兼得。 如果我們使用一個不兼容的版本庫與另一個庫; 項目最終可能會產(chǎn)生錯誤和崩潰拿穴。 讓我們假設庫Z在我們的項目錯誤背后的罪魁禍首; 我們想知道哪個版本的Z正在創(chuàng)建的錯誤泣洞。
我們使用Z版本?
我們的項目X使用Maven稱為默認機制依賴機制解決,知道使用哪個庫的依賴關系。
讓我們看看依賴機制是如何工作的默色。
首先,圖書館的版本的節(jié)點是根(最近的項目X)將使用依賴關系樹球凰。 然而,如果有幾個版本的相同的庫的節(jié)點都在相同的水平在樹上? 在這種情況下,發(fā)現(xiàn)第一個庫版本使用。 這意味著庫版本的選擇取決于依賴POM文件里面了,那些依賴宣布第一將選擇腿宰。
如何解決沖突
有兩種方法可以解決上述沖突呕诉。 第一和最簡單的解決方案是導入庫G在圖書館Y內(nèi)部X的POM文件; 正如我上面解釋道。 然而,一個簡潔的解決方案是進口的最后版本Z(2.0)的直接依賴關系X; 內(nèi)部XPOM文件吃度。 有一些運氣,后者的解決方案如果圖書館工作Z支持向后兼容(如圖書館Y使用Z的v1.0)甩挫。 在這種情況下測試需要增加可靠性
重要提示:如果有版本沖突,它并不總是意味著你的項目將會崩潰,通常會有版本沖突,當你使用大量的庫,但我們必須注意,不會崩潰,我們的項目使用的庫版本。
我怎么能更快地發(fā)現(xiàn)沖突?
提出的問題在上面的故事非常簡單,我們很幸運,快速解決它椿每。 然而,有時候,它不是一項容易的任務找到依賴沖突; 即使你已經(jīng)知道,這個錯誤不是來自你的代碼邏輯伊者。
不是很好有一個工具,測試庫項目中沖突嗎? 你很幸運!
執(zhí)行者- Maven的愛的鐵拳
就是干這個的。 執(zhí)行者可以幫助開發(fā)者解決依賴沖突Maven POM文件中聲明通過分析所有庫间护。
這個插件使用很多不同的規(guī)則,但是我們只是感興趣:
dependencyConvergence
-確保所有依賴項收斂于相同的版本亦渗。
讓我們配置插件來使用規(guī)則寫在pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-enforcer-plugin</artifactId>
<version>1.4.1</version>
<configuration>
<rules><dependencyConvergence/></rules>
</configuration>
</plugin>
</plugins>
從上面的配置,您可以執(zhí)行的目標執(zhí)行者:執(zhí)行通過項目的命令行(mvn執(zhí)行者:執(zhí)行); 或者通過綁定一個Maven目標階段。 這是非常有用的找到任何依賴沖突,項目可能會崩潰汁尺。 一旦執(zhí)行,插件返回樹列表顯示所有沖突(如果有的話)在項目:
Dependency convergence error for log4j:log4j:1.2.17 paths to dependency are:
+-com.ricston.conflict:conflict-info:2.1.3-SNAPSHOT
+-org.slf4j:slf4j-log4j12:1.7.6
+-log4j:log4j:1.2.17
and
+-com.ricston.conflict:conflict-info:2.1.3-SNAPSHOT
+-log4j:log4j:1.2.16
執(zhí)行者依賴樹寫道,正如上面你可以看到的,根源在哪里我們的項目“conflict-info”法精。
在這種情況下,圖書館log4j版本沖突。 我們有兩個圖書館log4j版本(1.2.17和1.2.16)均函。
log4j版本1.2.16是依靠由項目“conflict-info”; 雖然版本1.2.17取決于log4j的“slf4j-log4j12”亿虽。 在編譯和運行時,將使用log4j版本1.2.16,因為它的根節(jié)點最近的我們的項目依賴關系樹。 因為只有一個庫版本可以在運行時使用,同一版本將用于“slf4j-log4j12”苞也。
請注意,并不是所有項目依賴版本沖突會崩潰洛勉。 Maven的依賴機制負責選擇庫版本,在前面的部分。
最后,為了有更好的機會避免依賴版本沖突; 提取的依賴(和首選的版本)作為項目的直接的孩子如迟。 這將確保所選的版本是用于所有子庫的依賴關系; 提供選擇的版本不崩潰收毫。
結論
這一結論提供進一步信息版本沖突,如何克服他們在您的項目中攻走。
還有許多其他的方法來解決這種沖突; 甚至還有圖書數(shù)百頁使用不同的Maven配置說明解決方案。 本文描述了只有一個解決這些問題的方法此再。