依赖项的类型

Gradle 中有三种主要的依赖项类型

  1. 模块依赖项:引用来自外部仓库的库。

  2. 项目依赖项:引用同一多项目构建中的其他项目。

  3. 文件依赖项:引用本地文件或目录,例如 .jar.aar 文件。

1. 模块依赖项

模块依赖项是最常见的依赖项。它们引用由模块坐标(组、名称和版本)标识的依赖项

build.gradle.kts
dependencies {
    runtimeOnly(group = "org.springframework", name = "spring-core", version = "2.5")
    runtimeOnly("org.springframework:spring-aop:2.5")
    runtimeOnly("org.hibernate:hibernate:3.0.5") {
        isTransitive = true
    }
    runtimeOnly(group = "org.hibernate", name = "hibernate", version = "3.0.5") {
        isTransitive = true
    }
}
build.gradle
dependencies {
    runtimeOnly group: 'org.springframework', name: 'spring-core', version: '2.5'
    runtimeOnly 'org.springframework:spring-core:2.5',
            'org.springframework:spring-aop:2.5'
    runtimeOnly(
        [group: 'org.springframework', name: 'spring-core', version: '2.5'],
        [group: 'org.springframework', name: 'spring-aop', version: '2.5']
    )
    runtimeOnly('org.hibernate:hibernate:3.0.5') {
        transitive = true
    }
    runtimeOnly group: 'org.hibernate', name: 'hibernate', version: '3.0.5', transitive: true
    runtimeOnly(group: 'org.hibernate', name: 'hibernate', version: '3.0.5') {
        transitive = true
    }
}

Gradle 提供了多种用于声明模块依赖项的表示法,包括字符串表示法和映射表示法。

  • 字符串表示法: 通过将组、名称和版本组合成单个字符串来简化依赖项声明。

  • 映射表示法: 允许分别指定坐标的每个部分。

对于高级配置,例如强制执行严格版本,您还可以在这些表示法旁边提供闭包。

2. 项目依赖项

项目依赖项允许您引用多项目 Gradle 构建中的其他项目。

dependency management project dependencies

这对于将大型项目组织成更小的模块化组件非常有用

web-service/build.gradle.kts
dependencies {
    implementation(project(":utils"))
    implementation(project(":api"))
}
web-service/build.gradle
dependencies {
    implementation project(':utils')
    implementation project(':api')
}

Gradle 使用 project() 函数来定义项目依赖项。此函数采用构建中目标项目的相对路径。路径通常使用冒号 (:) 分隔项目结构的不同级别。

项目依赖项会自动解析,以便在依赖它的项目之前始终构建被依赖的项目。

类型安全的项目访问器

类型安全的项目访问器是一项孵化功能,必须显式启用。实现可能随时更改。

要添加对类型安全项目访问器的支持,请将 enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") 添加到您的 settings.gradle(.kts) 文件中

settings.gradle.kts
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
settings.gradle
enableFeaturePreview 'TYPESAFE_PROJECT_ACCESSORS'

使用 project(":some:path") 表示法的一个缺点是需要记住依赖项的项目路径。此外,更改项目路径需要手动更新每个出现的位置,从而增加了遗漏的风险。

相反,实验性的类型安全项目访问器 API 提供了 IDE 完成功能,使声明依赖项更容易

web-service/build.gradle.kts
dependencies {
    implementation(projects.utils)
    implementation(projects.api)
}
web-service/build.gradle
dependencies {
    implementation projects.utils
    implementation projects.api
}

使用此 API,Kotlin DSL 脚本中错误指定的项目会触发编译错误,帮助您避免遗漏更新。

项目访问器基于项目路径。例如,路径 :commons:utils:some:lib 变为 projects.commons.utils.some.lib,而 kebab-case (some-lib) 和 snake-case (some_lib) 转换为驼峰式大小写:projects.someLib

3. 文件依赖项

文件依赖项允许您通过引用文件路径将外部 JAR 或其他文件直接包含到您的项目中。文件依赖项还允许您将一组文件直接添加到配置中,而无需使用仓库。

通常不鼓励使用文件依赖项。相反,首选声明对外部仓库的依赖项,或者在必要时,使用 file:// URL 声明 Maven 或 Ivy 仓库。
dependency management file dependencies

文件依赖项是独特的,因为它们表示对文件系统上文件的直接引用,没有任何关联的 元数据,例如传递依赖项、来源或作者信息。

build.gradle.kts
configurations {
    create("antContrib")
    create("externalLibs")
    create("deploymentTools")
}

dependencies {
    "antContrib"(files("ant/antcontrib.jar"))
    "externalLibs"(files("libs/commons-lang.jar", "libs/log4j.jar"))
    "deploymentTools"(fileTree("tools") { include("*.exe") })
}
build.gradle
configurations {
    antContrib
    externalLibs
    deploymentTools
}

dependencies {
    antContrib files('ant/antcontrib.jar')
    externalLibs files('libs/commons-lang.jar', 'libs/log4j.jar')
    deploymentTools(fileTree('tools') { include '*.exe' })
}

在此示例中,每个依赖项都显式指定其在文件系统中的位置。引用这些文件的常用方法包括

FileTree 中文件的顺序不能保证稳定,即使在同一台计算机上也是如此。因此,使用 FileTree 的依赖配置可能会产生顺序不同的解析结果,这会影响使用这些结果作为输入的任务的可缓存性。为了确保更可预测和稳定的行为,建议尽可能使用更简单的 files 方法。

或者,您可以使用 扁平目录 仓库来指定多个文件依赖项的源目录。

理想情况下,您应该使用带有本地 URL 的 Maven 或 Ivy 仓库

repositories {
    maven {
        url = 'file:///path/to/local/files' // Replace with your actual path
    }
}

要将文件添加为依赖项,请将 文件集合 传递给配置

build.gradle.kts
dependencies {
    runtimeOnly(files("libs/a.jar", "libs/b.jar"))
    runtimeOnly(fileTree("libs") { include("*.jar") })
}
build.gradle
dependencies {
    runtimeOnly files('libs/a.jar', 'libs/b.jar')
    runtimeOnly fileTree('libs') { include '*.jar' }
}

请注意,文件依赖项不包含在您项目的已发布依赖描述符中。但是,它们在同一构建中的传递依赖项中可用,这意味着它们可以在当前构建中使用,但不能在外部使用。

您应该指定哪些任务生成文件依赖项的文件。否则,当您从另一个项目传递性地依赖它们时,必要的任务可能不会运行

build.gradle.kts
dependencies {
    implementation(files(layout.buildDirectory.dir("classes")) {
        builtBy("compile")
    })
}

tasks.register("compile") {
    doLast {
        println("compiling classes")
    }
}

tasks.register("list") {
    val compileClasspath: FileCollection = configurations["compileClasspath"]
    dependsOn(compileClasspath)
    doLast {
        println("classpath = ${compileClasspath.map { file: File -> file.name }}")
    }
}
build.gradle
dependencies {
    implementation files(layout.buildDirectory.dir('classes')) {
        builtBy 'compile'
    }
}

tasks.register('compile') {
    doLast {
        println 'compiling classes'
    }
}

tasks.register('list') {
    FileCollection compileClasspath = configurations.compileClasspath
    dependsOn compileClasspath
    doLast {
        println "classpath = ${compileClasspath.collect { File file -> file.name }}"
    }
}
$ gradle -q list
compiling classes
classpath = [classes]

Gradle 发行版特定的依赖项

Gradle API 依赖项

您可以使用 DependencyHandler.gradleApi() 方法声明对当前 Gradle 版本 API 的依赖项。当您开发自定义 Gradle 任务或插件时,这非常有用

build.gradle.kts
dependencies {
    implementation(gradleApi())
}
build.gradle
dependencies {
    implementation gradleApi()
}

Gradle TestKit 依赖项

您可以使用 DependencyHandler.gradleTestKit() 方法声明对当前 Gradle 版本 TestKit API 的依赖项。这对于为 Gradle 插件和构建脚本编写和执行功能测试非常有用

build.gradle.kts
dependencies {
    testImplementation(gradleTestKit())
}
build.gradle
dependencies {
    testImplementation gradleTestKit()
}

本地 Groovy 依赖项

您可以使用 DependencyHandler.localGroovy() 方法声明对 Gradle 发行版中包含的 Groovy 的依赖项。当您使用 Groovy 开发自定义 Gradle 任务或插件时,这非常有用

build.gradle.kts
dependencies {
    implementation(localGroovy())
}
build.gradle
dependencies {
    implementation localGroovy()
}

文档化依赖项

当声明依赖项或 依赖约束 时,您可以提供理由来澄清包含依赖项的原因。这有助于使您的构建脚本和 依赖项洞察报告 更易于理解

build.gradle.kts
plugins {
    `java-library`
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("org.ow2.asm:asm:7.1") {
        because("we require a JDK 9 compatible bytecode generator")
    }
}
build.gradle
plugins {
    id 'java-library'
}

repositories {
    mavenCentral()
}

dependencies {
    implementation('org.ow2.asm:asm:7.1') {
        because 'we require a JDK 9 compatible bytecode generator'
    }
}

在此示例中,because() 方法提供了包含 asm 库的理由,这有助于解释其在构建上下文中的用途

$ gradle -q dependencyInsight --dependency asm
org.ow2.asm:asm:7.1
  Variant compile:
    | Attribute Name                 | Provided | Requested    |
    |--------------------------------|----------|--------------|
    | org.gradle.status              | release  |              |
    | org.gradle.category            | library  | library      |
    | org.gradle.libraryelements     | jar      | classes      |
    | org.gradle.usage               | java-api | java-api     |
    | org.gradle.dependency.bundling |          | external     |
    | org.gradle.jvm.environment     |          | standard-jvm |
    | org.gradle.jvm.version         |          | 11           |
   Selection reasons:
      - Was requested: we require a JDK 9 compatible bytecode generator

org.ow2.asm:asm:7.1
\--- compileClasspath

A web-based, searchable dependency report is available by adding the --scan option.