build.gradle里面dependencies compile和api的区别
在 Gradle 的 build.gradle
文件中,compile
和 api
是两种不同的依赖配置方式,主要用于控制依赖项的传递性(即依赖是否会被暴露给下游模块)。它们的核心区别在于 依赖项的可见范围 和 对编译类路径的影响。以下是详细对比和适用场景分析:
1. compile
(已废弃,旧版配置)
作用
- 旧版 Gradle(< 4.0) 中用于声明编译时和运行时都需要的依赖。
- 依赖项会自动传递给所有依赖当前模块的其他模块(即下游模块可以访问该依赖)。
- 在 Gradle 4.0+ 中已被标记为废弃,推荐使用
implementation
或api
替代。
示例(旧版)
groovy
dependencies { |
compile 'com.example:library:1.0.0' // 依赖会传递到下游模块 |
} |
问题
- 过度暴露依赖:下游模块可能间接依赖了它实际不需要的库,导致类路径冲突或版本冲突。
- 破坏封装性:模块内部依赖的变更可能影响其他模块。
2. api
(新版推荐,替代 compile
)
作用
- Gradle 4.0+ 引入,用于声明需要暴露给下游模块的依赖。
- 依赖项会传递给所有依赖当前模块的其他模块(与
compile
行为一致)。 - 适用场景:当前模块是一个库/中间件,且下游模块需要直接使用该依赖的 API。
示例
groovy
dependencies { |
api 'com.example:library:1.0.0' // 依赖会传递到下游模块 |
} |
关键点
- 传递性:下游模块可以访问
api
依赖的类。 - 封装性:仅当下游模块必须使用该依赖时才用
api
,否则应使用implementation
。
3. implementation
(新版推荐,非传递依赖)
作用
- Gradle 3.4+ 引入,用于声明仅当前模块内部使用的依赖。
- 依赖项不会传递给下游模块(下游模块无法访问该依赖)。
- 适用场景:当前模块是一个应用或内部服务,且依赖仅用于内部实现。
示例
groovy
dependencies { |
implementation 'com.example:library:1.0.0' // 依赖不会传递到下游模块 |
} |
优势
- 减少构建时间:Gradle 可以并行编译无关模块。
- 避免版本冲突:下游模块不会间接依赖不必要的库。
- 提高封装性:模块内部依赖的变更不会影响其他模块。
4. 对比总结
配置 | 传递性 | 适用场景 | 示例 |
---|---|---|---|
compile | ✅(已废弃) | 旧版 Gradle,行为同 api | compile 'com.example:lib:1.0' |
api | ✅ | 库/中间件,下游需直接使用该依赖 | api 'com.example:lib:1.0' |
implementation | ❌ | 应用/内部服务,依赖仅内部使用 | implementation 'com.example:lib:1.0' |
5. 实际场景分析
场景 1:开发一个库(Library Module)
- 如果下游模块需要调用
library
中的某些类(例如通过@Autowired
注入),则必须用api
:groovy
dependencies {
api 'org.springframework:spring-context:5.3.0' // 暴露 Spring 依赖给下游
}
- 如果
library
仅内部使用log4j
,则用implementation
:groovy
dependencies {
implementation 'org.apache.logging.log4j:log4j-core:2.17.0' // 不暴露给下游
}
场景 2:开发一个应用(Application Module)
- 所有依赖(如 Retrofit、Gson)都应使用
implementation
,因为它们仅用于内部实现:groovy
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.google.code.gson:gson:2.8.9'
}
6. 最佳实践
- 默认使用
implementation
- 除非明确需要暴露依赖给下游,否则优先用
implementation
。
- 除非明确需要暴露依赖给下游,否则优先用
- 库模块谨慎使用
api
- 仅当下游模块必须直接使用该依赖时才用
api
,否则会破坏封装性。
- 仅当下游模块必须直接使用该依赖时才用
- 避免混用
compile
- 新项目应完全弃用
compile
,改用api
或implementation
。
- 新项目应完全弃用
- 检查依赖树
- 使用
gradle dependencies
查看依赖传递关系,避免意外暴露或冲突。
- 使用
7. 迁移指南(旧版 → 新版)
- 将所有
compile
替换为:api
(如果依赖需要传递)。implementation
(如果依赖仅内部使用)。
- 示例:
groovy
// 旧版
dependencies {
compile 'com.example:lib-a:1.0'
compile 'com.example:lib-b:2.0'
}
// 新版
dependencies {
api 'com.example:lib-a:1.0' // lib-a 需要暴露给下游
implementation 'com.example:lib-b:2.0' // lib-b 仅内部使用
}
总结
api
= 暴露依赖给下游(类似旧版compile
,但更明确)。implementation
= 隐藏依赖(推荐默认使用)。compile
= 已废弃,避免使用。
通过合理选择依赖配置,可以显著提升项目的构建性能、可维护性和避免版本冲突。