5

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

假设我有两个依赖项:

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

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

对于我们的项目,module-1 和 module-2 的用途完全不同,但是在 module-2 的依赖关系树的某个地方,使用了 module-1。我删除了 module-1 依赖项,但 maven 继续构建我的项目而没有编译错误,因为它从 module-2 子依赖项中解析了 module-1。这种变化被忽视了。

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

这是一个简单的案例,但在大型项目中,这可能会使依赖关系变得一团糟。

4

4 回答 4

6

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

于 2013-10-15T13:55:55.507 回答
2

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

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

    <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 后缀来获取该版本的最新构建。

于 2013-10-15T16:13:35.057 回答
1

似乎没有办法告诉 maven 不要传递地解决依赖关系:如何排除 Maven 依赖项的所有传递依赖项。我认为原因之一是用户很快就会遇到运行时问题,当他发现某些工件在运行时没有得到解决或存在工件版本问题时。但是,如果您检查链接,则可以使用通配符排除模式使每个部门都“独立”。

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

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

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

于 2013-10-15T15:32:02.460 回答
0

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

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

您可以使用排除项来限制解析的深度:排除单个依赖项的所有传递依赖项

较新版本的 Maven 允许在其中使用通配符。

但是:您将需要重新添加您实际需要的那些,这是通过重复您拥有其他模块的依赖关系。这重复了工作。

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

于 2013-10-15T13:55:42.530 回答