Maven 基礎(二) | 解決依賴衝突的正確姿式

1、依賴原則

假設,在 JavaMavenService2 模塊中,log4j 的版本是 1.2.7,在 JavaMavenService1 模塊中,它雖然繼承於 JavaMavenService2 模塊,可是它排除了在 JavaMavenService2 模塊中繼承 1.2.7 的版本,本身引入了1.2.9log4j版本。html

此時,相對於 WebMavenDemo 而言,log4j.1.2.7.jar 的依賴路徑是 JavaMavenService1 >> JavaMavenService2 >> log4j.1.2.7.jar,長度是 3;而 log4j.1.2.9.jar 的依賴路徑是 JavaMavenService1 >> log4j.1.2.7.jar 長度是 2。前端

因此 WebMavenDemo 繼承的是 JavaMavenService1 模塊中的 log 版本,而不是 JavaMavenService2 中的,這叫路徑優先原則(誰路徑短用誰)java

依賴原則

此外,在路徑相同的狀況下,python

路徑相同

這種場景依賴關係發生了變化,WebMavenDemo 項目依賴 Sercive1Service2,它倆是同一個路徑,那麼誰在 WebMavenDemopom.xml 中先聲明的依賴就用誰的版本。這叫先定義先使用原則linux

好比:先聲明 JavaMavenService1 因此 WebMavenDemo 繼承它的 log4j.1.2.9.jar 依賴c++

<!--先聲明 JavaMavenService1 因此 WebMavenDemo 繼承它的 log4j.1.2.9.jar 依賴-->
<dependency>
    <groupId>com.nasus</groupId>
    <artifactId>JavaMavenService1</artifactId>
    <version>1.0.0</version>
</dependency>
<dependency>
    <groupId>com.nasus</groupId>
    <artifactId>JavaMavenService2</artifactId>
    <version>1.0.0</version>
</dependency>
  • 參考:cnblogs.com/hzg110/p/6936101.html

2、依賴衝突的緣由

項目的依賴 service1 和依賴 service2 同時引入了依賴 log4j。這時,若是依賴 log4jservice1service2 中的版本不一致就可能致使依賴衝突。以下圖:算法

依賴衝突的緣由

注意,上面我用的是可能,並非說知足上面的條件就必定會發生依賴衝突。由於 maven 遵循上面提到的兩個原則:編程

  • 先定義先使用原則 (路徑層級相同狀況下)
  • 路徑優先原則(誰路徑短用誰)

2.1 依賴衝突會報什麼錯?

依賴衝突一般兩個錯:NoClassDefFoundErrorNoSuchMethodError,逐一講解下致使這兩種錯誤的緣由:小程序

  • 以上圖依賴關係爲例,假設 WebDemo 經過排除 service1 中低版本的依賴,從而繼承 service2 中的高版本的依賴。這時,若是 WebDemo 在執行過程當中調用 log4j(1.2.7) 有,可是升級到 log4j(1.2.9)就缺失的類 log,就會致使運行期失敗,出現很典型的依賴衝突時的 NoClassDefFoundError 錯誤。
  • 仍是以上圖依賴關係爲例,WebDemo 經過排除 service1 中低版本的依賴,從而繼承 service2 中的高版本的依賴。WebDemo 調用了原來 log4j(1.2.7) 中有的方法 log.info(),但升級到 log4j(1.2.7) 後,log.info() 不存在了,就會拋出 NoSuchMethodError 錯誤.

因此說,當存在依賴衝突時,僅期望 maven 的兩個原則來解決是不成熟的。不論是路徑優先原則仍是先定義先使用原則,都有可能形成以上的依賴衝突。那麼如何解決它呢?微信

3、解決依賴衝突

經過上面的分析咱們應該能理解到,解決依賴衝突的核心就是使衝突的依賴版本統一,並且項目不報錯

咱們能夠經過運行 maven 命令:mvn dependency:tree 查看項目的依賴樹分析依賴,看那些以來有衝突,仍是以上圖舉例:運行命令以後,查看依賴樹的 log4j 依賴就會獲得錯誤提示: (1.2.7 omitted for conflict with 1.2.9)

知道了如何查看衝突以後,就是解決衝突。

一、嘗試升高 service2 的版本使他依賴的 log 版本與 service1log 版本一致,但它可能會致使 service2 不能工做。

二、若是 service2 是個舊項目,找遍了也沒找到與 service1 版本一致的 log,這時能夠嘗試拉低 service1 的版本使他依賴的 log 版本與 service2log 版本一致,但可能會致使 service1 不能工做。

你可能說了,這又不行,那又不行,怎麼辦呢?別急,往下看,maven 解決依賴衝突主要用兩種方法:

  • 排除低版本,直接用高版本

最理想的情況就是直接排除低版本,依賴高版本,通常狀況下高版本會兼容低版本。若是 service2 並無調用 log4j.1.2.9 升級所摒棄的方法或類時, 可使用 <exclusion> 標籤,排除掉 service2 中的 log。仍是以上圖舉例:

<dependency>
    <groupId>com.nasus</groupId>
    <artifactId>service2</artifactId>
    <version>1.0.0</version>
    <!-- 排除低版本 log4j -->
    <exclusions>
        <exclusion>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
        </exclusion>
    </exclusions>
</dependency>

看着到這裏,你可能又說了。若是 service2 有用到 log 升級所摒棄的方法或類;而 service1 又必須用新版本的 log,怎麼辦?

第一,通常狀況下,第三方依賴不會出現這種狀況。若是出現了,那你就到 maven 中央倉庫找下兼容兩個版本的依賴。若是找不到,那隻能換依賴。

第二,若是是本身公司的 jar 出現這種狀況,那就是大家的 jar 管理很是混亂。建議從新開發,兼容舊版本。

4、使用 Maven Helper 插件解決依賴衝突

idea plugin 中搜索 maven helper 插件安裝完以後,打開 pom 文件,發現左下角有個 Depandency Analyzer 選項,點擊進入選 conflicts 選項,就能夠看到當前有衝突的 jar 包,在右邊 exclude 掉紅色衝突的版本便可。

解決衝突

最後

若是看到這裏,喜歡這篇文章的話,請轉發、點贊。微信搜索「一個優秀的廢人」,歡迎關注。

回覆「1024」送你一套完整的 java、python、c++、go、前端、linux、算法、大數據、人工智能、小程序以及英語教程。

回覆「電子書」送你 50+ 本 java 電子書。

編程語言

相關文章
相關標籤/搜索