介绍
本节可选的依赖项和排除依赖项。将帮助我们了解它们是什么,合适以及如何使用。它还解释了为什么排除是基于每个依赖项而不是POM级别。
可选依赖项
可选的依赖项用于无法(无论出于何种原因)将项目分割为子模块的情况。其思想是,一些依赖项仅用于项目中的某些特性,如果不使用该特性,则不需要这些依赖项。理想情况下,这样的特性应该被分割成依赖于核心功能项目的子模块。这个新的子项目将只有非可选的依赖项,因为如果决定使用子项目的功能,将需要所有这些依赖项。
然而,由于项目不能分割(同样,出于某种原因),这些依赖项声明为可选的。如果用户希望使用与可选依赖项相关的功能,他们必须在自己的项目中重新声明该可选依赖项。这不是处理这种情况的最清晰的方法,但是可选的依赖项和排除依赖项都是权宜之计。
为什么使用可选依赖项
可选的依赖项可以节省空间和内存。它们可以防止违反许可协议或导致类路径问题的jar被捆绑到WAR、EAR、fat jar或类似的文件中。
如何使用可选标记
通过在依赖项声明中将<optional>
元素设置为true,可以将依赖项声明为optional:
|
|
可选依赖项如何工作
|
|
上面的图表表示项目A依赖于项目B。当A在其POM中将B声明为可选依赖项时,此关系保持不变。它就像一个普通的构建,项目B将被添加到项目A的类路径中
|
|
当另一个项目(Project-X)在其POM中将Project-A声明为依赖项时,依赖项的可选性质就会生效。Project-B不包含在Project-X的类路径中。您需要在项目X的POM中直接声明它,以便将B包含在X的类路径中。
例子
假设有一个名为X2的项目具有与Hibernate类似的功能。它支持许多数据库,如MySQL、PostgreSQL和Oracle的几个版本。每个支持的数据库都需要额外的驱动jar包依赖。在编译时构建X2需要所有这些依赖项。但是,我们的数据库只使用一个特定的数据库,不需要为其它数据库提供驱动。X2可以将这些依赖项声明为可选的,这样当项目在其POM中将X2声明为直接依赖项时,X2支持的所有驱动程序不会自动包含在项目的类路径中。项目必须为它所使用的数据库包含对特定驱动程序的显式依赖。
依赖项排除
由于Maven是临时解决依赖项的,所以不需要的依赖项可能包含在项目的类路径中。例如,某个较旧的jar可能存在安全问题,或者与我们正在使用的Java版本不兼容。为了解决这个问题,Maven允许我们排除特定的依赖项。排除是在POM中的特定依赖项上设置的,并且针对特定的groupId和artifactId。在构建项目时,不会将声明了排除依赖关系的项目添加到类路径中。
如何使用依赖排除
在包含有问题的jar的<dependency>
元素中添加< exclude >
元素。
|
|
依赖排除是如何工作的以及什么时候使用它
|
|
该图显示项目A同时依赖于项目B和项目C。项目B依赖于项目D。项目D同时依赖于项目E和F。默认情况下,项目A的类路径包括:
|
|
假设我们不希望将项目D及其依赖项添加到项目A的类路径中,因为存储库中缺少一些项目D的依赖项,而且也不需要项目B中依赖于项目D的功能。项目B的开发人员可以标记对项目D设置<optional>true</optional>
依赖关系:
|
|
不幸的是,他们没有。最后,我们可以将其排除在您自己的项目POM中,如下所示:
|
|
如果将Project-A部署到存储库中,并且Project-X声明了对Project-A的正常依赖关系,那么Project-D仍然会被排除在类路径之外吗?
|
|
答案是肯定的。Project-A已经声明它不需要Project-D来运行,所以它不会作为Project-A的传递依赖项被引入。
现在,考虑项目X依赖于项目Y,如下图所示:
|
|
Project-Y也依赖Project-B,它确实需要Project-D支持的特性。因此,它不会在依赖项列表中排除Project-D。它还可以提供一个额外的存储库,用于解析Project-E。在这种情况下,重要的是Project-D没有被全局排除,因为它是Project-Y的合法依赖项。
作为另一种场景,假设您不想要的依赖项是Project-E而不是Project-D。如何排除它?如下图所示:
|
|
如果您想要排除Project-E而不是Project-D,只需将排除更改为指向Project-E,但不会将排除移动到Project-D。您不能更改Project-D的POM。如果可以,您可以使用可选的依赖项而不是排除项,或者将Project-D分割成多个子项目,每个子项目只有正常的依赖项。
|
|
为什么排除是基于每个依赖项而不是POM级别
这主要是为了确保依赖关系图是可预测的,并防止继承效果排除不应该排除的依赖关系。如果使用最后一种方法,并且必须放入一个排除,那么应该完全确定是哪个依赖项引入了不需要的传递依赖项。
如果我们确实希望确保某个特定的依赖项在类路径中不出现,无论路径如何,都可以将禁用的依赖项规则(bannedDependencies
)配置为在发现有问题的依赖项时构建失败。当构建失败时,您需要在执行者找到的每个路径上添加特定的排除。