[英]Maven parent POM: Circular dependencies
我們有一個模塊化項目,大約有10個工件:
parent
+- artifact1
+- artifact2
+- artifact3
+- ...
+- artifact10
此外,一些工件彼此之間存在依賴關系:
artifact1
+-> artifact2
+-> artifact3
+-> ...
+-> artifact10
artifact2
+-> artifact3
artifact4
+-> artifact3
artifact4
+-> artifact5
artifact5
+-> artifact6
我們目前的設置如下:
我們使用帶有三個數字的版本控制方案:
<major version>.<minor version>.<patch level>
例如:
0.1.0-SNAPSHOT (a young artifact in development)
0.1.0 (the same artifact once it has been released)
0.1.1 (the same artifact after a hotfix)
問題:
一旦我們更改了工件的版本(例如:0.1.0 => 0.1.1),我們的父工件版本(12.7.3)需要更新,因為它引用了舊的工件版本(0.1.0)。 由於我們在父POM(0.1.0 => 0.1.1)中更改了此引用,因此我們也需要增加父POM的版本(12.7.3 => 12.7.4)。 現在,我們的工件仍然引用了先前的父版本(12.7.3),即我們需要再次更新它...這是循環的。
解決這種循環親子關系的最佳方法是什么? 我們可以從父POM中刪除我們自己的依賴項,並在所有其他工件的POM中定義它們的版本,但這意味着我們需要在依賴項更改后更新所有工件。
編輯
包含我們工件的簡化目錄結構:
.
├── [api:0.14.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main
│ │ ├── java ...
│ │ └── webapp ...
│ └── test
├── [dao:1.21.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [parent:0.11.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [pdf-exporter:0.2.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [docx-exporter:0.3.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
├── [exporter-commons:0.9.0-SNAPSHOT]
│ ├── pom.xml
│ └── src
│ ├── main ...
│ └── test ...
└── [security:0.6.0-SNAPSHOT]
├── pom.xml
└── src
├── main ...
└── test ...
工件目錄(在方括號中;與工件版本一起)彼此獨立,即為方便起見,它們僅在公共根目錄(“。”)中。 每個工件都有自己的git存儲庫。 “api”是部署在應用程序服務器上的工件。 所有工件都像這樣引用“父”(在開發期間):
<parent>
<groupId>com.acme</groupId>
<artifactId>parent</artifactId>
<version>0.11.0-SNAPSHOT</version>
</parent>
<artifactId>api</artifactId>
<version>0.14.0-SNAPSHOT</version>
場景:
問題:api:0.14.0-SNAPSHOT引用父:0.11.0-SNAPSHOT。 api:0.14.0-SNAPSHOT然后更新為引用父:0.12.0-SNAPSHOT。 api:0.14.0-SNAPSHOT變為api:0.15.0-SNAPSHOT。 但是父級中的pom.xml:0.12.0-SNAPSHOT引用api:0.14.0-SNAPSHOT。 =>惡性循環。
(注意:工件名稱是為了簡單起見。)
Maven中混淆的一個主要原因是parent
pom實際上可以包含兩種不同類型的關系:
<parent>
標記內聲明一次 <modules>
標簽在頂級pom中聲明一次 mvn clean install
)將傳遞給子模塊 如果所有模塊保持在同一版本(即始終從頂層執行發布),則此區別無關緊要。 但是只要版本開始碎片化(即釋放一個子模塊而不釋放另一個子模塊),就有必要為每個任務創建2個獨立的pom。
project/
parent/
parent_pom.xml # declare dependency versions as ranges [0.1.0, 0.2.0)
children/
aggregator_pom.xml # <modules> section lists api/dao/etc
api/
pom.xml # declare parent_pom as parent
dao/
pom.xml # declare parent_pom as parent
為什么需要這種復雜的結構?
為什么不直接使用MariuszS建議在頂級父級使用范圍?
想象一下, api
一個基本組件非常穩定。 如果可以避免,您不想重建或重新發布它。
同時,讓我們說兩個相互依賴的組件,如pdf-exporter
和docs
,你經常發布和/或分支,以便你經常更改版本范圍:0.1.x - > 0.2.x - > 0.3.x等。
然后你會被迫修改和釋放你的父pom以反映pdf-exporter
和docs
之間的關系,但你不一定要發布api
因為它不關心這些變化。 因此,需要將父親放在一邊並確保釋放它不會觸發api
子模塊的不必要的重新釋放。
如果有一個共同的根模塊(“父”),所有其它模塊(以下簡稱“兒”)依靠, 沒有一個孩子應該在由母公司依賴。
這是因為Maven以一種非常簡單的方式工作:要構建一個模塊, 首先要構建它所依賴的所有模塊(使用傳遞閉包模型),這些模塊尚未構建。 如果你有一個循環依賴,你最終會遇到這樣的情況:為了構建A,你必須首先建立A。 這很瘋狂,顯然無法以有用的方式運作。
但是,您也可以讓父母將其子項作為子模塊。 這是一種不同的, 不可繼承的關系,它導致子模塊在超級模塊之后構建。 這樣可行。 使超級模塊的子模塊與超級模塊沒有其他關系也是完全合理的。
簡而言之,無論您將模塊安排在磁盤上還是存儲庫中, 都不要引入循環依賴 。 (我已經看到它認為循環依賴應該在邏輯上將一組模塊轉換為單個模塊,因為這是明確定義正確包含運算符操作的唯一方法。我不確定我是否完全贊同,但這並非完全錯誤......)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.