Maven-Optional Dependencies & Dependency Exclusion


本文討論可選依賴和排除依賴.  幫助用戶理解它們是什么, 如何使用, 它們如何工作, 以及什么時候使用它們最合適. 本文也將解釋為什么排除是基於單個依賴的, 而非POM級別的.

Optional Dependencies

可選依賴用在不能真正地將一個項目划分為多個子模塊時.  一些依賴只在該項目中的某些特性中使用, 並且如果這些特性沒有使用到的話, 這些依賴就不需要.  最理想的情況, 這樣的特性會被划分到一個依賴於核心功能工程的子模塊, 這個新子模塊將只有非可選依賴, 因為一旦你決定使用該子模塊的功能, 你就會需要這些依賴.

然而, 如果該項目無法划分, 這些依賴就需要被聲明為可選的. 如果一個用戶想要使用和一個可選依賴相關的功能, 他們需要在自己的工程里聲明那個可選依賴.  這並不是處理這種情況的最清晰的方式.. 但可選依賴和依賴排除都是 stop-gap 方案.

Why use optional dependencies?

聲明可選依賴不僅僅在節省內存空間問題上很重要. 當一個用戶使用一個工程時, 控制實際需要的依賴列表非常重要. 因為這些jar包可能會最終放入一個WAR, EAR, EJB等等. 包含了錯誤的jar包, 可能會違反許可協議, 引起路徑問題等等.

 How do I use the optional tag?

聲明一個可選依賴, 只需要在你的依賴聲明中簡單地設置 <optional> 標簽為 true. 如下例所示:

image

How do optional dependencies work?

Project-A -> Project-B

如果 project A 依賴於 project B, 當A將B聲明為可選依賴時, 這個關系就確定下來了. 這就像一個正常的構建, B將會被添加到它的類路徑里.

Project-X -> Project-A

但當另一個工程 project X 將工程A聲明為它的依賴時, 可選依賴就發揮效用了. 你會發現, 工程B沒有被包含到X的類路徑中. 你需要在POM中直接聲明B, 才能將它包含到X的類路徑中.

image

Example

假設有一個工程名為X2, 它和Hibernate有相似的功能,  支持很多種數據庫驅動, 比如mysql, postge, oracle等. 構建X2需要所有這些依賴, 但你的項目未必. 所以, 將這些依賴聲明為可選的對X2來說是非常實用的, 這樣無論何時你的項目聲明了X2作為一個直接依賴, X2支持的所有驅動就不會自動地包含到你的工程的類路徑里, 你需要直接聲明你需要的數據庫驅動.

[注意] 在理想情況下, 不應用使用可選依賴. 在面向對象設計中, 有個單一職責性原則, 意指一個類應該只有一項職責, 而不是糅合太多功能. 這個原則在規划maven項目時也同樣適用. 上例中, 更好的做法是為mysql和postgreSQL分別創建一個maven項目, 基於同樣的groupId分配不同的artifactId. 在各自的pom中聲明對應的jdbc驅動依賴, 不使用可選依賴. 用戶根據需要選擇使用. 由於傳遞性依賴的作用, 就不用再聲明jdbc驅動依賴了.

Dependency Exclusions

由於maven 2.x的依賴傳遞規則, 很有可能你的項目類路徑中包含了一些不想要的依賴. 比如說, 你的項目依賴的那些工程可能沒有正確地聲明他們的依賴集合. 為了應對這個特殊的場景, maven2.x提出了依賴排除的概念. 排除是針對POM中的一個特定的依賴設置的, 以一個特定的groupId和artifactId為標識. 如果你聲明了排除依賴, 當你構建你的工程時, 該構件就不會被添加到你的工程的類路徑中.

How to use dependency exclusions

我們在pom的<dependency>部分添加<exclusions>標簽.

image

How dependency exclusion works and when to use it ( as a last resort! )

如下圖所示. 工程A同時依賴於B,C. 而工程B又依賴於D. 默認情況下, A的類路徑會包含: B, C, D, E, F.

如果我們不需要使用工程D, 同時不想把它的依賴添加到A的類路徑中, 因為我們已知D的某些依賴, 比如說E, 在倉庫中找不到了. 而你又不需要工程B中依賴於工程D的那部分功能. 在這種情況下, B的開發者可能會提供一個關於D的可選依賴.

然而!!! 他們沒有提供!!!  作為最后的手段, 你依然可以選擇在你這一側把不想要的依賴排除掉.

image

image

如果我們將工程A發布到一個倉庫, 並且工程X聲明一個關於A的普通依賴, 那么D還會被排除在類路徑之外嗎?

答案是會. 工程A已經聲明了它不需要工程D就可以運行, 所以這會產生一個傳遞的依賴.

現在, 考慮工程X依賴於Y. 工程Y也有一個關於B的依賴, 且它確實需要由工程D支持的特性. 因此, 在它的依賴列表里不會出現排除D的情況. 它也可能提供一個額外的倉庫, 在那里我們可以處理工程E. 在這種情況下, 工程D不是全局排除就非常重要了, 因為它是Y的一個合法依賴.

Why exclusions are made on a per-dependency basis, rather than at the POM level

主要是為了確保依賴關系圖是可預知的, 避免排除了不應排除的依賴. 如果你需要排除, 你應絕對確定你引入的哪個依賴帶來了不必要的依賴傳遞.

Reference

http://maven.apache.org/guides/introduction/introduction-to-optional-and-excludes-dependencies.html

<Maven實戰>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM