在 Maven 中有一个非常有用的功能,您可以在父 POM 的 <dependencyManagement>
部分定义依赖项,并从子模块引用该依赖项,而无需指定版本或范围或其他内容。
Gradle 中有哪些替代方案?
您可以在父脚本中声明公共依赖项:
ext.libraries = [ // Groovy map literal
spring_core: "org.springframework:spring-core:3.1",
junit: "junit:junit:4.10"
]
然后,您可以从子脚本中使用依赖项声明,如下所示:
dependencies {
compile libraries.spring_core
testCompile libraries.junit
}
要与高级配置选项共享依赖项声明,您可以使用 DependencyHandler.create
:
libraries = [
spring_core: dependencies.create("org.springframework:spring-core:3.1") {
exclude module: "commons-logging"
force = true
}
]
可以在同一个名称下共享多个依赖项:
libraries = [
spring: [ // Groovy list literal
"org.springframework:spring-core:3.1",
"org.springframework:spring-jdbc:3.1"
]
]
dependencies { compile libraries.spring }
然后将同时添加两个依赖项。
您不能以这种方式共享的一条信息是依赖项应该分配给什么配置(Maven 术语中的范围)。但是,根据我的经验,最好还是明确说明这一点。
从 Gradle 4.6 开始,文档中建议使用依赖约束作为实现此目的的方法。从 https://docs.gradle.org/current/userguide/declaring_dependencies.html#declaring_a_dependency_without_version:
对于大型项目,推荐的做法是声明没有版本的依赖项,并使用依赖项约束进行版本声明。优点是依赖约束允许你在一个地方管理所有依赖的版本,包括传递的。
在您的父 build.gradle
文件中:
allprojects {
plugins.withType(JavaPlugin).whenPluginAdded {
dependencies {
constraints {
implementation("com.google.guava:guava:27.0.1-jre")
}
}
}
}
用检查 Java 插件 (... whenPluginAdded {
) 来包装依赖项块并不是绝对必要的,但它会处理将非 Java 项目添加到同一构建中。
然后在子 gradle 项目中,您可以简单地省略版本:
apply plugin: "java"
dependencies {
implementation("com.google.guava:guava")
}
子构建仍然可以选择指定更高版本。如果指定了较低的版本,它会自动升级到约束中的版本。
allprojects
的用法也很好。
这是一个迟到的回复,但您可能还想看看:http://plugins.gradle.org/plugin/io.spring.dependency-management 它提供了导入 maven 'bom' 的可能性,并重用 'bom' 中定义的定义。当逐渐从 maven 迁移到 gradle 时,这当然是一个很好的帮助!现在享受它。
io.spring.gradle:dependency-management-plugin
插件在新的 Gradle 3.x 系列中存在问题,但在 2.x 系列中稳定。参考错误报告 Drop support for Gradle 3 #115
在 Spring (main promoter of BOM usage) 的情况下,您可能会以:
buildscript {
repositories {
mavenLocal()
jcenter()
}
dependencies {
classpath 'io.spring.gradle:dependency-management-plugin:1.0.0.RELEASE'
}
}
repositories {
mavenLocal()
jcenter()
}
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
dependencyManagement {
imports {
mavenBom 'io.spring.platform:platform-bom:Athens-SR3'
}
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-web'
testCompile 'org.springframework.boot:spring-boot-starter-test'
}
请注意,io.spring.platform:platform-bom
有 org.springframework.boot:spring-boot-starter-parent
作为父级,因此它与 Spring Boot 兼容
您可以通过以下方式验证实际的依赖关系解析:
$ gradle dependencies
$ gradle dependencies --configuration compile
$ gradle dependencies -p $SUBPROJ
$ gradle buildEnvironment
$ gradle buildEnvironment -p $SUBPROJ
或有任务:
task showMeCache {
configurations.compile.each { println it }
}
阅读 Soring 官方博文 Better dependency management for Gradle,了解引入 io.spring.gradle:dependency-management-plugin
的原因。
我更喜欢在根项目中创建包含内容的 common_dependencies.gradle 文件
buildscript {
ext {
commonDependencies = [
redis : 'redis.clients:jedis:3.6.3',
lettuce : 'io.lettuce:lettuce-core:6.1.4.RELEASE'
]
}
}
然后在根/子模块的 build.gradle
apply from: rootProject.file("common_dependencies.gradle")
dependencies {
commonDependencies.values().forEach {
implementation it
}
}
从 gradle 7.1.1 开始,您可以使用版本目录
https://docs.gradle.org/current/userguide/platforms.html
https://melix.github.io/blog/2021/03/version-catalogs.html
您可以使用以下代码集中依赖项:
在 gradle.properties
COMPILE_SDK_VERSION=26
BUILD_TOOLS_VERSION=26.0.1
TARGET_SDK_VERSION=26
MIN_SDK_VERSION=14
ANDROID_SUPPORT_VERSION=26.0.2
在每个模块中添加到 build.gradle
:
android {
compileSdkVersion COMPILE_SDK_VERSION as int
buildToolsVersion BUILD_TOOLS_VERSION as String
defaultConfig {
minSdkVersion MIN_SDK_VERSION as int
targetSdkVersion TARGET_SDK_VERSION as int
versionCode 1
versionName "1.0"
}
}
dependencies {
compile "com.android.support:appcompat-v7:${ANDROID_SUPPORT_VERSION}"
compile "com.android.support:support-v4:${ANDROID_SUPPORT_VERSION}"
compile "com.android.support:support-annotations:${ANDROID_SUPPORT_VERSION}"
compile "com.android.support:support-vector-drawable:${ANDROID_SUPPORT_VERSION}"
compile "com.android.support:design:${ANDROID_SUPPORT_VERSION}"
}
此博文建议将依赖项和组作为配置进行管理:https://www.javacodegeeks.com/2016/05/manage-dependencies-gradle-multi-project-build.html
我自己没有尝试过,但它看起来很有趣。
根项目 build.gradle
subprojects {
configurations {
commonsIo
}
dependencies {
commonsIo 'commons-io:commons-io:2.5'
}
}
子项目 build.gradle
configurations {
compile.extendsFrom commonsIo
}
正如 datta 在 their answer 中所说,Gradle 现在有一个称为版本目录的东西。
这是 Kotlin DSL (*.kts) 的示例。请注意,我使用的是 Gradle 7.4。
在 settings.gradle.kts 中定义依赖:
// Configure dependencies aspects applied to all projects
dependencyResolutionManagement {
// By default, repositories declared by a project will override the ones here.
// You can change this behavior with the repositoriesMode property.
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
// Define repositories for all projects
repositories {
mavenCentral()
maven("https://jitpack.io")
}
versionCatalogs {
create("libs") {
// Versions are useful specially when you have libraries with the same
// group and version which are updated together with the same version
version("room", "2.4.1")
// │ │
// │ └───> The version notation
// └───> Your desired name (alias)
library("material", "com.google.android.material:material:1.4.0")
// │ │
// │ └───> The dependency notation (coordinates)
// ├───> Your desired name (alias); only letters, digits and _ - .
// └───> Note that _ - . will all be normalized to .
// You can configure the version as you would in regular build file
// Note that the group and module are separate parameters
library("junit5", "org.junit.jupiter", "junit-jupiter").version {
prefer("5.8.0")
}
// Using the same version for multiple dependencies
library("room-ktx", "androidx.room", "room-ktx").versionRef("room")
library("room-runtime", "androidx.room", "room-runtime").versionRef("room")
}
}
}
build.gradle.kts 中的用法:
dependencies {
implementation(libs.material)
implementation(libs.room.ktx)
implementation(libs.room.runtime)
testImplementation(libs.junit5)
}
如您所见,您不仅可以声明依赖项,还可以在此处声明存储库(而不是在顶级构建脚本中使用 allprojects
块来定义所有子项目的存储库)。
有关上述解决方案的常规语法以及有关版本目录和集中存储库和依赖项配置的更多信息,请参阅 Gradle official guides。
为了让您的 gradle 文件保持干净,我们可以将依赖项分组到一个数组中并在以后实现它们。
在依赖块之外的 build.gradle(应用程序级别)中添加这样的库版本:
// 声明库的版本 final RetrofitVersion = '2.3.0' final OkHttpVersion = '3.9.1'
创建一个相关依赖的数组,以便您以后可以轻松找到它。将其添加到依赖块之外的 build.gradle(应用程序级别)中:
// 使用库中的版本并添加依赖以及访问名称(如改造(第一个))最终网络依赖 = [改造:“com.squareup.retrofit2:retrofit:${RetrofitVersion}”,改造GsonConverter:“com.squareup.retrofit2 :converter-gson:${RetrofitVersion}",retrofitRxJavaAdapter:"com.squareup.retrofit2:adapter-rxjava2:${RetrofitVersion}",okHttp3:"com.squareup.okhttp3:okhttp:${OkHttpVersion}",okHttp3Logging:" com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}" ]
在依赖块中:
// 从数组依赖项中实现所有依赖项 { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation networkDependencies.values() }
所以最终的代码将如下所示:
final RetrofitVersion = '2.3.0'
final OkHttpVersion = '3.9.1'
final networkDependencies = [
retrofit : "com.squareup.retrofit2:retrofit:${RetrofitVersion}",
retrofitGsonConverter: "com.squareup.retrofit2:converter-gson:${RetrofitVersion}",
retrofitRxJavaAdapter: "com.squareup.retrofit2:adapter-rxjava2:${RetrofitVersion}",
okHttp3 : "com.squareup.okhttp3:okhttp:${OkHttpVersion}",
okHttp3Logging : "com.squareup.okhttp3:logging-interceptor:${OkHttpVersion}"
]
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation networkDependencies.values()
}
dependencies.gradle
脚本,在其中我将所有依赖项定义为属性,例如:ext.GROOVY = 'org.codehaus.groovy:groovy-all:2.1.6'
。在根项目build.gradle
中,我包含allprojects { apply from: "$rootDir/dependencies.gradle" }
。然后将所有依赖项定义在一个文件中,而不是分散它们,并且在依赖项配置中使用更多“易于阅读”的常量。allprojects
,因为项目级别的额外属性对子项目可见。