Gradle-依赖管理
几乎所有的基于JVM的软件项目都需要依赖外部类库(通常l以ar形式存在)来重用现有功能。jar文件规范不要求你指定类库版本。然而,将版本号添加到jar文件上来标识一个特定的发布版本(比如:spring-context-3.1.3.RELEASE.jar)是常见的做法。随着项目由小变大,项目所依赖的模块和第三方类库会越来越多。组织和管理好jar文件显得至关重要。
由于Java语言并没提供依赖管理的工具,所以你的团队需要自己开发一套存储和检索依赖的想法。你可能会采取以下几种常见的方法:
- 手动复制JAR文件到目标机器,这是最原始的很容易出错的方法。
- 使用一个共享的存储介质来存储JAR文件(比如共享的网盘),你可以加载网络硬盘或者通过FTP检索二进制文件。这种方法需要开发者事先建立好与仓库的连接,手动添加新的依赖到仓库中.
- 把依赖的JAR文件同源代码都添加到版本控制系统中。这种方法不需要任何额外的步骤,你的同伴在拷贝仓库的时候就能检索依赖的改变。另一方面,这些JAR文件占用了不必要的空间,当你的项目存在相互之间依赖的时候你需要频繁的check-in的检查源代码是否发生了改变。
尽管上面的方法都能用,但是这距离理想的解决方案差远了,因为他们没有提供一个标准化的方法来命名和管理JAR文件。至少你得需要开发库的准确版本和它依赖的库(传递依赖)
使用自动化的依赖管理
声明依赖
依赖属性
当依赖管理器从仓库中查找依赖时,需要通过属性的结合来定位,最少需要提供一个name
- group:这个属性用来标识一个组织、公司或者项目,可以用点号分隔,Hibernate的group是org.hibernate
- name: name属性唯一的描述了这个依赖,hibernate的核心库名称是hibernate-core。
- version:一个库可以有很多个版本,通常会包含一个主版本号和次版本号,比如Hibernate核心库3.6.3-Final。
- classifier:有时候需要另外一个属性来进一步的说明,比如说明运行时的环境,Hibernate核心库没有提供classifier
你可以使用下面的语法在项目中声明依赖
1.dependencies {
ccmpile "org.apache.commons:commons-email:1.53.
compile group: 'org.hibernate', name: 'hibernate-core', version: '5.4.2.Final"
}
首先声明要给哪个配置添加依赖,然后添加依赖列表,你可以用map的形式来注明,你也可以直接用冒号来分隔属性,比如这样的
动态指定版本
如果你想使用一个依赖的最新版本,你可以使用latest.integration,比如声明Cargo Ant tasks的最新版本,你可以这样写org.codehaus.cargo:cargo-ant:latest-integration,你也可以用一个+号来动态的声明:cargo 'org.codehaus.cargo:cargo-ant:1.+'
如果你项目中依赖比较多,你把一些共同的依赖属性定义成外部属性可以简化build脚本。
//声明外部属性 ext.cargoGroup = "org.codehaus.cargo"
ext.cargoversion = "1.3.1" dependencies { //使用映射声明依赖 compile group: cargoGroup,name: 'cargo-core-uberjar', version: cargoVersion
//使用快捷方式来声明,引用了前面定义的外部属性 cargo "ScargoGroup: cango-ant : $cargoversion"
}
配置仓库
repositories {
mavenCentral(
}
常用仓库
repositories { mavenLocal()//漆加本地仓库 maven{//自定义仓库,私服等 name 'custom Maven Repository ', url "http://repository.forge.cloudbees.com/release/" } mavenCentral() //maven中央仓库 jcenter()//jcenter仓库 }
解决依赖问题
版本冲突是一个棘手的问题。如果你的项目有很多依赖,而且你选择自动解决传递性依赖,那么版本冲突几乎是不可避免的。Gradle解决版本冲突的默认策略是选择最新的依赖版本(绝大部分情况下可以解决依赖冲突问题)。依赖报告是最有用的工具,它可以帮助选择所需要依赖的版本。
检查依赖报告
当你运行dependencies任务时,这个依赖树会打印出来,依赖树显示了你build脚本声明的顶级依赖和它们的传递依赖
仔细观察你会发现有些传递依赖标注了*号,表示这个依赖被忽略了,这是因为其他顶级依赖中也依赖了这个传递的依赖,Gradle会自动分析下载最合适的依赖。
应对版本冲突
Gradle不会自动通知你项目遇到了版本冲突问题。必须不断的运行依赖报告以找出冲突并不是一个实际的解决方法。你可以更改默认的解决策略,当遇到版本冲突问题是让构建失败
//所有依髋 configurations.all { resolutionStrategy { failOnVersionConflict() } } //or指定依赖 configurations.hibernate-core.resolutionStrategy { fail0nversionConflict() }
失败对于调试目的很有帮助,特别是建立项目的早期阶段和改变依赖关系时,运行项目的任何task都会显示版本冲突信息:
Conflict(s) found for the following module(s): -org.slf4j:slf4j-api between versions 1.7.26 and 1.7.25
Run with: --scan or :dependencyInsight --configuration compileClasspath --dependency org.slf4j:slt4j-api
to get more insight on how to solve the conflict.
排除传递依赖
Gradle允许你完全控制传递依赖,你可以选择排除全部的传递依赖也可以排除指定的依赖,假设你不想使用UberJar传递的xml-api的版本而想声明一个不同版本,你可以使用exclude方法来排除它
compile ("ch.qos.logback: logback-classic: 1.2.3"){ //排除传递依赖exclude exclude group: 'org.slf4j',module: 'slf4j-api' //transitive = false;//全部排除 }
exclude属性值和正常的依赖声明不太一样,你只需要声明group和(或)module,Gradle不允许你只排除指定版本的依赖。
有时候仓库中找不到项目依赖的传递依赖,这会导致构建失败,Gradle允许你使用transitive属性来排除所有的传递依赖:
dependencies{ implementation("com.google.guava:guava:23.0") { transitive = false } }
项目可以决定完全禁用可传递依赖项(全部排除)
configurations.all { transitive = false }
强制指定一个版本
configurations.cargo.resolutionStrategy { force "org.slf4j:slf4j-api:1.7.26"//强制性的指定一个版本 }
或
configurations.all{ resolutionStrategy { force "org.slf4j: slf4j-api:1.7.26" } }
写在最后:当然,绝大部分情况下是不需要我们去解决版本冲突问题的,因为Gradle的默认解决方案(使用最新)可以解决掉90%以上的冲突问题。剩余不能解决的就可以参照上面的步骤
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南