[英]maven - separate modules for interfaces and implementation with Spring
我們正在研究Mavenizing我們的java項目,我們希望在每個模塊的接口和實現之間建立一個清晰的分離。 為了做到這一點,我們希望將每個模塊分成兩個子模塊,一個用於它們使用的接口和數據對象,另一個用於實現。 例如:
+commons
+commons-api
+commons-impl
將配置模塊的POM,使得沒有模塊依賴於impl子模塊。 這樣,來自一個模塊的代碼就無法“看到”另一個模塊的實現細節。
我們遇到麻煩的是,將Spring XML放在哪里。 在我們的項目中,我們使用通配符導入自動導入spring XML文件
<import resource="classpath*:**/*-beans.xml"/>
這樣,Spring XML的位置在運行時並不重要,因為所有模塊都被加載到同一個類加載器中,並且POM中嚴格的單向依賴規則不適用。
但是,在開發過程中,我們希望IDE(我們使用Intellij IDEA)識別從spring XML引用的實現類。 我們還希望IDEA識別其他模塊中定義的bean。
如果我們將spring XML放在API子模塊中 - 它們將不會“看到”impl子模塊中的實現類。 如果我們將它們放在impl子模塊中,它們的bean將不會從其他模塊中“看到”。 可能可以將IDEA項目配置為從沒有依賴項的模塊中識別spring XML,但我們更喜歡POM保存所有項目結構信息而不依賴於IDEA項目文件。
我們考慮創建第三個子模塊只是為了保存Spring XML(也許還有hibernate xmls)。 例如:
+commons
+commons-api
+commons-impl
+commons-config
外部模塊將依賴於commons-api和commons-config , commons-config將依賴於commons-api和commons-impl ,並且依賴於commons-impl標記為“提供”(以防止傳遞解析)。
然而,這似乎是一個復雜而笨拙的解決方案,我們認為必須有一個更好 - 更簡單的方法來實現與Maven和Spring的接口/ impl分離。
您需要的是運行時依賴范圍:
runtime - 此范圍指示編譯不需要依賴項,但是用於執行。 它位於運行時和測試類路徑中,但不是編譯類路徑。
( https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html )
定義從一個impl模塊到另一個impl模塊的運行時依賴關系,您可以在其中使用* -beans.xml配置中的impl類。 Intellij會在spring配置文件中正確識別它,但不會在代碼中自動完成它們(但它會在測試代碼中完成)。
此外,如果有人在代碼中使用這些類,則通過maven進行編譯會失敗,因為運行時依賴性不在編譯類路徑上。
你可以像這樣實現api和impl的解耦:
+ commons (pom)
+ pom.xml <--- serves as a parent aggregator (see below)
+ commons-api (jar) <--- contains models, interfaces and abstract classes only
+ commons-impl (jar) <--- depends on commons-api
+ commons-config (jar) <--- depends on commons-impl only (no need to depend on commons-api as it is brought in transitively)
+ external-project (war or jar) <--- has commons-config as a dependency
父聚合器pom(指定構建順序):
<modules>
<module>commons-api</module>
<module>commons-impl</module>
<module>commons-config</module>
</modules>
如果配置模塊僅包含spring應用程序上下文配置,則可以省略它。 應用程序配置xml應位於包含要部署的工件的模塊的類路徑和文件夾結構中。 因此,如果您正在構建戰爭工件,應用程序上下文應該在那里。
應該在commons模塊中的唯一配置是在impl模塊的測試包中。
簡而言之,您希望Idea覆蓋maven依賴關系圖,但避免將此配置保留在想法項目文件中?
一種選擇是在maven配置文件中對實現依賴性進行分組。 默認情況下不會啟用此配置文件,但您應該能夠在想法下將其標記為活動狀態。
想到兩個想法:
provided
這樣的實施方式將是已知的,而沒有該API為部署的依賴性。 commons-impl在外部模塊的運行時范圍內
公共(pom dependencyManagement)=>
+ commons-api(編譯)
+ commons-impl(編譯)
+ commons-config(編譯)
commons-impl(pom dependencies)=>
+ commons-api(編譯)
+ commons-config(編譯)
外部模塊(pom依賴)=>
+ commons-impl( 運行時 )
+ commons-api(編譯)
+ commons-config(編譯)
保持模塊數量盡可能少;
這加快了項目構建時間並簡化了布局。
保持模塊結構盡可能簡單:單根+同一文件夾中的所有子模塊,例如:
pom.xml commons-api/ commons-runtime/ module-a-api/ module-a-runtime/ ...
當模塊數量非常高(> 50)時,這簡化了項目的導航
僅在需要時為運行時模塊提供運行時范圍的依賴關系;
這可以保持您的架構清晰。 使用mocks而不是顯式依賴於另一個運行時模塊。
在api模塊中保存api spring上下文,將公共bean定義為abstract bean + interface;
將您的實現上下文保留在運行時模塊中,通過spring配置文件覆蓋api bean(使用<beans profile =“default”)。
結果:簡單,透明的布局和設計; 全力支持; 沒有對運行時模塊內部的顯式依賴。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.