[Gradle中文教程系列]-跟我学Gradle-5.3:依赖-管理依赖的版本(传递(transitive)\排除(exclude)\强制(force)\动态版本(+))

本文介绍Gradle中的依赖管理,包括传递依赖的概念、如何开启或关闭传递依赖、排除特定依赖的方法及使用强制版本和动态版本来解决依赖冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是传递依赖

  在Maven仓库中,构件通过POM(一种XML文件)来描述相关信息以及传递性依赖。Gradle 可以通过分析该文件获取获取所以依赖以及依赖的依赖和依赖的依赖的依赖,为了更加直观的表述,可以通过下面的输出结果了解。

+--- org.springframework:spring-web:4.3.4.RELEASE
|    |    +--- org.springframework:spring-aop:4.3.4.RELEASE
|    |    +--- org.springframework:spring-beans:4.3.4.RELEASE
|    |    +--- org.springframework:spring-context:4.3.4.RELEASE
|    |    \--- org.springframework:spring-core:4.3.4.RELEASE

  可以看到,我们的项目依赖了spring-web,然而spirng-web却依赖了一众spring的全家桶,借助Gradle的传递性依赖特性,你无需再你的脚本中把这些依赖都声明一遍,你只需要简单的一行,Gradle便会帮你将传递性依赖一起下载下来。

compile `org.springframework:spring-web:4.3.4.RELEASE`

 传递依赖特性可以轻松地通过transitive参数进行开启或关闭,上面的示例中如果要忽略spring-web的传递性依赖可以采用指定 transitive = false 的方式来关闭依赖传递特性,也可以采用添加@jar的方式忽略该依赖的所有传递性依赖。

compile("org.springframework:spring-web:4.3.4.RELEASE") {
    transitive = false
}
compile `org.springframework:spring-web:4.3.4.RELEASE@jar`

下面的语句,可以全局性的关闭依赖传递特性。

configurations.all {
   transitive = false
}

排除依赖

   有些时候你可能需要排除一些传递性依赖中的某个模块,此时便不能靠单纯的关闭依赖传递特性来解决了。这时exclude就该登场了,如果说@jar彻底的解决了传递问题,那么exclude则是部分解决了传递问题。然而实际上exclude肯能还会用的频率更更频繁一些,比如下面几种情况。

  • 依赖冲突时,如果有两个依赖引用了相同jar包的不同版本时,默认情况下gradle会采用最新版本的jar包,此时可以通过排除选项来排除。
  • 运行期无需此模块的。
  • 无法正常获取到此传递依赖,远程仓库都不存在的。
  • 版权原因需要排除的。
  • 其他原因。

可以通过configuration配置或者在依赖声明时添加exclude的方式来排除指定的引用。

  exclude可以接收group和module两个参数,这两个参数可以单独使用也可以搭配使用,其中module可以理解为对应GAV中的artifactId,也就是compile group: 'org.gradle.test.classifiers', name: 'service', version: '1.0'中的中间name部分。

configurations {
    //编译期排除commons模块
    compile.exclude module: 'commons'
    //在整个构建过程中排除pkaq.tiger:share
    all*.exclude group: 'pkaq.tiger', module: 'share'
}

dependencies {
    compile("pkaq.tiger:web:1.0") {
        exclude module: 'share'
    }       
}

使用强制版本

  当然,有时候你可能仅仅是需要强制使用某个统一的依赖版本,而不是排除他们,那么此时force就该登场了。指定force = true属性可以冲突时优先使用该版本进行解决。

compile('org.hibernate:hibernate:3.1') {
    force = true
}

全局配置强制使用某个版本的依赖来解决依赖冲突中出现的依赖

configurations.all {
   resolutionStrategy {
       force 'org.hamcrest:hamcrest-core:1.3'
   }
}

使用动态版本

  如果你想让你的工程始终采用最新依赖,那么Gradle提供了一种方式可以始终保证采用依赖的最新版本而无需每次手工检查修改版本。
  使用加号+,可以让Gradle在每次执行构建时检查远程仓库是否存在该依赖的新版本,如果存在新版本则下载选用最新版本。当然也可以指定依赖某个大版本下的最新子版本,1.+表示始终采用该依赖最新的1.x版本的最新依赖。

compile 'org.springframework:spring-web:+'

虽然这是看上去十分风骚的一种用法,但这无疑会降低你系统构建的速度同时提高构建失败的风险。因为Gradle不得不每次检查远程仓库是否存在最新版本,同时新版本也可能带来无法预知的兼容性问题,比如quartz2.x较之于quartz1.x,common-lang3较之于common-lang等。

一个综合示例

compile('org.hibernate:hibernate:3.1') {
 // 冲突时优先使用该版本
 force = true

 // 依据构建名称排除
 exclude module: 'cglib' 
 // 依据组织名称排除
 exclude group: 'org.jmock' 
 // 依据组织名称+构件名称排除
 exclude group: 'org.unwanted', module: 'iAmBuggy' 

 // 为本依赖关闭依赖传递特性
 transitive = false
}
<think>我们正在处理一个Gradle依赖排除问题,用户希望在Kotlin项目中排除特定的Maven依赖:`com.android.support:support-compat`模块。根据提供的引用,我们有几种方法可以排除依赖:1.在声明依赖时直接排除(引用[2]的方法)2.使用全局配置强制指定版本(引用[3]的方法)但这里我们不是要指定版本,而是要排除,所以方法1更直接。注意:用户要求排除的是`com.android.support:support-compat`,而不是整个`com.android.support`。所以我们需要在引入该依赖的地方进行排除。然而,用户可能并没有直接引入`com.android.support:support-compat`,而是通过其他依赖传递引入的。因此,我们需要在引入传递依赖的库的地方进行排除。假设我们有一个依赖库A,它传递依赖了`com.android.support:support-compat`,那么我们在引入A的时候可以这样排除:在KotlinDSL的Gradle脚本中(build.gradle.kts),我们可以使用以下方式:方法1:在具体的依赖项中使用`exclude`函数排除```kotlinimplementation("group:artifact:version"){exclude(group="com.android.support",module="support-compat")}```方法2:如果多个依赖传递了这个库,我们也可以使用全局配置排除(但Gradle官方文档指出全局排除可能会带来问题,因为它会无差别排除,所以谨慎使用)。不过,在KotlinDSL中全局排除的写法稍微复杂,而且并不常见,所以通常推荐方法1。另外,引用[2]中展示了使用`transitive=false`来关闭整个传递依赖,但这样会排除所有传递依赖,而不仅仅是`support-compat`,所以不推荐,除非确实需要关闭所有传递依赖。因此,我们推荐方法1:在引入传递了`support-compat`的依赖项时,使用`exclude`来排除特定的模块。例如,假设我们引入了`com.example:library:1.0.0`,而这个库传递依赖了`com.android.support:support-compat:27.1.1`,那么我们可以这样写:```kotlindependencies{implementation("com.example:library:1.0.0"){exclude(group="com.android.support",module="support-compat")}}```这样,Gradle在解析依赖时就会排除掉这个特定的传递依赖。如果用户不知道是哪个依赖引入了`support-compat`,可以使用Gradle依赖报告任务(如`./gradlewapp:dependencies`)来查看依赖树,从而确定需要在哪里排除。注意:在Android项目中,如果多个模块都传递了相同的依赖,可能需要分别在每个引入该依赖的地方进行排除。另外,引用[1]和引用[3]提到的是强制指定版本的方法,这适用于解决版本冲突,而不是排除依赖。所以如果用户的目标是排除而不是覆盖版本,则不需要使用`force`。因此,针对用户的问题,我们给出如下答案:</think>在 Kotlin 项目中使用 Gradle 排除特定依赖(如 `com.android.support:support-compat`),可通过以下方式实现: ### 方法 1:声明依赖时直接排除(推荐) 在 `build.gradle.kts` 中使用 `exclude` 函数: ```kotlin dependencies { implementation("com.android.support:design:27.0.2") { exclude(group = "com.android.support", module = "support-compat") } // 其他依赖... } ``` 此方法精确排除指定模块的传递依赖,不影响其他依赖项[^2]。 ### 方法 2:全局强制指定版本 在 `android` 配置块中添加全局策略: ```kotlin android { configurations.all { resolutionStrategy { force("com.android.support:support-v4:27.0.2") // 强制指定兼容版本 // 或直接排除:dependencySubstitution { // substitute(module("com.android.support:support-compat")).using(module("com.android.support:support-v4:27.0.2")) // } } } } ``` 此方式适用于解决多模块版本冲突[^3]。 ### 方法 3:关闭传递依赖(慎用) 完全禁用某个库的传递依赖: ```kotlin implementation("com.android.support:appcompat-v7:27.0.2") { isTransitive = false // 关闭所有传递依赖 } ``` ⚠️ 这会排除该库的所有传递依赖,可能导致功能缺失[^2]。 ### 操作步骤 1. **定位问题依赖** 执行 `./gradlew :app:dependencies` 查看依赖树,确认 `support-compat` 的来源库。 2. **选择排除方式** - 精确排除 → 方法 1 - 解决版本冲突 → 方法 2 - 完全隔离 → 方法 3 3. **验证排除效果** 再次运行依赖检查命令,确认 `support-compat` 已消失。 ### 注意事项 - AndroidX 迁移后无需此操作,建议迁移至 `androidx.appcompat`[^1] - 排除核心依赖可能导致运行时错误,需充分测试 - Kotlin DSL 需使用 `group` 和 `module` 参数(而非 Maven 的 `groupId`/`artifactId`) > **示例场景**:若 `com.google.android.material:material` 传递依赖了 `support-compat`,排除代码如下: > ```kotlin > implementation("com.google.android.material:material:1.5.0") { > exclude(group = "com.android.support", module = "support-compat") > } > ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值