在 Gradle 构建系统中,理解依赖配置对于优化项目结构和构建速度至关重要。随着 Gradle 版本的演进,compile
配置已经被废弃,取而代之的是更现代的 api
和 implementation
配置。此外,compileOnly
用于特定场景。这篇文章将详细介绍这些依赖配置的用法及其区别。
配置 | 编译时可见 | 运行时可见 | 传递到下游模块 | 适用场景 |
---|---|---|---|---|
compile (已废弃) | ✅ | ✅ | ✅ | Gradle 旧版本的通用配置 |
implementation | ✅ | ✅ | ❌ | 模块内部使用,不需要对外暴露的依赖 |
api | ✅ | ✅ | ✅ | 构建公共库或共享依赖的多模块项目 |
compileOnly | ✅ | ❌ | ❌ | 仅在编译时需要的依赖,如 Lombok 和注解处理器 |
apiElements | ❌ | ❌ | ✅ | 用于控制库发布时的依赖暴露 |
1. compile
(已废弃)
在 Gradle 的旧版本中,
compile
是最常用的依赖配置。它在项目中既可用于 编译时,又可用于 运行时,同时依赖会自动传递给使用当前模块的其他模块。
用法:gradle
代码解读:
dependencies {
compile 'org.apache.commons:commons-lang3:3.12.0'
}
特点
- 编译时和运行时都可用。
- 依赖会传递给所有依赖当前模块的下游模块。
现状
自 Gradle 7.0 起,compile
配置已经被废弃,官方建议使用 implementation
或 api
来替代。
2. implementation
implementation
是用来替代 compile
的现代配置之一,专注于模块内的依赖管理。它强调模块之间的隔离,以减少重编译的次数,从而提升构建速度。
用法:arduino
代码解读
dependencies {
implementation 'org.apache.commons:commons-lang3:3.12.0'
}
特点
- 仅在 当前模块 的编译和运行时可用。
- 不会传递给依赖当前模块的其他模块(即下游模块无法访问这些依赖)。
- 适合那些只在模块内部使用的库,而不需要暴露给下游模块。
适用场景
- 推荐在模块化项目中使用,以减少模块之间的耦合和依赖传递。
- 加快构建速度,尤其是大型项目。
3. api
api
是 java-library
插件引入的配置,用于替代 compile
,并允许依赖被 传递 到下游模块。它确保任何依赖当前模块的其他模块都可以访问这些依赖。
用法
首先,需要在 build.gradle
文件中应用 java-library
插件:
代码解读
plugins {
id 'java-library'
}
dependencies {
api 'org.apache.shardingsphere:shardingsphere-jdbc-core:5.1.1'
implementation 'org.springframework:spring-context:5.3.29'
}
特点
- 编译时和运行时都可用。
- 依赖会传递给下游模块(类似于旧的
compile
)。- 用于构建公共库模块,使其对其他模块暴露 API 依赖。
适用场景
- 多模块项目中共享公共 API 时使用。
- 如果你希望依赖当前模块的其他模块也能访问某些依赖,则应使用
api
。
4. compileOnly
compileOnly
用于声明 仅在编译时可用 的依赖。编译完成后,这些依赖不会包含在最终的 JAR 文件中,也不会传递给下游模块。这对于注解处理器或只在编译阶段起作用的工具特别有用。
用法:arduino
代码解读
dependencies {
compileOnly 'org.projectlombok:lombok:1.18.28'
}
特点
- 仅在编译时可见,运行时不可用。
- 不会包含在打包的 JAR 文件中,也不会传递给下游模块。
- 适合仅在编译期间需要的库,例如 Lombok 或注解处理器。
适用场景
- 使用 Lombok 之类的注解工具。
- 编译期代码生成工具。
5. apiElements
apiElements
是 Gradle 的 发布变体(publishing variant),用于控制库发布时的 API 依赖。一般在构建公共库时使用,通过声明哪些依赖应暴露给下游消费者,而不是直接影响模块的编译和运行时。
用法:scss
代码解读
configurations {
apiElements {
attributes {
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, Usage.JAVA_API))
}
}
}
特点
- 主要用于库发布时的依赖管理,而不是直接声明项目的编译依赖。
- 影响生成的 POM 文件和发布时的依赖元数据。
- 通常由
java-library
插件自动处理。
6. 总结与建议
- 使用
implementation
:如果依赖只在当前模块内部使用,不需要对外暴露。 - 使用
api
:如果希望依赖传递给依赖当前模块的其他模块,如公共库模块。 - 使用
compileOnly
:仅在编译时需要,运行时不需要的依赖,如 Lombok。 - 使用
apiElements
:在发布库时,用于控制哪些依赖对下游模块可见。
通过合理使用 Gradle 的依赖配置,可以有效提升构建效率、减少模块之间的耦合,并更好地管理项目的依赖关系。