Maven用戶都應(yīng)該知道的一些事:關(guān)于依賴的常見問題

依賴范圍(scope)不同選項的區(qū)別

依賴范圍參數(shù)的作用是控制依賴在不同階段與classpath的關(guān)系,具體區(qū)別如下圖所示。

依賴范圍圖

表中沒有列出的值是import,這個選項是用于引入dependencyManagement,下文會有介紹。

依賴調(diào)解,調(diào)解同一依賴的不同版本

假設(shè)你的項目有如下的依賴樹

POM
|-- A
|   `-- B 1.0
|-- C
|   `-- D
|       `-- B 2.0
`-- E
    `-- B 3.0

POM同時依賴了B的1.0和2.0版本,可Maven是不會重復引入相同坐標的依賴的,那么究竟哪個版本會生效呢?

Maven對于依賴的調(diào)解遵循兩個基本原則:

  • 1 依賴路徑長度短者優(yōu)先;
  • 2 如果依賴路徑長度相同,則后聲明優(yōu)先。

所以根據(jù)1,2.0版本被排除,根據(jù)2,3.0版本被實際引入。

如果你自己明確知道該引入哪個版本的B,那么直接在POM中聲明B依賴就好了,因為這時的依賴路徑是最短了。

可選依賴(optional)含義

可選依賴的作用就是聲明該依賴不被傳遞依賴。

POM
`-- A
   `-- B(optional)

這里B不會被引入。

Super POM(Project Object Model)

Super POM是Maven自帶的全局POM文件,所有的POM文件都默認繼承了Super POM。其中定義了各種默認配置,以簡化POM文件的編寫。下面是Maven 3.5.4的Super POM的核心部分。

<project>
  <modelVersion>4.0.0</modelVersion>
 
  <repositories>
    <repository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
    </repository>
  </repositories>
 
  <pluginRepositories>
    <pluginRepository>
      <id>central</id>
      <name>Central Repository</name>
      <url>https://repo.maven.apache.org/maven2</url>
      <layout>default</layout>
      <snapshots>
        <enabled>false</enabled>
      </snapshots>
      <releases>
        <updatePolicy>never</updatePolicy>
      </releases>
    </pluginRepository>
  </pluginRepositories>
 
  <build>
    <directory>${project.basedir}/target</directory>
    <outputDirectory>${project.build.directory}/classes</outputDirectory>
    <finalName>${project.artifactId}-${project.version}</finalName>
    <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <resources>
      <resource>
        <directory>${project.basedir}/src/main/resources</directory>
      </resource>
    </resources>
    <testResources>
      <testResource>
        <directory>${project.basedir}/src/test/resources</directory>
      </testResource>
    </testResources>
    ...

Super POM中定義了中央依賴倉庫、中央插件倉庫,以及各種文件夾的默認路徑。

POM繼承

如果你的項目有多個模塊,通常每個模塊之間會有一些相同的公共的依賴,你可以把依賴聲明在模塊各自的POM中,如下所示。

.
|-- mod A
|   `-- pom.xml
|       `-- P(1.0)
`-- mod B
    `-- pom.xml
        `-- P(1.0)

這樣A模塊和B模塊都依賴了P,但是如果有天你想要修改P的版本,又希望A,B模塊依賴的P版本相同,那就得同時修改POM-A和POM-B,太不優(yōu)雅了。

所以Maven提供了POM繼承功能,讓我們可以吧公共的依賴抽取出來。

.
|-- pom.xml (父POM)
|   `-- P(1.0)
|-- mod A
|   `-- pom.xml
`-- mod B
    `-- pom.xml

做法如上,在父POM中聲明依賴P,在AB模塊的POM中聲明對父POM的繼承,便能實現(xiàn)AB模塊對P依賴的引入。

AB模塊中加入下面一段,便能實現(xiàn)對父POM的繼承。

  <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>my-app</artifactId>
    <version>1</version>
    <relativePath>../pom.xml</relativePath>
  </parent>

relativePath的默認值即是‘../pom.xml’,可以省略。

值得一提的是,這里父POM并不需要知道子POM的信息。

總之,有了繼承,子模塊就能擁有父模塊同樣的依賴。

POM聚合

假設(shè)你的項目有多個模塊,通常每個模塊需要各自單獨構(gòu)建,如果想要所有模塊能同時構(gòu)建,則需要使用Maven的聚合功能。

使用聚合同樣需要建一個父POM

.
|-- pom.xml (父POM)
|-- A
|   `-- pom.xml
`-- B
    `-- pom.xml

父POM內(nèi)容如下:

<project>
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <version>1</version>
  <packaging>pom</packaging>
 
  <modules>
    <module>A</module>
    <module>B</module>
  </modules>
</project>

其中packaging必須是pom,modules中聲明需要聚合的子模塊。
與繼承相反,子POM中不需要父POM的信息。

總之,有了聚合,所有對父模塊執(zhí)行的Maven命令,同樣會對子模塊執(zhí)行。

依賴管理(dependencyManagement)是什么

在前面講繼承的時候,我們通過父POM使得AB兩個模塊都擁有了依賴P,但是如果我們現(xiàn)在添加一個模塊C,模塊C并不需要依賴P,只需要父POM中的其他配置和依賴,該怎么辦呢?

這就要用到dependencyManagement這個配置了,dependencyManagement與dependencies元素不同在于并不會真的引入依賴,只是指定依賴的版本。

做法是在父POM中添加dependencyManagement配置

 <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>groupabc</groupId>
        <artifactId>p</artifactId>
        <version>1.0</version>
      </dependency>
  </dependencyManagement>

然后在AB模塊的POM中添加如下,注意不含版本信息。

  <dependencies>
    <dependency>
      <groupId>groupabc</groupId>
      <artifactId>p</artifactId>
    </dependency>
  </dependencies>  

如此一來,AB模塊都引入了依賴p的v1.0,而模塊C沒有引入依賴p。

另外還有pluginManagement與此類似,不過是針對插件而已。

參考文獻

Introduction to the POM

Introduction to the Dependency Mechanism

《Maven實戰(zhàn)》

轉(zhuǎn)載請保留原文地址:Maven用戶都應(yīng)該知道的一些事:關(guān)于依賴的常見問題

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 直奔主題,課外知識自行腦補。 1、傳遞依賴和繼承依賴 繼承依賴是個啥?就是你定義了一個父模塊,然后子模塊的pom里...
    HighTao_eb74閱讀 2,036評論 0 1
  • 前言 在Java項目開發(fā)中,項目的編譯、測試、打包等是比較繁瑣的,屬于重復勞動的工作,浪費人力和時間成本。以往開發(fā)...
    JourWon閱讀 1,177評論 0 1
  • 逅弈 轉(zhuǎn)載請注明原創(chuàng)出處,謝謝! 以前的日子 以前我們寫代碼時,jar包都默認放在一個叫 /lib 的目錄下,然后...
    逅弈閱讀 3,173評論 3 45
  • 剛剛來新公司,發(fā)現(xiàn)項目中大量的單例使用的雙重檢查鎖方式的單例,但是很奇怪并沒有加volatile修飾詞。認真復習了...
    嘟嘟賭起閱讀 297評論 1 0
  • 不好意思,來晚了。又是忘了更新的一天,每天都在23點快要到了的時候才發(fā)現(xiàn)我的日更沒有更上,好懊惱,好氣憤。 什么時...
    沒有眼神的殺手閱讀 356評論 0 0

友情鏈接更多精彩內(nèi)容