【问题标题】:'Provided' dependency in GradleGradle 中的“提供”依赖项
【发布时间】:2015-06-09 11:45:39
【问题描述】:

我前面有build.gradle,并且有一些依赖项声明为provided,但在documentation 中我看不到这个依赖范围。

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web:1.2.4.RELEASE")
    ....

    provided 'backport-util-concurrent:backport-util-concurrent:3.1'
    provided 'org.javolution:javolution:5.5.1@jar
    ....
}

这是由插件提供的吗?如果是这样,我如何找出它属于哪个插件?

Gradle 中providedruntime 依赖范围有什么区别?

【问题讨论】:

  • 你有一个名为provided的配置吗?
  • 我好像没明白你的意思是什么配置。
  • 我的意思是configurations 块中名为provided 的条目。能否请您粘贴整个 build.gradle 脚本?
  • 我为此功能使用了gradle-extra-configurations-plugin。也有类似的插件,比如propsdeps
  • 在 Maven 世界中,“provided”范围是指一个库,该库需要用于编译项目,但不应作为传递依赖项导出或包含在最终打包存档中(例如 WAR 文件),因为它将由目标环境以其他方式“提供”。经典示例是 Web 应用程序 - 您在编译时需要 servlet API 依赖项,但您不希望在最终的 WAR 中使用它,因为 Web 服务器将在父类加载器上提供它。

标签: java gradle dependency-management


【解决方案1】:

为了进一步说明,从最新版本开始,Gradle 5.5 具有compileOnly(与provided 相同)和runtimeOnly 选项。新的默认“编译和运行时”选项是implementation

【讨论】:

  • IIUC "compileOnly" 不提供用于编译和运行测试的库。这是一个遗憾。
  • @fml2 怎么会这样?你不能使用 testCompileOnly / testImplementation etc.
  • 是的,我可以。但是,如果通过compileOnly 包含一个库,IMO 会更方便,我可以自动在测试中使用它。
【解决方案2】:

provided 范围是什么?

假设需要jar 来编译您的代码,但该jar 存在于生产环境库集合中。然后,您不需要将 jar 与您的项目档案一起打包。为了支持这个要求,Maven 有一个名为provided 的作用域。如果您将任何 jar 依赖项声明为 provided,则此 jar 将在编译期间出现在您的类路径中,但不会与您的项目存档一起打包。

provided 作用域非常有用,尤其是在 Web 应用程序中。例如,servlet-api.jar 需要出现在您的类路径中才能编译您的项目,但您不需要它来将servlet-api.jar 文件与war 打包在一起。使用provided 范围可以实现这一要求。

在 Gradle java 名为 provided 的插件中没有定义范围。也不在 warandroid 插件中。如果你想在你的项目中使用provided 范围,那么你必须在你的build.gradle 文件中定义它。以下是在 gradle 中声明 provided 范围的代码 sn-p:

configurations {
    provided
}

sourceSets {
    main { compileClasspath += configurations.provided }
}

现在,你的第二个问题:

Gradle 中提供的依赖范围和运行时依赖范围有什么区别?

为了首先回答这个问题,我将定义compile 依赖。 compile 依赖项是依赖项,它们是编译代码所必需的。现在想象一下,如果您的代码使用名为 X 的库,那么您必须将 X 声明为您的编译时依赖项。还可以想象X 在内部使用另一个库Y,并且您将Y 声明为您的运行时依赖项。

在编译期间,Gradle 会将 X 添加到您的类路径中,但不会添加 Y。因为,Y 不需要编译。但它会将XY 与您的项目存档打包在一起,因为XY 都是在生产环境中运行您的项目存档所必需的。一般生产环境所需的所有依赖都称为runtime依赖。

在 Gradle 官方documentation 中,它说runtime 依赖是“生产类在运行时所需的依赖。默认情况下,还包括编译时依赖。”。

现在,如果您已经读到这里,那么您已经知道 provided 是一个 compile 依赖项,我们不希望出现在 runtime 依赖项中(基本上,我们不希望它与项目存档一起打包)。

以下是providedruntime 范围的图示。这里compile指的是编译项目需要的依赖,non-compile指的是不需要编译项目的依赖。

【讨论】:

  • compileOnly 配置是最接近 maven“提供”范围的选项,但它不是真正的“仅在编译时”配置。例如,在编译期间需要项目 Lombok 类,但在运行时从不需要,应该从不在运行时提供,并且应该从不被打包。这与编译和运行期间需要的 servlet 依赖项不同,但在打包期间不需要,因为它们是由环境提供的。 Maven 和 Gradle 都没有建立真正的“仅编译”和“提供编译”之间的区别。
  • runtime 配置已弃用,请改用runtimeOnly
  • 这里 Gradle 自己写道,runtime 应替换为 runtimeOnlyprovided 应替换为 compileOnly docs.gradle.org/current/userguide/…
  • 如果你使用了war插件,你也会得到'providedCompile',docs.gradle.org/current/userguide/…
【解决方案3】:

从 gradle 2.12 开始,您可以使用 compileOnly 选项。

https://blog.gradle.org/introducing-compile-only-dependencies

【讨论】:

  • 从 Gradle 6.7 开始,还有 compileOnlyApi 依赖:docs.gradle.org/6.7/…
  • 试过了,这会产生 compile,不酷
【解决方案4】:

根据最新的 gradle 版本更新答案。

来自以下链接的 gradle 官方文档:

https://docs.gradle.org/current/userguide/upgrading_version_5.html

弃用

不应再使用编译和运行时配置声明依赖关系。编译和运行时的使用 不鼓励 Java 生态系统插件中的配置 从 Gradle 3.4 开始。

需要使用 implementation、api、compileOnly 和 runtimeOnly 配置来声明依赖和 compileClasspath 和 runtimeClasspath 配置来解决依赖关系。

更重要的是,最近发布的 Gradle 7.0 版本中删除了编译依赖配置。

如果您尝试在 Gradle 3.4+ 项目中使用 compile,您将收到如下警告:

此版本中使用了已弃用的 Gradle 功能,使其 与 Gradle 7.0 不兼容。使用‘–warning-mode all’来显示 个别弃用警告。

您应该始终使用实现而不是编译依赖项,并使用 runtimeOnly 而不是运行时。

战争插件

War 插件扩展了 Java 插件以添加对组装 Web 应用程序 WAR 文件的支持。它禁用默认的 JAR 归档 生成 Java 插件并添加默认的 WAR 归档任务。

War 插件增加了两个依赖配置:

  1. 提供编译
  2. 提供运行时

向providedCompile 或providedRuntime 添加一个条目将导致该依赖项从war 文件中排除。

  1. 如果您的源代码依赖于某些类,请使用 providedCompile 用于编译。
  2. 如果您将提供的Runtime 用于测试而不是 编译。

示例:

providedCompile 'org.springframework.boot:spring-boot-starter-tomcat:1.1.6.RELEASE'

上述 JAR 及其传递依赖仅在编译时可用,但在运行时不可用。这意味着,这些 JAR 将不会包含在战争档案中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-26
    • 2012-08-31
    • 1970-01-01
    • 2013-12-23
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多