一、問題背景
相信大家在日常的開發過程中都遇到過Jar包沖突的問題,emm,在最近處理業務需求時我也遇到了不同版本jar包沖突導致項目加載出錯的問題。主要是一個完整的項目會不可避免的使用第三方的Jar包來實現功能開發,各種第三方包之間可能會存在依賴關系,不同版本的依賴就會可能導致依賴間的相互沖突,進而導致整個項目加載的失敗。
這篇文章主要記錄了本次遇到的問題:即maven在面對不同版本的jar包在pom文件中同時聲明會存在加載覆蓋的問題,于是通過查詢網上相關資料對maven包的加載規則介紹,并通過實際場景對其進行分析驗證;
二、maven加載原則
1.最短路徑原則:面對多級(兩級及以上)的不同依賴,會優先選擇路徑最短的依賴;
2.聲明優先原則:面對多級(兩級及以上)的同級依賴,先聲明的依賴會覆蓋后聲明的依賴;
3.同級依賴中,后聲明的依賴會覆蓋先聲明的依賴;
三、本地驗證maven加載原則
1.最短路徑原則:使用最短路徑加載的前提是,項目中存在兩級以上的不同依賴jar包,此時項目會優先加載路徑最短的jar包;
?實例驗證:分別在common模塊和service模塊中間接和直接的引入不同版本的elasticsearch-rest-client,觀察項目中面對不同路徑長度情況下實際加載時所使用的版本情況。
?common模塊:在common模塊中引入elasticsearch-rest-high-level-client 依賴包, 而該依賴包它引入了 elasticsearch-rest-client 7.4.2,從而實現在common模塊中間接引用該包;
common的pom文件:
org.elasticsearch.client/groupId?> elasticsearch-rest-high-level-client/artifactId?> 7.4.2/version?> /dependency?> /dependencies?>
?service模塊:為了驗證不同路徑長度下maven的包加載順序,我們在service模塊中直接引入elasticsearch-rest-client 6.8.13;
service的pom文件:
org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 6.8.13/version?> /dependency?> /dependencies?>
?實際加載結果:在IDEA中加載pom文件時,可以在maven管理中看到已經提示jar包沖突;
?mvn dependency:tree: 我們可以通過mvn dependency :tree命令來查看該項目的依賴樹,觀察發現實際加載的版本是elasticsearch-rest-client 6.8.13,符合maven中的最短路徑優先原則;
?
2. 聲明優先原則:聲明優先原則的前提是對于兩級以上的同級依賴,先聲明的依賴會覆蓋后聲明的依賴包;
?實例驗證:針對該原則的驗證場景構造不再關注模塊是否直接或者間接引用不同版本的es,我們在common模塊和service模塊中都直接引用不同版本的es,然后通過改變兩個模塊在pom文件中聲明的先后順序來觀察項目啟動后實際加載的jar包;
?common模塊:在common模塊中直接引入依賴包elasticsearch-rest-client 7.4.2
org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 7.4.2/version?> /dependency?> /dependencies?>
?service模塊:在service模塊中引入依賴包elasticsearch-rest-client 6.8.13
org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 6.8.13/version?> /dependency?> /dependencies?>
?實際加載結果:
?場景1:我們將common模塊在pom文件中先引入,然后將在service模塊置于common模塊后面引入,觀察項目實際加載情況;
org.example/groupId?> backend_common/artifactId?> 1.0-SNAPSHOT/version?> /dependency?> org.example/groupId?> backend_service/artifactId?> 1.0-SNAPSHOT/version?> /dependency?> /dependencies?>
?觀察加載結果圖,發現實際加載的是es-rest-client 7.4.2, 即確實是common模塊的聲明生效,service模塊后聲明導致其中的es未被加載。符合聲明優先原則;
?場景2:我們將service模塊在pom文件中先引入,然后將在common模塊置于service模塊后面引入,觀察項目實際加載情況;;
org.example/groupId?> backend_service/artifactId?> 1.0-SNAPSHOT/version?> /dependency?> org.example/groupId?> backend_common/artifactId?> 1.0-SNAPSHOT/version?> /dependency?> /dependencies?>
?觀察項目實際加載結果圖,發現實際加載的是es-rest-client 6.8.13, 即確實是模塊的聲明生效,common模塊后聲明導致其中的es未被加載。發現符合聲明優先原則;
?聲明優先原則場景驗證結束;
3. 同級依賴中后加載覆蓋先加載原則;
?實例驗證:為了構造在同級依賴中的加載場景,我們在項目中直接引入兩個不同es版本的依賴,然后同樣通過改變兩個es版本在pom中的聲明順序來觀察項目實際加載的es版本。
?場景1:我們首先驗證client 7.4.2依賴包在client 6.8.13之前聲明的情況;
org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 7.4.2/version?> /dependency?> org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 6.8.13/version?> /dependency?> /dependencies?>
?觀察maven的實際加載結果如下,發現項目中實際加載的es-rest-client 版本是6.8.13,先聲明的7.4.2版本并未實際加載到項目中。符合同級依賴中后加載覆蓋先加載原則。
?場景2:然后我們改變聲明順序,將client 6.8.13依賴包在client 7.4.2之前聲明;
org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 6.8.13/version?> /dependency?> org.elasticsearch.client/groupId?> elasticsearch-rest-client/artifactId?> 7.4.2/version?> /dependency?> /dependencies?>
?觀察maven實際加載結果如下,發現項目中實際加載的es-rest-client 版本是7.4.2,先聲明的6.8.13版本并未實際加載到項目中。符合同級依賴中后加載覆蓋先加載原則。
四、常見異常
Jar發生沖突后在程序啟動時常見異常報錯,下面四種異常是能夠直觀表征Jar包加載沖突:
?程序拋出java.lang.ClassNotFoundException異常;
?程序拋出java.lang.NoSuchMethodError異常;
?程序拋出java.lang.NoClassDefFoundError異常;
?程序拋出java.lang.LinkageError異常等;
五、總結
之前只是淺層的了解maven包的加載,沒有結合具體的加載原則進行系統的學習驗證,正好通過需求開發中遇到依賴沖突相關問題對maven的加載原則進行探究。ok,明白啦!
審核編輯 黃宇
-
maven
+關注
關注
0文章
30瀏覽量
3698
發布評論請先 登錄
相關推薦
評論