具有不同范围的依赖内的Maven依赖

时间:2009-09-08 23:36:57

标签: java maven-2

假设我在下面的项目中定义了两个Maven依赖项。

    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.3.1</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>mycompany.library</groupId>
        <artifactId>mylibrary</artifactId>
        <version>1.0.1</version>
        <scope>compile</scope>
    </dependency>

然后,在mylibrary中,我也有一个依赖定义如下。

    <dependency>
        <groupId>com.thoughtworks.xstream</groupId>
        <artifactId>xstream</artifactId>
        <version>1.3.1</version>
        <scope>compile</scope>
    </dependency>

当我打包我的项目时,我没有看到xstream打包在其中。我认为项目的xstream依赖范围'test'正在覆盖mylibrary的xstream依赖范围,'compile'。

在这种情况下,将xstream包含在整个项目中的最佳方法是什么,以便子模块在项目中打包时可以访问它?

我已经阅读过Apache Maven网站关于Transitive依赖关系的解释,但我很难理解它的含义,并且在这种情况下找出最佳实践。

4 个答案:

答案 0 :(得分:12)

这对我来说真的很奇怪,如果它是“特色”,我认为这是一个非常危险的。 无论如何,它不是Maven错误,而是在maven文档中here

关于这个问题的最佳实践,我没有听说过,但最安全的方法是依靠传递依赖来完全从你的pom中删除xstream。如果删除了对mylibrary的依赖,则执行此操作将导致构建失败。这将作为通知您需要修复的东西。您不会以静默方式释放所需的依赖项,并且您不会默默地拥有不再需要的依赖项。

另一方面,mvn dependency:analyze可用于检查包含但未使用的依赖项。

答案 1 :(得分:5)

正如mattb的回答所说,将依赖声明为test范围会覆盖传递的编译范围依赖声明,因此依赖关系不会包含在打包的战争中。

如果您只需要测试中的依赖项,因为'mylibrary'需要执行它,那么您不应该在项目的pom中声明依赖的所有。让传递依赖性解析过程处理它。

如果你的项目确实直接使用xstream jar,你仍然可以依赖传递依赖,因为你需要一个兼容的项目版本和'mylibrary'来运行xstream jar。您应该使用单元测试来执行该功能,如果mylibrary将xstream的版本更改为不兼容的版本,您的构建应该会失败,并且您可以在那时解决该问题。

一般来说,我会说你应该尽量避免在多模块项目中直接声明依赖版本。我在父POM的dependencyManagement部分声明了这些版本,以便子项只需要声明groupId / artifactId。或者,从Maven 2.0.9开始,还有一个额外的依赖范围import

  

此范围仅用于部分中pom类型的依赖项。它表示应该用该POM部分中的依赖项替换指定的POM。由于它们被替换,具有导入范围的依赖性实际上并不参与限制依赖的传递性。

因此,使用import scope可以在单个POM中定义公共依赖项版本,将该POM的依赖项导入dependencyManagement部分,并在其他POM中声明依赖项的groupId / artifactId。

答案 2 :(得分:4)

通过声明自己对xstream的依赖,并将范围设置为test,您将覆盖mylibrary声明的依赖项。

这实际上是一个Maven功能 - 它允许您执行某些操作,例如依赖于您自己项目中的传递依赖项的更高版本,而不是最终打包同一工件的两个不同版本。例如,您可能依赖于log4j的版本1.2.15,但因为您还使用了依赖于libraryX的{​​{1}} - 您不会同时需要log4j-1.2.14和{{1与你的项目一起打包。

如果您确实希望在项目中打包xstream,则不应将范围声明为log4j-1.2.15。实际上,如果你删除你在xstream上列出的依赖关系,事情会随你都喜欢,因为log4j-1.2.14对它有一个编译依赖...

答案 3 :(得分:0)

如果您想要打包,为什么要声明范围?如果在编译和执行时需要它,你不应该将范围留空吗?如果你这样做,那么你只需要

<dependency>
    <groupId>mycompany.modules</groupId>
    <artifactId>submodule</artifactId>
    <version>1.0.1</version>
</dependency>
在你的pom中。除非有理由在编译期间而不是在包装过程中对其进行去除?