2013-02-13 70 views
21

我們正在開發Mavenizing我們的java項目,並且我們希望爲每個模塊在接口和實現之間設置一個乾淨的分隔。 爲了做到這一點,我們希望將每個模塊分成兩個子模塊,一個用於接口和數據對象,另一個用於實現。 例如:maven - 用於接口和用Spring實現的獨立模塊

+commons 
    +commons-api 
    +commons-impl 

的模塊的多金屬氧酸鹽將被構造成使得沒有模塊依賴於IMPL子模塊。這樣,一個模塊中的任何代碼都不能「看到」另一個模塊的實現細節。

我們遇到的問題是在哪裏放置我們的spring XML。 在我們的項目中,我們使用通配符進口自動進口彈簧XML文件,如

<import resource="classpath*:**/*-beans.xml"/>

這樣春天個XML的位置並不重要,在運行時,所有的模塊得到加載到相同的類加載器和,POM中嚴格的單向依賴關係規則不適用。

然而,在開發過程中,我們希望IDE - 我們使用IntelliJ IDEA的 - 承認從春天個XML引用的實現類。 我們也希望IDEA識別在其他模塊中定義的bean。

如果我們把API子模塊春天個XML - 他們不會「看見」在IMPL子模塊的實現類。 如果我們將它們放在impl子模塊中,它們的bean將不會從其他模塊「看到」。 也許可以將IDEA項目配置爲從沒有依賴關係的模塊中識別spring XML,但我們更喜歡我們的POM保存所有項目結構信息,而不依賴於IDEA項目文件。

我們考慮建立第三子模塊剛剛舉行春季個XML(或許冬眠個XML以及)。例如:

+commons 
    +commons-api 
    +commons-impl 
    +commons-config 

外部模塊將取決於兩個公地-API公地配置公地配置將取決於兩個公地-API公地IMPL,依賴於commons-impl標記爲「提供」(以防止傳遞性解析)。

然而,這似乎是一個複雜而尷尬的解決方案,我們覺得必須有一個更好 - 更簡單的方式來實現與Maven和Spring接口/ IMPL分離。

+2

很好的問題,但沒有答案呢?真是可惜.. – cirit 2015-07-15 12:18:04

+1

@cirit同意 - 開始賞金 – drewmoore 2015-10-01 12:06:56

回答

1

總之你想要理念覆蓋Maven的依賴關係圖,但要避免在保持想法的項目文件這個配置?

一種選擇是在Maven配置文件中對實現依賴關係進行分組。此配置文件默認情況下不會啓用,但您應該能夠將其標記爲主動。

+0

我不想完全重寫圖表,我只想讓Spring XML文件在Maven項目中可見,其中不存在依賴關係... – dkarlinsky 2013-02-14 15:27:59

1

兩個想法浮現在腦海中:

  1. 你將有一個(或多個)模塊,所有模塊(API + implement執行)的依賴,也可以有把你的Spring配置文件。
  2. 將spring配置文件放在api模塊中,並聲明對範圍爲provided的impl模塊的依賴關係,這樣實現將是已知的,而api對於部署沒有依賴性。
6

你需要的是一個運行時依賴範圍:

運行 - 此範圍表明依賴不需要編譯,而是執行。它在運行時和測試類路徑中,但不在編譯類路徑中。

https://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html

定義到您在*個-beans.xml配置使用IMPL類另一個IMPL模塊從一個IMPL模塊運行時的依賴。 Intellij將在spring配置文件中正確識別它,但不會在代碼中自動完成它們(但它將在測試代碼中完成)。

此外,如果有人使用代碼中的類,通過maven編譯將失敗,因爲運行時依賴不在編譯類路徑。在外部模塊

1
  • 公地IMPL在運行範圍

    1. 公地(POM dependencyManagement)=>

      +公地-API(編譯)

      +公地IMPL(編譯)

      + commons-config(編譯)

    2. 公地IMPL(POM依賴性)=>

      +公地-API(編譯)

      +公地配置(編譯)

    3. 外部模塊(POM依賴性)=>

      +公地IMPL(運行時

      +公地-API(編譯)

      +公地配置(編譯)

2

可以實現API和實現解耦是這樣的:

+ 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> 

如果配置模塊僅包含彈簧應用程序上下文配置,則可以省略配置模塊。應用程序配置xml應位於包含要部署的工件的模塊的類路徑和文件夾結構中。所以如果你正在構建一個戰爭工件,應用程序的上下文應該在那裏。

應該在您的公共模塊中的唯一配置將在您的impl模塊的測試包中。

1
  1. 保持模塊數量儘可能少;

    這加快了項目建設時間並簡化了佈局。

  2. 保持模塊結構儘可能簡單:單個根目錄+同一文件夾中的所有子模塊, G。:

    pom.xml 
    commons-api/ 
    commons-runtime/ 
    module-a-api/ 
    module-a-runtime/ 
    ... 
    

這簡化在整個項目中,當模塊的數量是非常高(> 50)

  • 提供運行時範圍的依賴關係到運行時的導航模塊只有在需要時;

    這可以保持您的架構清晰。使用mock而不是顯式依賴於另一個運行時模塊。

  • 在api模塊中保留你的api spring上下文,將你的public bean定義爲抽象bean +接口;

  • 在運行時模塊中保留您的實現上下文,通過彈簧配置文件使用您的實現覆蓋api bean(使用< beans profile =「default」)。

  • 結果:簡單,透明的佈局和設計;完整的IDE支持;在運行時模塊內部沒有明確的依賴關係。