(轉)Maven中的DependencyManagement和pluginmanagement


背景:最近在學習maven的多模塊構建過程中看到DependencyManagement選項,對這個選項的使用做個記錄!

 區別與聯系

這里介紹一個在父項目中的根結點中聲明dependencyManagement和dependencies的區別

dependencyManagement使用

dependencyManagement只會影響現有依賴的配置,但不會引入依賴。

例如我們可以在父模塊中配置如下:

<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactid>junit</artifactId>
      <version>4.8.2</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactid>log4j</artifactId>
      <version>1.2.16</version>
    </dependency>
  </dependencies>
</dependencyManagement>

這段配置不會給任何子模塊引入依賴,但如果某個子模塊需要使用JUnit和Log4j的時候,我們就可以簡化依賴配置成這樣:

 <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
  </dependency>

現在只需要groupId和artifactId,其它元素如version和scope都能通過繼承父POM的dependencyManagement得到,如果有依賴配置了exclusions,那節省的代碼就更加可觀。但重點不在這,重點在於現在能夠保證所有模塊使用的JUnit和Log4j依賴配置是一致的。而且子模塊仍然可以按需引入依賴,如果我不配置dependency,父模塊中dependencyManagement下的spring-aop依賴不會對我產生任何影響。

也許你已經意識到了,在多模塊Maven項目中,dependencyManagement幾乎是必不可少的,因為只有它是才能夠有效地幫我們維護依賴一致性。

dependencies

相對於dependencyManagement,所有聲明在dependencies里的依賴都會自動引入,並默認被所有的子項目繼承。

classifier

如果你要發布同樣的代碼,但是由於技術原因需要生成兩個單獨的構件,你就要使用一個分類器(classifier)。例如,如果你想要構建兩個單獨的構件成JAR,一個使用Java 1.4 編譯器,另一個使用Java 6 編譯器,你就可以使用分類器
來生成兩個單獨的JAR構件,它們有同樣的groupId:artifactId:version組合。如果你的項目使用本地擴展類庫,你可以使用分類器為每一個目標平台生成一個構件。分類器常用於打包構件的源碼,JavaDoc 或者二進制集合。

dependencyManagement精進

我們知道Maven的繼承和Java的繼承一樣,是無法實現多重繼承的,如果10個、20個甚至更多模塊繼承自同一個模塊,那么按照我們之前的做法,這個父模塊的dependencyManagement會包含大量的依賴。

如果你想把這些依賴分類以更清晰的管理,那就不可能了,import scope依賴能解決這個問題。你可以把dependencyManagement放到單獨的專門用來管理依賴的POM中,然后在需要使用依賴的模塊中通過import scope依賴,就可以引入dependencyManagement。

例如可以寫這樣一個用於依賴管理的POM

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.juvenxu.sample</groupId>
  <artifactId>sample-dependency-infrastructure</artifactId>
  <packaging>pom</packaging>
  <version>1.0-SNAPSHOT</version>
  <dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>junit</groupId>
          <artifactid>junit</artifactId>
          <version>4.8.2</version>
          <scope>test</scope>
        </dependency>
        <dependency>
          <groupId>log4j</groupId>
          <artifactid>log4j</artifactId>
          <version>1.2.16</version>
        </dependency>
    </dependencies>
  </dependencyManagement>
</project>

 

然后我就可以通過非繼承的方式來引入這段依賴管理配置:

<dependencyManagement>
    <dependencies>
        <dependency>
          <groupId>com.juvenxu.sample</groupId>
          <artifactid>sample-dependency-infrastructure</artifactId>
          <version>1.0-SNAPSHOT</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
    </dependencies>
  </dependencyManagement>

  <dependency>
    <groupId>junit</groupId>
    <artifactid>junit</artifactId>
  </dependency>
  <dependency>
    <groupId>log4j</groupId>
    <artifactid>log4j</artifactId>
  </dependency>

 

這樣,父模塊的POM就會非常干凈,由專門的packaging為pom的POM來管理依賴,也契合的面向對象設計中的單一職責原則。此外,我們還能夠創建多個這樣的依賴管理POM,以更細化的方式管理依賴。

這種做法與面向對象設計中使用組合而非繼承也有點相似的味道。

plugins和pluginmanagement的區別

pluginmanagement標簽一般用在父pom中,子元素可以包含plugins插件,比如

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-source-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <attach>true</attach>
            </configuration>
            <executions>
                <execution>
                    <phase>compile</phase>
                    <goals>
                        <goal>jar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</pluginManagement>

然后,在子pom文件中就可以這樣使用:

<plugins>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-source-plugin</artifactId>
    </plugin>
</plugins>

省去了版本、配置等信息,只需指定groupId和artifactId即可。

但是在父pom中,如果使用這個標簽來包裹plugins插件,當在此項目根目錄運行對應的mvn命令時,如果在子pom中沒有直接像上面再次引用這個plugin,那么不會觸發這個plugin插件,只有在子pom中再次引用了之后,才會在對應的子項目路徑下觸發這個plugin.

plugins和pluginManagement標簽都需要在build標簽中。

關於插件pluginManagement,Maven並沒有提供與import scope依賴類似的方式管理,那我們只能借助繼承關系,不過好在一般來說插件配置的數量遠沒有依賴配置那么多,因此這也不是一個問題。

 


免責聲明!

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



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