7.1 maven依赖传递
简介/优点:
Maven通过自动包含传递依赖项,避免了发现和指定您自己的依赖项所需的库的需要。
通过从指定的远程存储库读取依赖项的项目文件,可以简化此功能。一般来说,这些项目的所有依赖项都将在您的项目中使用,就像项目从其父或依赖项等继承的任何依赖项一样。
依赖项的传递深度是没有限制的。只有在发现循环依赖项时才会出现问题(依赖冲突)。
问题:
通过传递依赖关系,包含的库的图可以迅速增长到相当大的规模。出于这个原因,有一些额外的特性来限制传递哪些依赖项。
限制传递的特性:
特性 | 特性描述 |
---|---|
Dependency mediation (依赖调节) | 当依赖在不同依赖路径上同时出现时,决定哪个依赖版本将会被使用。 如果俩个依赖版本的在依赖树中的深度不一样,深度小的版本将会被使用;如果两个依赖版本在依赖树里的深度是一样的时候,第一个被声明的依赖将会被使用。 |
Dependency management(依赖管理) | 直接指定或者使用dependencyManagement在传递依赖项中或在没有指定版本的依赖项中遇到工件时要使用的构建版本。 |
Dependency scope (依赖范围) | 给依赖项配置scope指定该依赖的依赖范围 (compile, runtime, test, system, import, provided ) |
Excluded dependencies (依赖排除) | 任何可传递的依赖都可以通过 “exclusion” 元素被排除在外。举例说明,A 依赖 B, B 依赖 C,因此 A 可以标记 C 为 “被排除的”。 |
Optional dependencies(依赖可选) | 任何可传递的依赖可以被标记为可选的,通过使用 “optional” 元素。例如:A 依赖 B, B 依赖 C。因此,B 可以标记 C 为可选的, 这样 A 就可以不再使用 C。 |
建议:
尽管传递依赖关系可以隐式地包含所需的依赖关系,但最好还是显式地指定源代码直接使用的依赖关系。
7.2 maven依赖传递的范围
范围 | 描述 |
---|---|
compile(编译阶段) | 默认取值。编译依赖范围指 在项目的所有类路径中都可用,而且,这些依赖关系被传播到依赖项目。 |
provided (供应阶段) | 与compile很相似,特指JDK或容器在运行时提供依赖项。例如,当为Java企业版构建web应用程序时,你会将Servlet API和相关Java EE API的依赖设置为provided ,因为web容器提供了这些类。具有此作用域的依赖项被添加到用于编译和测试的类路径,而不是运行时类路径。它不具有传递性的。 |
runtime(运行阶段) | 此范围指示编译不需要依赖项,但运行需要该依赖项。Maven在运行时和测试类路径中包含此作用域的依赖项,但不在编译类路径中。 |
test(测试阶段) | 此范围表明该依赖项对于应用程序的正常使用不是必需的,并且仅在测试编译和执行阶段可用。这个范围是不可传递的。通常,这个范围用于JUnit和Mockito等测试库。它也用于非测试库,如:Apache Commons IO,如果这些库在单元测试(src/test/java)中使用,但不在模型代码(src/main/java)中使用。 |
system(系统阶段) | 类似于provided ,不同在于必须显式地提供JAR的路径。构件总是可用的,并且不需要在存储库中查找。该范围需要提供一个系统路径。 |
import(导入阶段) | import仅支持定义<dependencyManagement> 的依赖项。它表示依赖项将被指定POM的<dependencyManagement> 节中的有效依赖项列表替换。由于它们被替换,import依赖项实际上并不参与限制依赖项的传递性。 |
举例
scope:system (已弃用)
<!-- JDBC标准扩展或Java身份验证和授权服务(JAAS)-->
<project>
...
<dependencies>
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
</dependencies>
...
</project>
<!-- 构建是由JDK的tools.jar提供的,那么系统路径将定义如下-->
<project>
...
<dependencies>
<dependency>
<groupId>sun.jdk</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
...
</project>
7.3 scope:provided 和optional:true的区别
在提供方,将依赖的范围定义为不传递有俩种方式,俩种方式功能上一致,语义上不同:
- provided
- true
optional 可选的
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
可以理解为此功能/此依赖可选,如果不需要某项功能,可以不引用这个包
scope provided 提供的
<dependency>
<groupId>org.apache.submarine</groupId>
<artifactId>server-api</artifactId>
<scope>provided</scope>
</dependency>
可以理解为此包不由我直接提供 需要调用者/容器提供