1. 程式人生 > >Maven 可選的依賴和依賴排除

Maven 可選的依賴和依賴排除

聲明 str 列表 解決辦法 ear 傳遞 環境變量 ould pac

轉載自並發編程網 – ifeve.com本文鏈接地址: 《Maven官方指南》可選的依賴和依賴排除

簡介

這節主要討論了可選的依賴排除功能。這將幫助用戶理解它們是什麽,怎麽使用它們,它們是怎麽工作的,和使用它們的最好的方式。同樣也解釋了為什麽排除是在每個依賴的基礎上,而不是在POM級別。

可選的依賴

當不可能把一個項目分裂成子模塊(不管什麽原因)的時候,我們可以使用可選的依賴。它的思想就是:在項目中一些依賴僅僅被某些功能使用,並且如果這個功能不被使用,這個依賴就不需要。理想情況下,根據核心的功能性項目,一個功能被分成子模塊… 如果你決定使用子模塊的功能,因為你必須需要他們的全部,所以新的子項目僅僅有不可選的依賴。

然而,因為這個項目不可能被分成子模塊,所以這些依賴被聲明成可選的。如果一個用戶想要使用和一個可選的依賴相關的功能,他們將不得不在他們自己的項目中重新聲明可選的依賴。用這種方法處理這種情況不是的最好的方式,但是可選的依賴和依賴排除也是一個權宜的解決辦法。

為什麽使用可選的依賴?

聲明可選的依賴,重點不是為了節省空間/內存,因為這些jar最後可能被打進一個WAR、EAR、EJB等,重點是當一個用戶為了使用一個項目時來控制實際的依賴列表。包含了一個錯誤的jar可能會違反一個許可協議,引起環境變量問題等。

怎麽使用可選的標簽?

在你的依賴聲明中,通過簡單的設置<optional> 標簽為true,一個依賴就被聲明為可選的。一個簡單的示例:

<project>
  ...
  <dependencies>
    <!-- declare the dependency to be set as optional -->
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</
scope> <optional>true</optional> <!-- value will be true or false only --> </dependency> </dependencies> </project>

可選的依賴工作原理

Project-A -> Project-B

上面的圖意味著項目A依賴於項目B,當A在它的POM文件中把B聲明為一個可選的依賴,他們的關系依然沒有改變。僅僅就像一次正常的構建,在這次構建中,項目B將會被添加進classpath。

Project-X -> Project-A

但是當一個其他的項目(項目X)在它的POM文件中聲明項目A為一個依賴,這個可選的依賴就發揮作用了。你將會註意到項目X的classpath不會包含項目B:為了把B包含進項目X的classpath,你需要在你的POM文件中直接聲明。

例子:

有一個名為X2的項目,這個項目和hibernate有一些類似的功能,支持許多數據庫驅動/依賴,比如說MySQL,postgre,oracle等。為了構建X2,所有的這些依賴都是必須的,但是對於你的項目來說卻不是必須的,所以對於X2把這些依賴聲明為可選的是非常實用的,不論什麽時候當你在POM文件中把X2聲明為一個直接依賴的時候,所有被X2支持的驅動不會自動的被包含進你的項目的classpath,你需要直接聲明你將要使用的數據庫的依賴/驅動。

依賴排除

因為maven2.X的依賴是傳遞的,可能會把不想要的依賴包含進你的classpath。比如說 ,你所依賴的項目或許沒有正確的設置它們的依賴集。為了處理這種特殊的情況,maven2.x包含了依賴排除的概念。排除在你的POM設置了一個特殊的依賴,並目標到一個特殊的groupId和artifactId,當你構建項目的時候,通過聲明排除依賴,這個特殊的artifactId不會被添加到你的項目的classpath中。

怎麽使用依賴排除:

在pom文件的<dependency>部分增加<exclusions> 標簽:

<project>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectA</groupId>
      <artifactId>Project-A</artifactId>
      <version>1.0</version>
      <scope>compile</scope>
      <exclusions>
        <exclusion>  <!-- declare the exclusion here -->
          <groupId>sample.ProjectB</groupId>
          <artifactId>Project-B</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

依賴排除的工作原理和何時使用它(作為最後一招)

Project-A
   -> Project-B
        -> Project-D <! -- This dependency should be excluded -->
              -> Project-E
              -> Project-F
   -> Project C

上面的圖表表示項目A依賴於整個項目B和項目C,項目B依賴於項目D,項目D依賴於項目E和F,默認情況下,項目A的classpath將包含:

B, C, D, E, F

因為我們知道項目D的一些依賴在倉庫中丟失了,所以,如果我們不想要把項目D和它的依賴添加到項目A的classpath中會怎樣呢?並且你不想要項目B中依賴於項目D的某些功能,在這種情況下,項目B的開發者在項目D的依賴上增加<optional> true</optional>標簽,就像下面這樣:

<dependency>
  <groupId>sample.ProjectD</groupId>
  <artifactId>ProjectD</artifactId>
  <version>1.0-SNAPSHOT</version>
<optional>true</optional>
</dependency>

然而,他們並沒有這麽做。使用最後的手段,你仍然可以把它排除在外,在項目A中,像這樣:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>sample.ProjectA</groupId>
  <artifactId>Project-A</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectD</groupId> <!-- Exclude Project-D from Project-B -->
          <artifactId>Project-D</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

如果我們把項目A部署到倉庫,並且項目X聲明了一個正常的依賴,依賴於項目A,項目D會被從classpath中排除嗎?

Project-X -> Project-A

答案是yes,項目A已經聲明了它不需要項目D,所以項目D不會被傳遞地帶到項目A中。

現在,考慮依賴於項目Y的項目X,就像下面表示的一樣:

Project-X -> Project-Y
               -> Project-B
                    -> Project-D
                       ...

項目Y同樣也有也依賴於項目B,並且它需要一些被項目D支持的特性。因此,不要在這個依賴列表裏放置一個對項目D的排除。它或許會供給一個額外的倉庫,在這個倉庫裏,我們可以依賴項目E。在這個例子裏,項目D不是被全局排除是非常重要的,因為項目Y有一個合理的依賴。

有另外一種情況,如果我們不想要項目E,而不是項目D,該怎麽去排除呢?看看下面的圖:

Project-A
   -> Project-B
        -> Project-D
              -> Project-E <!-- Exclude this dependency -->
              -> Project-F
   -> Project C

整個依賴的排除工作在我們聲明的點下進行。如果你想要排除項目E,你只需要改變排除的點,但是你不能在項目D進行排除,你不能改變項目D的POM文件,如果可以,就會使用可選的依賴而不是排除了,或者簡單的把項目D分成子模塊,

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>sample.ProjectA</groupId>
  <artifactId>Project-A</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>jar</packaging>
  ...
  <dependencies>
    <dependency>
      <groupId>sample.ProjectB</groupId>
      <artifactId>Project-B</artifactId>
      <version>1.0-SNAPSHOT</version>
      <exclusions>
        <exclusion>
          <groupId>sample.ProjectE</groupId> <!-- Exclude Project-E from Project-B -->
          <artifactId>Project-E</artifactId>
        </exclusion>
      </exclusions>
    </dependency>
  </dependencies>
</project>

為什麽排除是在每個依賴的基礎上,而不是在POM級別

這用來保證依賴圖是可預測的,並從排除一個依賴保持繼承效果。如果你采取了最後的手段並放置了一個排除,你應該能絕對的確認哪個依賴被帶進了一個不想要的傳遞依賴。

Maven 可選的依賴和依賴排除