5月27日 23:16

Gradle 依赖管理有哪些配置类型?如何解决冲突?

Gradle 通过 configurations(依赖配置)和 repositories(仓库)两大机制管理依赖。configurations 定义依赖的可见范围和生命周期,repositories 定义依赖的获取来源。

核心依赖配置类型

配置编译时运行时传递给消费者典型场景
implementation可见可见不可见默认选择,大多数依赖用这个
api可见可见可见库模块需要暴露给下游的 API 依赖
compileOnly可见不可见不可见Lombok 等仅编译期需要的依赖
runtimeOnly不可见可见不可见JDBC 驱动等仅运行时需要的依赖
annotationProcessor可见不可见不可见注解处理器
groovy
dependencies { implementation 'org.apache.commons:commons-lang3:3.12.0' api 'org.apache.commons:commons-math3:3.6.1' // 消费者也能访问 compileOnly 'org.projectlombok:lombok:1.18.24' // 编译后丢弃 runtimeOnly 'mysql:mysql-connector-java:8.0.28' // 运行时才加载 annotationProcessor 'org.projectlombok:lombok:1.18.24' }

implementation 与 api 的关键区别: implementation 的依赖不会出现在消费者的编译类路径中,改动后只重新编译当前模块;api 会传递,改动后消费者也要重新编译。优先用 implementation 可以显著缩短构建时间。

版本管理

推荐使用版本目录(Version Catalog),在 gradle/libs.versions.toml 中集中声明:

toml
[versions] spring-boot = "3.0.0" [libraries] spring-boot-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "spring-boot" }
groovy
dependencies { implementation libs.spring.boot.web }

多模块项目也可用 BOM 统一版本:

groovy
dependencies { implementation platform('org.springframework.boot:spring-boot-dependencies:3.0.0') implementation 'org.springframework.boot:spring-boot-starter-web' // 版本由 BOM 控制 }

依赖冲突与排除

Gradle 默认取最高版本。当冲突不可自动解决时,可强制版本或排除:

groovy
// 排除特定传递依赖 implementation('org.springframework.boot:spring-boot-starter-web:3.0.0') { exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat' } // 强制版本 configurations.all { resolutionStrategy { force 'org.apache.commons:commons-lang3:3.12.0' } }

查看依赖树排查冲突:./gradlew dependencies --configuration implementation

追问

Q: 为什么 implementation 改了不会触发下游模块重编译? A: implementation 的依赖被隔离在当前模块的编译类路径内,消费者编译时看不到这些依赖,因此改动不影响消费者的编译产物。这是 Gradle 3.4 引入 implementation 替代 compile 的核心动机。

Q: 什么时候必须用 api 而不能用 implementation? A: 当模块的公开 API 方法签名中用到了某个依赖的类型时(如返回值或参数类型来自该依赖),必须用 api,否则消费者编译时会找不到类。

Q: 动态版本(如 3.+)有什么问题? A: 构建不可复现——同一份代码不同时间构建可能拉到不同版本,导致线上行为不一致。生产环境必须锁定版本。

标签:Gradle