依賴沖突是什么
依賴沖突是
程序在編譯或運行過程中,由于調(diào)用的方法不是期望依賴版本中的方法而導致編譯失敗或運行時異常。
依賴沖突通常表現(xiàn)為:
- 調(diào)用方法不存在
- 參數(shù)或返回類型不匹配
- 運行異?;蚍祷刂挡环项A期
依賴沖突歸因主要有兩點:
- 依賴傳遞機制
依賴傳遞即:項目a直接依賴于b,b直接依賴c,那么傳遞的結果為a間接依賴于c,即a中也可以調(diào)用c的方法,不用再直接生命c。
項目往往有多個依賴,直接依賴與間接依賴間都難免有相同的依賴存在,而版本不同,maven為了保證只有一個依賴被解析使用,遵循2條基本原則:1. 路徑優(yōu)先 2. 聲明優(yōu)先。這樣的擇一去余的方法難免造成最終選擇的依賴不是我們期望的依賴。當我們期望一個高版本而最終解析的是一個低版本時,那很可能造成我們調(diào)用的方法不存在等錯誤。 - 類加載機制
依賴沖突不僅發(fā)生在相同依賴不同版本間,也可能發(fā)生在不同依賴間,它們的特征是有相同的方法限定名(包名+類名+函數(shù)名),JVM的加載機制通常會保證同名類只會被加載一次,這樣就可能導致?lián)碛邢嗤窂矫念悾ò?類名)被加載一次,這樣很可能需要的類沒有被JVM加載。
避免及解決
- 解決
當遇到依賴沖突的時候,通常的做法是找到發(fā)生沖突的依賴來自哪個傳遞依賴,可以通過mvn默認集成插件執(zhí)行mvn dependency:tree 或則通過idea的mvn helper插件分析,然后排除造成沖突的依賴或者在直接依賴中聲明所需版本,如果沒有必須指定特定版本,最好聲明更新版本的依賴。 - 避免
為了盡量避免依賴沖突,盡量直接在pom中聲明所需依賴;另外對項目依賴進行“瘦身”,盡量排除不需要的依賴。
實例介紹
最近用springboot + junit+jsonschema 寫一個簡單的接口測試框架時遇到依賴沖突,運行case 時載入jsonschema報錯如下:
在這里插入圖片描述
-
明確報錯方法調(diào)用入口及被調(diào)用jar
idea追蹤方法調(diào)用的地方,報錯的方法來自com.github.everit-org.json-schema:org.everit.json.schema,顯示調(diào)用的JSONObject類來自com.vaadin.external.google:android-json依賴,
在這里插入圖片描述 -
明確期望被調(diào)用的jar
通過查看com.github.everit-org.json-schema:org.everit.json.schema的pom依賴,得知其依賴的json為org.json:json
在這里插入圖片描述 -
明確被錯誤調(diào)用的jar來源
通過idea的maven helper插件得知com.vaadin.external.google:android-json來自spring-boot-start-test的間接依賴
在這里插入圖片描述 依賴排除
在pom中排除依賴com.vaadin.external.google:android-json
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
<scope>test</scope>
</dependency>
- 驗證及回歸
重新運行測試用例,依賴沖突問題解決。注意:為了確認排除對依賴在項目其它地方?jīng)]有應用,應該進行項目回歸測試。