【问题标题】:Limiting a transitive dependency to runtime scope in Maven在 Maven 中将传递依赖限制为运行时范围
【发布时间】:2012-06-15 03:33:52
【问题描述】:

我有 2 个使用 Maven 的项目。第一个是包含实用程序类和方法的库。第二个项目是将库作为依赖项的实际应用程序。我的库在内部使用第三方库。

所以这些是依赖项:

  • 我的库:依赖第三方库
  • 我的应用程序:取决于我的库

但是,我不希望第三方库类在编译时在我的应用程序中可用。这是因为该应用程序由一个大型团队支持,并且鉴于两者之间的某些类名和某些方法名相似,我想防止人们在应用程序中意外使用第三方库中的方法。当然,第三方库必须在我的应用程序中的运行时可用。

如果我所有依赖项的范围都是compile,那么它就达不到我的目标。有没有办法在 Maven 3 中实现这一点?

【问题讨论】:

    标签: maven maven-3


    【解决方案1】:

    非常好的问题,但遗憾的是,由于其基本设计,您无法使用 Maven 3、2 或任何其他版本执行此操作。您要问的实际上是一种理想的行为,因为实际上任何工件的 compile 依赖项都应该在 runtime 范围内传递。然而,这样的设计会导致一些问题。正如您可以在Maven's Introduction to the Dependency Mechanism 阅读的关于compile 范围的内容:

    它的目的是[应该考虑编译依赖的传递依赖,它们本身就是编译依赖]运行时范围,以便所有 编译依赖项必须明确列出 - 但是,有 您所依赖的库从另一个类扩展的情况 库,迫使您在编译时可用。为了这 原因,即使在 它们是可传递的。

    因此,如您所见,您实际上需要的是正确设计此行为,但不幸的是,这是不可能实现的。

    【讨论】:

    • 我希望有办法做到这一点。谢谢你的回答,米哈尔。
    • 这是多年前的回答。现在有没有办法做到这一点?我想知道您是否可以以某种方式使用import 的范围来破解这里的解决方案?
    • 我认为这里没有任何改变。正如我在 2012 年所说,这是非常基础的 Maven 设计。我相信现在没有办法改变这一点,因为 Maven 从一开始就是这样做的。
    • 是否可以检查编译的类是否仅依赖于直接指定的编译依赖项,如果这些编译的类依赖于指定的编译依赖项之外的类,是否有 maven 错误?
    • 如果您知道自己在做什么,您可以使用dependencyManagement 覆盖意图行为,请参阅其他答案。
    【解决方案2】:

    过去三年没有任何变化,因此 Michal 的回答仍然正确:无法限制 Maven 中的传递可见性。

    但是,您应该考虑重新设计您的库,将其拆分为一个 api-artifact,它是编译时依赖所必需的,并且它本身不依赖于第三方库和一个仅需要作为运行时依赖的实现工件和这取决于第三方库。

    【讨论】:

      【解决方案3】:

      在您的应用程序中,您可以使用“运行时”范围声明对第三方库的显式依赖。

      这可以防止在编译时看到第三方库,因此无法直接使用。但是,它仍然会在运行时出现(因为您的库需要它)。

      这可行,但很尴尬,值得在 pom 中添加解释性 XML 注释。

      【讨论】:

        【解决方案4】:

        其他答案都是正确的。除了通过拆分仅人工 API 的模块来解决 maven 中缺少的关键功能之外,您还可以使用以下替代方法:

        • 排除传递依赖,然后直接依赖它们(你必须自己管理版本号)
        • 使用 checkstyle 导入控制和 CI。这样团队成员可能会使用传递,但随后 maven 验证将失败
        • 使用梯度。这是 Maven 诸多限制的解决方案

        【讨论】:

        • 当您的库子类化您试图在编译时排除的第 3 方库中的类时,Gradle 将如何解决问题?
        • 如果使用了子类,我相信您在应用程序的编译时需要超类,否则编译器将无法编译。所以 Gradle 没有什么可以解决的。
        【解决方案5】:

        似乎可行的是在 pom.xml 中使用 <dependencyManagement> 部分。 您将需要检查是否有任何副作用,因为它适用于整个项目。而且您必须具体指定每个库。

        以下代码示例允许我将 guava(在项目中由 google guice 作为编译时传递依赖项 smurfed)强制到任何地方的运行时依赖项。

        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>com.google.guava</groupId>
                    <artifactId>guava</artifactId>
                    <scope>runtime</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
        

        【讨论】:

          【解决方案6】:

          您可以使用mvn dependency:analyze 分析依赖关系,或者将依赖关系作为验证生命周期阶段的一部分进行分析: https://maven.apache.org/plugins/maven-dependency-plugin/examples/failing-the-build-on-dependency-analysis-warnings.html

          【讨论】:

            【解决方案7】:

            你可以这样尝试:

            #My application pom.xml
             <dependencies>
                    <dependency>
                        <groupId>My groupId</groupId>
                        <artifactId>My library</artifactId>
                        <version>${version}</version>
                        <exclusions>
                            <exclusion>
                                <groupId>third-party library</groupId>
                                <artifactId> third-party library</artifactId>
                            </exclusion>
                        </exclusions>
                    </dependency>
                    <dependency>
                        <groupId>third-party library</groupId>
                        <artifactId> third-party library</artifactId>
                        <version>${version}</version>
                        <scope>runtime</scope>
                    </dependency>
            </dependencies>
            

            【讨论】:

            • 正如目前所写,您的答案尚不清楚。请edit 添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。你可以找到更多关于如何写好答案的信息in the help center
            猜你喜欢
            • 2019-08-23
            • 2013-03-25
            • 1970-01-01
            • 2018-05-19
            • 1970-01-01
            • 2023-03-04
            • 2016-05-28
            • 1970-01-01
            • 2018-07-30
            相关资源
            最近更新 更多