集中宣告相依性

使用版本目錄

版本目錄 是相依性清單,表示為相依性座標,使用者可以在組建指令碼中宣告相依性時從中選取。

例如,可以從版本目錄選取相依性座標,而不是使用字串表示法宣告相依性

build.gradle.kts
dependencies {
    implementation(libs.groovy.core)
}
build.gradle
dependencies {
    implementation(libs.groovy.core)
}

在此內容中,libs 是目錄,groovy 表示此目錄中可用的相依性。版本目錄相較於直接在組建指令碼中宣告相依性,提供了許多優點

  • 對於每個目錄,Gradle 會產生類型安全存取器,讓您可以在 IDE 中輕鬆新增相依性,並享有自動完成功能。

  • 每個目錄都對組建中的所有專案可見。這是宣告相依性版本,並確保對該版本的變更套用到每個子專案的集中位置。

  • 目錄可以宣告相依性套件,也就是「通常一起使用的相依性群組」。

  • 目錄可以將相依性的群組和名稱與其實際版本分開,並改用版本參考,讓多個相依性可以共用版本宣告。

使用 libs.someLib 表示法新增相依性的方式,與直接在組建指令碼中硬式編碼群組、人工製品和版本完全相同。

相依性目錄不會強制執行相依性的版本:就像一般相依性表示法一樣,它會宣告要求的版本或豐富版本約束。該版本不一定是衝突解決期間選取的版本。

宣告版本目錄

版本目錄可以在 settings.gradle(.kts) 檔案中宣告。在上面的範例中,為了讓 groovy 可以透過 libs 目錄使用,我們需要將別名與 GAV (群組、成品、版本) 座標關聯起來

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            library("groovy-core", "org.codehaus.groovy:groovy:3.0.5")
            library("groovy-json", "org.codehaus.groovy:groovy-json:3.0.5")
            library("groovy-nio", "org.codehaus.groovy:groovy-nio:3.0.5")
            library("commons-lang3", "org.apache.commons", "commons-lang3").version {
                strictly("[3.8, 4.0[")
                prefer("3.9")
            }
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            library('groovy-core', 'org.codehaus.groovy:groovy:3.0.5')
            library('groovy-json', 'org.codehaus.groovy:groovy-json:3.0.5')
            library('groovy-nio', 'org.codehaus.groovy:groovy-nio:3.0.5')
            library('commons-lang3', 'org.apache.commons', 'commons-lang3').version {
                strictly '[3.8, 4.0['
                prefer '3.9'
            }
        }
    }
}

別名及其對應的類型安全存取器

別名必須由一系列識別碼組成,識別碼之間以破折號 (-,建議)、底線 (_) 或句點 (.) 分隔。識別碼本身必須由 ASCII 字元組成,最好是小寫,最後可以接數字。

例如

  • guava 是有效的別名

  • groovy-core 是有效的別名

  • commons-lang3 是有效的別名

  • androidx.awesome.lib 也是有效的別名

  • this.#is.not! 不是

然後會為每個子群組產生類型安全存取器。例如,假設在名為 libs 的版本目錄中有下列別名

guavagroovy-coregroovy-xmlgroovy-jsonandroidx.awesome.lib

我們會產生下列類型安全的存取器

  • libs.guava

  • libs.groovy.core

  • libs.groovy.xml

  • libs.groovy.json

  • libs.androidx.awesome.lib

其中 libs 前置詞來自版本目錄名稱。

如果您不想產生子群組存取器,我們建議依據大小寫來區分。例如,別名 groovyCoregroovyJsongroovyXml 會分別對應到存取器 libs.groovyCorelibs.groovyJsonlibs.groovyXml

在宣告別名時,值得注意的是 -_. 字元都可以用作分隔符號,但產生的目錄會將所有分隔符號正規化為 .:例如,foo-bar 別名會自動轉換為 foo.bar

有些關鍵字是保留字,因此不能用作別名。下列字詞不能用作別名

  • extensions

  • class

  • convention

此外,下列字詞不能用作相依項別名的第一個子群組 (對於套件、版本和外掛,這個限制不適用)

  • 套件

  • 版本

  • 外掛程式

因此,例如對於相依性,別名 versions-dependency 無效,但 versionsDependencydependency-versions 有效。

具有相同版本號碼的相依性

宣告版本目錄 的第一個範例中,我們可以看到我們為 groovy 函式庫的各種元件宣告 3 個別名,而且所有這些別名都共用相同的版本號碼。

我們可以宣告版本並參考它,而不是重複相同的版本號碼

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            version("groovy", "3.0.5")
            version("checkstyle", "8.37")
            library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")
            library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")
            library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")
            library("commons-lang3", "org.apache.commons", "commons-lang3").version {
                strictly("[3.8, 4.0[")
                prefer("3.9")
            }
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            version('groovy', '3.0.5')
            version('checkstyle', '8.37')
            library('groovy-core', 'org.codehaus.groovy', 'groovy').versionRef('groovy')
            library('groovy-json', 'org.codehaus.groovy', 'groovy-json').versionRef('groovy')
            library('groovy-nio', 'org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
            library('commons-lang3', 'org.apache.commons', 'commons-lang3').version {
                strictly '[3.8, 4.0['
                prefer '3.9'
            }
        }
    }
}

另外,透過類型安全存取器宣告的版本可用,讓它們可用於比相依性版本更多的使用案例,特別是對於工具。

build.gradle.kts
checkstyle {
    // will use the version declared in the catalog
    toolVersion = libs.versions.checkstyle.get()
}
build.gradle
checkstyle {
    // will use the version declared in the catalog
    toolVersion = libs.versions.checkstyle.get()
}

如果宣告版本的別名也是某些更特定別名的字首,例如 libs.versions.zinclibs.versions.zinc.apiinfo,則更一般性版本的數值可透過類型安全存取器上的 asProvider() 取得

build.gradle.kts
scala {
    zincVersion = libs.versions.zinc.asProvider().get()
}
build.gradle
scala {
    zincVersion = libs.versions.zinc.asProvider().get()
}

在目錄中宣告的相依性會透過對應於其名稱的延伸模組公開給建置指令碼。在上面的範例中,因為在設定中宣告的目錄稱為 libs,所以延伸模組可在目前建置的所有建置指令碼中透過名稱 libs 取得。使用下列符號宣告相依性…​

build.gradle.kts
dependencies {
    implementation(libs.groovy.core)
    implementation(libs.groovy.json)
    implementation(libs.groovy.nio)
}
build.gradle
dependencies {
    implementation libs.groovy.core
    implementation libs.groovy.json
    implementation libs.groovy.nio
}

…​與撰寫下列內容完全相同

build.gradle.kts
dependencies {
    implementation("org.codehaus.groovy:groovy:3.0.5")
    implementation("org.codehaus.groovy:groovy-json:3.0.5")
    implementation("org.codehaus.groovy:groovy-nio:3.0.5")
}
build.gradle
dependencies {
    implementation 'org.codehaus.groovy:groovy:3.0.5'
    implementation 'org.codehaus.groovy:groovy-json:3.0.5'
    implementation 'org.codehaus.groovy:groovy-nio:3.0.5'
}

在目錄中宣告的版本是 豐富版本。請參閱 版本目錄建置器 API 以取得完整的版本宣告支援文件。

相依性套件

由於某些相依性經常在不同的專案中系統性地一起使用,因此版本目錄提供了「相依性套件」的概念。套件基本上是多個相依性的別名。例如,您可以撰寫以下內容,而不是像上面那樣宣告 3 個個別相依性

build.gradle.kts
dependencies {
    implementation(libs.bundles.groovy)
}
build.gradle
dependencies {
    implementation libs.bundles.groovy
}

名為 groovy 的套件需要在目錄中宣告

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            version("groovy", "3.0.5")
            version("checkstyle", "8.37")
            library("groovy-core", "org.codehaus.groovy", "groovy").versionRef("groovy")
            library("groovy-json", "org.codehaus.groovy", "groovy-json").versionRef("groovy")
            library("groovy-nio", "org.codehaus.groovy", "groovy-nio").versionRef("groovy")
            library("commons-lang3", "org.apache.commons", "commons-lang3").version {
                strictly("[3.8, 4.0[")
                prefer("3.9")
            }
            bundle("groovy", listOf("groovy-core", "groovy-json", "groovy-nio"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            version('groovy', '3.0.5')
            version('checkstyle', '8.37')
            library('groovy-core', 'org.codehaus.groovy', 'groovy').versionRef('groovy')
            library('groovy-json', 'org.codehaus.groovy', 'groovy-json').versionRef('groovy')
            library('groovy-nio', 'org.codehaus.groovy', 'groovy-nio').versionRef('groovy')
            library('commons-lang3', 'org.apache.commons', 'commons-lang3').version {
                strictly '[3.8, 4.0['
                prefer '3.9'
            }
            bundle('groovy', ['groovy-core', 'groovy-json', 'groovy-nio'])
        }
    }
}

語意再次等效:新增單一套件等於個別新增所有屬於該套件的相依性。

外掛程式

除了函式庫之外,版本目錄支援宣告外掛程式版本。函式庫由其群組、成品和版本座標表示,而 Gradle 外掛程式僅由其 ID 和版本識別。因此,它們需要分開宣告

您無法在設定檔或設定檔外掛程式中使用在版本目錄中宣告的外掛程式(因為目錄本身在設定中定義,這將會是先有雞還是先有蛋的問題)。
settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            plugin("versions", "com.github.ben-manes.versions").version("0.45.0")
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            plugin('versions', 'com.github.ben-manes.versions').version('0.45.0')
        }
    }
}

然後,可以在 plugins 區塊中存取外掛程式,並可以使用以下方式在建置的任何專案中使用

build.gradle.kts
plugins {
    `java-library`
    checkstyle
    alias(libs.plugins.versions)
}
build.gradle
plugins {
    id 'java-library'
    id 'checkstyle'
    // Use the plugin `versions` as declared in the `libs` version catalog
    alias(libs.plugins.versions)
}

使用多個目錄

除了傳統的 libs 目錄之外,您還可以透過 Settings API 宣告任意數量的目錄。這讓您可以使用對專案有意義的方式,在多個來源中分開相依性宣告。

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("testLibs") {
            val junit5 = version("junit5", "5.7.1")
            library("junit-api", "org.junit.jupiter", "junit-jupiter-api").versionRef(junit5)
            library("junit-engine", "org.junit.jupiter", "junit-jupiter-engine").versionRef(junit5)
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        testLibs {
            def junit5 = version('junit5', '5.7.1')
            library('junit-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef(junit5)
            library('junit-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef(junit5)
        }
    }
}

每個目錄都會產生一個擴充套件,套用至所有專案以存取其內容。因此,透過挑選減少潛在衝突的名稱,來降低衝突的機率是有意義的。例如,一個選項是挑選以 Libs 結尾的名稱。

libs.versions.toml 檔案

除了上述的設定 API 之外,Gradle 提供一個傳統檔案來宣告目錄。如果在根建置的 gradle 子目錄中找到 libs.versions.toml 檔案,則會自動宣告一個目錄,其中包含此檔案的內容。

宣告 libs.versions.toml 檔案並不會使其成為相依性的唯一真實來源:它是一個可以宣告相依性的傳統位置。一旦您開始使用目錄,強烈建議您在目錄中宣告所有相依性,而不是在建置指令碼中寫入群組/成品/版本字串。請注意,外掛程式可能會新增相依性,這些相依性定義在此檔案之外。

就像 src/main/java 是尋找 Java 來源的慣例,這並不會阻止宣告其他來源目錄(在建置指令碼或外掛程式中),libs.versions.toml 檔案的存在也不會阻止在其他地方宣告相依性。

不過,這個檔案的存在表示大多數的相依性(如果不是全部的話)都將會在這個檔案中宣告。因此,對大多數使用者來說,更新相依性版本只需要變更這個檔案中的一行即可。

預設情況下,libs.versions.toml 檔案將會是 libs 目錄的輸入。可以變更預設目錄的名稱,例如,如果你已經有同名的擴充功能

settings.gradle.kts
dependencyResolutionManagement {
    defaultLibrariesExtensionName = "projectLibs"
}
settings.gradle
dependencyResolutionManagement {
    defaultLibrariesExtensionName = 'projectLibs'
}

版本目錄 TOML 檔案格式

這個 TOML 檔案包含 4 個主要區段

  • [versions] 區段用於宣告相依性可以參考的版本

  • [libraries] 區段用於宣告別名到座標

  • [bundles] 區段用於宣告相依性套件

  • [plugins] 區段用於宣告外掛程式

例如

libs.versions.toml 檔案
[versions]
groovy = "3.0.5"
checkstyle = "8.37"

[libraries]
groovy-core = { module = "org.codehaus.groovy:groovy", version.ref = "groovy" }
groovy-json = { module = "org.codehaus.groovy:groovy-json", version.ref = "groovy" }
groovy-nio = { module = "org.codehaus.groovy:groovy-nio", version.ref = "groovy" }
commons-lang3 = { group = "org.apache.commons", name = "commons-lang3", version = { strictly = "[3.8, 4.0[", prefer="3.9" } }

[bundles]
groovy = ["groovy-core", "groovy-json", "groovy-nio"]

[plugins]
versions = { id = "com.github.ben-manes.versions", version = "0.45.0" }

版本可以宣告為單一字串,這種情況下它們會被解釋為必要的版本,或宣告為 豐富版本

[versions]
my-lib = { strictly = "[1.0, 2.0[", prefer = "1.2" }

版本宣告支援的成員有

相依性宣告可以宣告為簡單字串,這種情況下它們會被解釋為 group:artifact:version 座標,或將版本宣告從群組和名稱中分開

對於別名,別名及其對類型安全存取器的對應 區段中所述的規則也適用。
不同的相依性表示法
[versions]
common = "1.4"

[libraries]
my-lib = "com.mycompany:mylib:1.4"
my-other-lib = { module = "com.mycompany:other", version = "1.4" }
my-other-lib2 = { group = "com.mycompany", name = "alternate", version = "1.4" }
mylib-full-format = { group = "com.mycompany", name = "alternate", version = { require = "1.4" } }

[plugins]
short-notation = "some.plugin.id:1.4"
long-notation = { id = "some.plugin.id", version = "1.4" }
reference-notation = { id = "some.plugin.id", version.ref = "common" }

如果您想要引用在 [versions] 區段中宣告的版本,您應該使用 version.ref 屬性

[versions]
some = "1.4"

[libraries]
my-lib = { group = "com.mycompany", name="mylib", version.ref="some" }

TOML 檔案格式非常寬鬆,讓您可以撰寫「點狀」屬性作為完整物件宣告的捷徑。例如,這個

a.b.c="d"

等同於

a.b = { c = "d" }

a = { b = { c = "d" } }

請參閱 TOML 規範 以取得詳細資料。

類型不安全的 API

版本目錄可透過類型不安全的 API 存取。此 API 可在沒有產生存取器的情況下使用。它是透過版本目錄擴充功能存取的

build.gradle.kts
val versionCatalog = extensions.getByType<VersionCatalogsExtension>().named("libs")
println("Library aliases: ${versionCatalog.libraryAliases}")
dependencies {
    versionCatalog.findLibrary("groovy-json").ifPresent {
        implementation(it)
    }
}
build.gradle
def versionCatalog = extensions.getByType(VersionCatalogsExtension).named("libs")
println "Library aliases: ${versionCatalog.libraryAliases}"
dependencies {
    versionCatalog.findLibrary("groovy-json").ifPresent {
        implementation(it)
    }
}

請查看 版本目錄 API 以取得所有支援的方法。

共用目錄

版本目錄用於單一建置(可能是多專案建置),但也可以在建置之間共用。例如,組織可能想要建立一個相依性目錄,讓不同團隊的不同專案可以使用。

從 TOML 檔案匯入目錄

版本目錄建置器 API 支援包含來自外部檔案的模型。這使得在需要的情況下,可以重複使用主建置的目錄以供 buildSrc 使用。例如,buildSrc/settings.gradle(.kts) 檔案可以使用下列方式包含這個檔案

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from(files("../gradle/libs.versions.toml"))
        }
    }
}

使用 VersionCatalogBuilder.from(Object dependencyNotation) 方法時,只會接受單一檔案。這表示像 Project.files(java.lang.Object…​) 這類的表示法必須參照單一檔案,否則建置會失敗。

如果需要更複雜的結構(從多個檔案匯入版本目錄),建議使用基於程式碼的方法,而不是 TOML 檔案。

因此,此技術可用於從不同檔案宣告多個目錄

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        // declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' file
        create("testLibs") {
            from(files("gradle/test-libs.versions.toml"))
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        // declares an additional catalog, named 'testLibs', from the 'test-libs.versions.toml' file
        testLibs {
            from(files('gradle/test-libs.versions.toml'))
        }
    }
}

版本目錄外掛

雖然從本機檔案匯入目錄很方便,但它並未解決在組織中或對外部消費者共用目錄的問題。共用目錄的一種選項是撰寫設定外掛,將其發布在 Gradle 外掛入口網站或內部存放庫中,並讓消費者套用他們的設定檔上的外掛。

或者,Gradle 提供了一個版本目錄外掛,它提供宣告目錄然後發布目錄的能力。

為執行此操作,您需要套用 version-catalog 外掛

build.gradle.kts
plugins {
    `version-catalog`
    `maven-publish`
}
build.gradle
plugins {
    id 'version-catalog'
    id 'maven-publish'
}

此外掛接著會公開 目錄擴充功能,您可以使用它來宣告目錄

範例 17. 目錄定義
build.gradle.kts
catalog {
    // declare the aliases, bundles and versions in this block
    versionCatalog {
        library("my-lib", "com.mycompany:mylib:1.2")
    }
}
build.gradle
catalog {
    // declare the aliases, bundles and versions in this block
    versionCatalog {
        library('my-lib', 'com.mycompany:mylib:1.2')
    }
}

此類目錄可透過套用 maven-publishivy-publish 外掛並將出版設定為使用 versionCatalog 元件來發布

範例 18. 發布目錄
build.gradle.kts
publishing {
    publications {
        create<MavenPublication>("maven") {
            from(components["versionCatalog"])
        }
    }
}
build.gradle
publishing {
    publications {
        maven(MavenPublication) {
            from components.versionCatalog
        }
    }
}

在發布此類專案時,將自動產生 (並上傳) 一個 libs.versions.toml 檔案,然後可以 從其他 Gradle 建置中使用

匯入已發布目錄

可透過設定 API 匯入 版本目錄外掛 所產生的目錄

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from("com.mycompany:catalog:1.0")
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        libs {
            from("com.mycompany:catalog:1.0")
        }
    }
}

覆寫目錄版本

如果目錄宣告版本,您可以在匯入目錄時覆寫版本

settings.gradle.kts
dependencyResolutionManagement {
    versionCatalogs {
        create("amendedLibs") {
            from("com.mycompany:catalog:1.0")
            // overwrite the "groovy" version declared in the imported catalog
            version("groovy", "3.0.6")
        }
    }
}
settings.gradle
dependencyResolutionManagement {
    versionCatalogs {
        amendedLibs {
            from("com.mycompany:catalog:1.0")
            // overwrite the "groovy" version declared in the imported catalog
            version("groovy", "3.0.6")
        }
    }
}

在上述範例中,任何使用 groovy 版本作為參考的相依項將自動更新為使用 3.0.6

同樣地,覆寫版本並不表示實際已解析的相依項版本會相同:這只會變更已匯入的內容,也就是說,在宣告相依項時使用什麼。實際版本將會受到傳統的衝突解析影響 (如果有的話)。

使用平台控制傳遞版本

一個 平台 是一個特殊軟體元件,可用于控制傳遞相依項版本。在多數情況下,它只由 相依項約束 組成,這些約束將建議相依項版本或強制執行某些版本。因此,這是一個完美的工具,只要您需要在專案之間共用相依項版本。在這種情況下,專案通常會以這種方式組織

  • 定義不同子專案中找到的各種相依項約束的 platform 專案

  • 許多依賴於平台並宣告沒有版本的相依項的子專案

在 Java 生態系統中,Gradle 提供了一個 外掛 以供此目的。

在平台上發布的 Maven BOM 也很常見,Gradle 本機支援

使用 platform 關鍵字建立對平台的依賴關係

build.gradle.kts
dependencies {
    // get recommended versions from the platform project
    api(platform(project(":platform")))
    // no version required
    api("commons-httpclient:commons-httpclient")
}
build.gradle
dependencies {
    // get recommended versions from the platform project
    api platform(project(':platform'))
    // no version required
    api 'commons-httpclient:commons-httpclient'
}

platform 符號是一種簡寫符號,實際上會在幕後執行多項作業

這表示預設情況下,對平台的依賴關係會觸發繼承該平台中定義的所有 嚴格版本,這對平台作者來說很有用,可以確保所有消費者都尊重其在依賴關係版本方面的決策。這可以用明確呼叫 doNotEndorseStrictVersions 方法來關閉。

匯入 Maven BOM

Gradle 提供支援來匯入 物料清單 (BOM) 檔案,這些檔案實際上是使用 <dependencyManagement> 來控制直接和傳遞依賴關係的依賴關係版本的 .pom 檔案。Gradle 中的 BOM 支援類似於在 Maven 中依賴 BOM 時使用 <scope>import</scope>。然而,在 Gradle 中,這是透過 BOM 上的常規依賴關係宣告來完成的

build.gradle.kts
dependencies {
    // import a BOM
    implementation(platform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

    // define dependencies without versions
    implementation("com.google.code.gson:gson")
    implementation("dom4j:dom4j")
}
build.gradle
dependencies {
    // import a BOM
    implementation platform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')

    // define dependencies without versions
    implementation 'com.google.code.gson:gson'
    implementation 'dom4j:dom4j'
}

在範例中,gsondom4j 的版本是由 Spring Boot BOM 提供的。這樣一來,如果您要為 Spring Boot 等平台開發,您不必自己宣告任何版本,而是可以依賴平台提供的版本。

Gradle 會將 BOM 的 <dependencyManagement> 區塊中的所有條目視為類似於 Gradle 的依賴關係約束。這表示在 <dependencyManagement> 區塊中定義的任何版本都可能會影響依賴關係解析結果。為了符合 BOM 的資格,.pom 檔案需要設定 <packaging>pom</packaging>

然而,BOM 通常不僅提供版本作為建議,還提供一種覆寫圖表中找到的任何其他版本的方法。您可以在匯入 BOM 時使用 enforcedPlatform 關鍵字(而不是 platform)來啟用此行為

build.gradle.kts
dependencies {
    // import a BOM. The versions used in this file will override any other version found in the graph
    implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

    // define dependencies without versions
    implementation("com.google.code.gson:gson")
    implementation("dom4j:dom4j")

    // this version will be overridden by the one found in the BOM
    implementation("org.codehaus.groovy:groovy:1.8.6")
}
build.gradle
dependencies {
    // import a BOM. The versions used in this file will override any other version found in the graph
    implementation enforcedPlatform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')

    // define dependencies without versions
    implementation 'com.google.code.gson:gson'
    implementation 'dom4j:dom4j'

    // this version will be overridden by the one found in the BOM
    implementation 'org.codehaus.groovy:groovy:1.8.6'
}

如果您軟體元件可以被其他人使用,則需要仔細考慮使用 enforcedPlatform。此宣告實際上是傳遞的,因此會套用至使用者的依賴關係圖表。很不幸的是,如果他們不同意其中一個強制版本,他們將必須使用 exclude。相反地,如果您的可重複使用軟體元件對某些第三方依賴關係版本有強烈意見,請考慮使用具有 strictly豐富版本宣告

我應該使用平台還是目錄?

由於平台和目錄都討論依賴項版本,而且兩者都可以用於在專案中分享依賴項版本,因此可能會混淆要使用哪一個,以及哪一個比較好。

簡而言之,您應該

  • 僅使用目錄來定義專案的依賴項及其版本,以及產生類型安全的存取器

  • 使用平台將版本套用至依賴項圖表,並影響依賴項解析

目錄有助於集中管理依賴項版本,而且正如其名稱所暗示的,它只是一個您可以選擇的依賴項目錄。我們建議在所有情況下都使用它來宣告依賴項的座標。Gradle 將使用它來產生類型安全的存取器,提供外部依賴項的簡寫符號,並且它允許在不同的專案之間輕鬆分享這些座標。使用目錄不會對下游使用者有任何影響:對他們來說是透明的。

平台是一個較為重量級的建構:它是依賴項圖表的組成部分,就像任何其他函式庫一樣。如果您依賴於平台,則該平台本身就是圖表中的組成部分。特別是,這表示

  • 約束在平台中定義的約束會影響傳遞性依賴項,而不僅是專案的直接依賴項。

  • 平台有版本,而圖表中的傳遞性依賴項可以依賴於不同版本的平台,導致各種依賴項升級。

  • 平台可以將組件綁在一起,特別是可以用作比對版本的建構。

  • 對平台的依賴會由依賴項的使用者「繼承」:這表示對平台的依賴可能會影響您的使用者所使用的函式庫版本,即使您沒有直接或傳遞性地依賴平台所參考的組件。

總之,使用目錄始終是一種良好的工程實務,因為它集中了常見的定義,允許分享依賴項版本或外掛程式版本,但它是建置的「實作細節」:它對使用者來說是不可見的,而目錄中未使用的元素只會被忽略。

平台旨在影響依賴項解析圖表,例如透過對傳遞性依賴項加入約束:它是建構依賴項圖表和影響解析結果的解決方案。

在實務上,您的專案既可以使用目錄,也可以宣告一個本身使用目錄的平台

build.gradle.kts
plugins {
    `java-platform`
}

dependencies {
    constraints {
        api(libs.mylib)
    }
}
build.gradle
plugins {
    id 'java-platform'
}

dependencies {
    constraints {
        api(libs.mylib)
    }
}