依賴範圍(scope)不同選項的區別
依賴範圍參數的作用是控制依賴在不同階段與classpath的關係,具體區別如下圖所示。
表中沒有列出的值是import,這個選項是用於引入dependencyManagement,下文會有介紹。
依賴調解,調解同一依賴的不同版本
假設你的項目有如下的依賴樹
POM
|-- A
| `-- B 1.0
|-- C
| `-- D
| `-- B 2.0
`-- E
`-- B 3.0
POM同時依賴了B的1.0和2.0版本,可Maven是不會重複引入相同座標的依賴的,那麼究竟哪個版本會生效呢?
Maven對於依賴的調解遵循兩個基本原則:
- 1 依賴路徑長度短者優先;
- 2 如果依賴路徑長度相同,則後聲明優先。
所以根據1,2.0版本被排除,根據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,太不優雅了。
所以Maven提供了POM繼承功能,讓我們可以吧公共的依賴抽取出來。
.
|-- pom.xml (父POM)
| `-- P(1.0)
|-- mod A
| `-- pom.xml
`-- mod B
`-- pom.xml
做法如上,在父POM中聲明依賴P,在AB模塊的POM中聲明對父POM的繼承,便能實現AB模塊對P依賴的引入。
AB模塊中加入下面一段,便能實現對父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聚合
假設你的項目有多個模塊,通常每個模塊需要各自單獨構建,如果想要所有模塊能同時構建,則需要使用Maven的聚合功能。
使用聚合同樣需要建一個父POM
.
|-- pom.xml (父POM)
|-- A
| `-- pom.xml
`-- B
`-- pom.xml
父POM內容如下:
<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的信息。
總之,有了聚合,所有對父模塊執行的Maven命令,同樣會對子模塊執行。
依賴管理(dependencyManagement)是什麼
在前面講繼承的時候,我們通過父POM使得AB兩個模塊都擁有了依賴P,但是如果我們現在添加一個模塊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 Dependency Mechanism
轉載請保留原文地址:Maven用戶都應該知道的一些事:關於依賴的常見問題