Force Maven仅使用第一级依赖项

时间:2013-10-15 13:43:13

标签: java maven dependencies

我有一个Maven Java项目。在编译项目时,我不希望通过一系列子依赖项偶然满足我的项目依赖项。在构建最终的战争时,当maven必须检查所有使用的依赖项并为战争添加必要的lib时,这是可以的,但是在编译代码时我想确保只使用直接依赖项。为什么呢?

假设我有两个依赖项:

<dependency>
    <groupId>com.package</groupId>
    <artifactId>module-1</artifactId>
</dependency>

<dependency>
    <groupId>com.package</groupId>
    <artifactId>module-2</artifactId>
</dependency>

对于我们的项目模块-1和模块-2提供完全不同的目的,但在模块-2的依赖树中的某处,使用模块-1。我删除了module-1依赖项,但maven继续构建我的项目而没有编译错误,因为它解决了module-2子依赖项中的module-1。这种变化没有被注意到。

一段时间后我们决定删除module-2,因为我们不需要它。奇怪的是,我们不能再使用从模块1导入的编译类,并且没有连接到模块2逻辑。

这是一个简单的案例,但在大项目中,这可能会造成相当大的依赖。

4 个答案:

答案 0 :(得分:6)

您可以使用Maven dependency plugin目标“依赖:分析”为您提供未在当前模块上声明的所有已使用依赖项的报告(包含传递)。那样Maven仍然会使用传递依赖(我猜不知道),但你可以通过插件强制自己确保这些也被声明。它还会警告您不必要的依赖。介意,该插件分析编译的类。有时,您可能需要配置插件,因为有时可能无法检测到编译时需要依赖项,而不是在运行时,例如因为内联常量。

答案 1 :(得分:2)

如果你真的需要这样做,那么你可以在pom中设置排除。

e.g。这是我的一个poms中的排除示例,我不希望它自动获取公共日志记录,因为我正在使用不同的日志记录提供程序。

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${org.springframework-version}</version>
        <exclusions>
            <!-- Exclude Commons Logging in favor of SLF4j -->
            <exclusion>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
             </exclusion>
        </exclusions>
    </dependency>

你可以这样做(未经测试)

<dependency>
    <groupId>com.package</groupId>
    <artifactId>module-2</artifactId>
    <exclusions>
      <exclusion>
        <groupId>com.package</groupId>
        <artifactId>module-1</artifactId>
      </exclusion>
    </exclusions>
</dependency>

我不一定会推荐这个。在我的日志记录排除的情况下这是有道理的,因为我使用slf4j而不是公共日志记录。我已经看过其他例子,如果整个项目使用spring 3,则用它来排除spring 2.

从你的例子中说出来有点困难,因为它太模糊了。通常,您应该将依赖关系保持在最低限度。如果module-2依赖于module-1,那么它意味着你的应用程序不会在没有module-1的情况下编译或运行。事实上,如果没有它,它可以幸福地生活,那么它并不是真正的依赖。

作为旁注,有点令人担忧的是你没有针对依赖项的版本号。你可能会发现maven警告你这件事。始终包含版本号是一种好习惯。如果您依赖于当前正在开发的模块,那么您应该在版本上使用.SNAPSHOT后缀来获取该版本的最新版本。

答案 2 :(得分:1)

似乎没有办法告诉maven不要过渡性地解决依赖:How to exclude all transitive dependencies of a Maven dependency。我认为其中一个原因是,当用户发现某些工件未在运行时解析或存在工件版本问题时,用户很快就会遇到运行时故障。但是,如果检查链接,则可以使用通配符排除模式使每个deps'独立'。

另一个选择是对每个<optional>子依赖项使用module-X依赖项。这将确保项目编译而非module-X将被传递解决。像:

<dependency>
   <groupId>com.package</groupId>
   <artifactId>module-1</artifactId>
   <optional>true</optional>
</dependency>

尽管如此,分析依赖树可能是最安全和可预测的选择。

答案 3 :(得分:0)

你打算做什么听起来有点奇怪。在某种程度上,你破坏了你想要使用的依赖管理。

如果你的module-2依赖于module-1并且依赖于它,那么依赖于module-2的任何模块只需要定义那个模块。

您可以使用排除限制分辨率的深度:Exclude all transitive dependencies of a single dependency

较新版本的maven允许使用通配符。

但是:你需要重新添加你真正需要的那些,这是通过重复你有其他模块的依赖。这复制了这项工作。

如果存在导致怪异的工件,则可以定义范围:http://maven.apache.org/guides/introduction/introduction-to-dependency-mechanism.html,因此它也不会传播到相关模块。