Gradle中api project()与普通api依赖的区别、用法及Maven对比
两种api依赖声明的核心差异不在依赖的传递规则(两者的透传行为完全一致,都会把依赖暴露给当前模块的下游消费者),而在依赖的来源和构建时的处理逻辑,具体说明如下:
api project(...)的适用时机
- 依赖目标是当前Gradle多项目构建中,已经在
settings.gradle(或settings.gradle.kts)里通过include引入的子模块时使用,比如示例里的:my-prj-1就是根目录下的同名子模块。 - 本地开发需要联动修改多个模块代码时必须用这种写法:修改被依赖子模块的代码后,当前模块不需要等子模块打包发布到制品库,直接编译、运行就能拿到最新的改动,联调成本最低。
- 多模块工程做全量构建、测试、发布时,Gradle可以自动识别这类依赖的链路关系,按正确的先后顺序执行各个模块的构建任务,不需要手动维护构建顺序。
和普通坐标形式api依赖的核心区别
- 依赖解析逻辑完全不同:
project形式的依赖直接关联本地构建内的子模块源码和构建输出,不会去远程制品库、本地Gradle缓存里查找对应包;GAV坐标形式的依赖,Gradle会按照配置的仓库优先级,从本地缓存、配置的私服/公共仓库拉取对应版本的已发布制品。 - 构建任务的感知能力不同:
project依赖会被纳入当前构建的任务依赖图,比如执行当前模块的compileJava任务时,Gradle会自动先执行被依赖子模块的编译、打包等前置任务;坐标形式的依赖是已经构建完成的静态制品,不存在前置构建步骤。
你观察到的project写法不需要填写GAV坐标,是因为Gradle给每个纳入多项目构建的子模块都自动生成了默认GAV(默认规则是根项目group:子模块名:根项目version,也可以手动在子模块的构建脚本里修改),不需要手动写坐标,Gradle就能直接定位到对应模块。
和Maven机制的类比
这套逻辑和Maven的机制完全可以对应,有Maven使用经验的话可以直接类比:
- Gradle的
api project(':my-prj-1')等价于Maven多模块(反应堆)构建中的同工程子模块依赖:Maven碰到这类依赖时,不会去远程仓库查找制品,会直接使用反应堆中对应子模块的构建输出,也会自动按依赖关系调整模块构建顺序。 - GAV坐标形式的
api "com.mydomain:grpc-helper:${grpc-helperVersion}"等价于Maven中的普通外部依赖:Maven会按照仓库配置从本地仓、远程仓拉取对应GAV的已发布包,不会关联本地源码模块。
补充一个共通的细节:不管是Gradle还是Maven,如果你声明的外部依赖GAV刚好和当前多项目构建里某个子模块的GAV完全一致,构建工具会自动将这个外部依赖替换为本地子模块依赖,不需要手动修改声明写法。
内容的提问来源于stack exchange,提问作者user18688240
相关产品推荐
相关产品推荐

