2024-07-29
燐灯三千燃长夜,烛照天门千山雪。 --- 《烛火千年》 · 烛火千年
Gradle插件
org.gradle.toolchains.foojay-resolver-convention
org.gradle.toolchains.foojay-resolver-convention 插件是 Gradle 提供的一个插件,用于简化 Java 工具链的解析和配置。该插件利用 Foojay(Friends of OpenJDK)提供的服务,自动解析和下载所需的 JDK 版本,从而简化项目的 Java 环境配置。
插件工作原理
- 工具链配置:在
build.gradle文件中指定所需的 Java 版本和供应商。 - 自动下载:当构建过程中发现本地没有指定的 JDK 时,插件会自动从 Foojay 服务下载对应的 JDK。
- 环境配置:下载完成后,插件会自动配置下载的 JDK 以供项目使用。
使用示例
以下是一个示例配置,展示了如何使用该插件自动解析和下载 JDK:
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17) // 指定需要的 Java 版本
}
}
tasks.withType(JavaCompile).configureEach {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
示例说明
- 插件声明:在
plugins块中声明org.gradle.toolchains.foojay-resolver-convention插件。 - 工具链配置:在
java块中配置所需的 Java 版本,这里指定使用 Java 17。 - 任务配置:为所有
JavaCompile任务指定使用自动解析的 Java 编译器。
测试自动下载功能
你可以尝试在一个没有预先安装指定 JDK 的环境中运行以下命令,以测试插件的自动下载和配置 功能:
./gradlew compileJava
在构建过程中,Gradle 会自动检查本地是否有符合要求的 JDK,如果没有,插件会自动下载并配置。
更多配置选项
你还可以配置更多选项,例如指定 JDK 供应商:
java {
toolchain {
languageVersion = JavaLanguageVersion.of(11)
vendor = JvmVendorSpec.ADOPTIUM // 指定 JDK 供应商为 Adoptium
}
}
通过这种方式,你可以确保所有开发和构建环境使用相同的 JDK 版本和供应商,减少环境差异带来的问题。如果你有其他问题或需要进一步的帮助,请告诉我!
参考文档
可以参考 Gradle 官方文档 和 Foojay 官方网站 了解更多关于 Java 工具链和 Foojay 服务的信息。
gradle强制特定依赖版本
这段代码的作用是通过配置 Gradle 的依赖解析策略来强制特定依赖的版本。具体来说,它针对 jakarta.xml.bind:jakarta.xml.bind-api 依赖,将其版本强制设为 3.0.1。以下是对这段代码的详细解释:
配置详解
configurations.all { Configuration c ->
c.resolutionStrategy.eachDependency { DependencyResolveDetails details ->
if (details.requested.group == 'jakarta.xml.bind' && details.requested.name == 'jakarta.xml.bind-api') {
details.useVersion '3.0.1'
}
}
}
主要作用
- 遍历所有配置:
configurations.all会遍历项目中所有的配置(如compileClasspath、runtimeClasspath等)。 - 设置解析策略:
c.resolutionStrategy.eachDependency为每个依赖配置一个解析策略。 - 检查依赖:
DependencyResolveDetails对象包含关于当前依赖的信息,通过details.requested.group和details.requested.name可以获取依赖的 group 和 name。 - 强制使用特定版本:通过
details.useVersion '3.0.1',将jakarta.xml.bind:jakarta.xml.bind-api依赖的版本强制设置为3.0.1。
示例解释
configurations.all { Configuration c -> ... }:对所有配置应用相同的依赖解析策略。c.resolutionStrategy.eachDependency { DependencyResolveDetails details -> ... }:为每个依赖配置一个解析策略。if (details.requested.group == 'jakarta.xml.bind' && details.requested.name == 'jakarta.xml.bind-api') { ... }:检查当前解析的依赖是否是jakarta.xml.bind:jakarta.xml.bind-api。details.useVersion '3.0.1':将匹配的依赖版本强制设置为3.0.1。
作用和场景
这段代码在以下场景中非常有用:
- 解决版本冲突:当项目中有多个库依赖于不同版本的
jakarta.xml.bind-api时,可以通过这种方式强制使用一个特定的版本,避免版本冲突。 - 统一依赖版本:确保项目中的所有配置使用相同版本的
jakarta.xml.bind-api,提高一致性。 - 依赖升级:当你需要升级某个特定依赖的版本,而不想逐一修改每个依赖声明时,可以通过这种方式统一升级。
总结
通过这段代码,你可以确保项目中的所有 jakarta.xml.bind:jakarta.xml.bind-api 依赖都使用 3.0.1 版本。这是一种管理依赖版本的一致性和解决版本冲突的有效方法。
这段代码的作用是为所有类型为 AbstractCompile 的任务配置编译器选项。具体来说,它添加了 -Werror 和 -Xlint:all 编译器参数。这些参数会影响 Java 编译器的行为。
Gradle配置编译器行为
代码详解
tasks.withType(AbstractCompile).configureEach {
options.compilerArgs <<
"-Werror" <<
"-Xlint:all"
}
主要作用
- 遍历编译任务:
tasks.withType(AbstractCompile).configureEach会遍历项目中所有继承自AbstractCompile的任务(如JavaCompile、GroovyCompile等),并 对每个任务进行配置。 - 设置编译器参数:
options.compilerArgs提供了一个列表,可以向其中添加编译器参数。这段代码向该列表中添加了-Werror和-Xlint:all参数。
编译器参数解释
-Werror:将所有警告视为错误。如果编译过程中出现任何警告,编译将会失败。这有助于确保代码质量,强制开发者解决所有警告。-Xlint:all:启用所有编译器警告。编译器会报告所有可能的问题,包括未使用的变量、未处理的异常等。这可以帮助开发者识别和解决潜在的问题。
作用和场景
这段代码在以下场景中非常有用:
- 提高代码质量:通过将警告视为错误,确保代码在没有警告的情况下进行编译,有助于保持代码的高质量。
- 严格代码审查:在团队开发中,强制解决所有警告可以帮助团队成员编写更规范和更安全的代码。
- 识别潜在问题:启用所有警告可以帮助开发者识别代码中的潜在问题,从而在早期阶段进行修复。
示例解释
tasks.withType(AbstractCompile):获取所有AbstractCompile类型的任务。configureEach:对每个任务进行配置。options.compilerArgs:获取编译器参数列表。<<:向参数列表中添加新的编译器参数(-Werror和-Xlint:all)。
完整示例
假设你的项目使用 Java 编译器,以下是一个完整的 build.gradle 文件示例:
plugins {
id 'java'
}
tasks.withType(AbstractCompile).configureEach {
options.compilerArgs << "-Werror" << "-Xlint:all"
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.13.2'
}
通过这种配置,你可以确保所有编译任务都会将警告视为错误,并启用所有警告,从而提高代码的质量和安全性。
gradle buildscan.value
这两行代码是使用 Gradle 的构建扫描(build scan)功能来记录构建过程中使用的 JVM 版本和 Gradle 版本。构建扫描是一种强大的工具,可以捕获和分析构建数据,从而帮助开发者了解和优化构建过程。具体来说,这两行代码将 JVM 版本和 Gradle 版本的信息添加到构建扫描中,以便稍后查看和分析。
代码详解
buildScan.value(identityPath.path + "#jvmVersion", testJavaRuntimeVersion)
buildScan.value(identityPath.path + "#gradleVersion", testGradleVersion)
详细解释
-
buildScan.value(key, value):这是 Gradle 构建扫描 API 提供的方法,用于向构建扫描中添加自定义值。key是自定义值的键,value是自定义值的内容。 -
identityPath.path + "#jvmVersion"和identityPath.path + "#gradleVersion":identityPath.path:这是 Gradle 内置 的一个属性,用于表示当前任务或项目的标识路径。它通常用于生成唯一的键,以确保不同任务或项目的构建扫描数据不会冲突。#jvmVersion和#gradleVersion:这些是自定义的后缀,用于区分记录的值。它们分别表示 JVM 版本和 Gradle 版本。
-
testJavaRuntimeVersion和testGradleVersion:testJavaRuntimeVersion:这是一个字符串,表示测试使用的 Java 运行时版本。在前面的代码中,这个值从项目属性或默认值中获取。testGradleVersion:这是一个字符串,表示测试使用的 Gradle 版本。在前面的代码中,这个值也是从项目属性或当前 Gradle 版本中获取。
作用和意义
通过将 JVM 版本和 Gradle 版本的信息添加到构建扫描中,你可以在构建完成后,通过构建扫描报告查看这些信息。这对以下情况特别有用:
- 调试和排查问题:当构建失败或出现问题时,了解构建使用的 JVM 和 Gradle 版本可以帮助快速定位问题的根源。
- 性能分析:在分析构建性能时,了解构建使用的环境信息(如 JVM 和 Gradle 版本)可以帮助优化构建过程。
- 构建历史记录:记录和跟踪不同版本的使用情况,有助于维护构建的一致性和可重复性。
示例解释
假设你的构建扫描报告中包含以下信息:
- Task Path:
:compileJava - JVM Version:
21 - Gradle Version:
7.4
在构建扫描中,你可以看到类似以下的自定义值:
:compileJava#jvmVersion:21:compileJava#gradleVersion:7.4
这些信息会帮助你在构建扫描报告中清晰地看到每个任务使用的 JVM 和 Gradle 版本,从而更好地理解和优化构建过程。
Gradle配置javadoc属性
这段代码为所有类型为 Javadoc 的任务配置了额外的 Javadoc 选项。具体来说,它添加了 -Xdoclint:none 和 -quiet 选项。以下是详细的解释:
代码详解
tasks.withType(Javadoc).configureEach {
options.addStringOption('Xdoclint:none', '-quiet')
}
主要作用
- 遍历 Javadoc 任务:
tasks.withType(Javadoc).configureEach会遍历项目中所有Javadoc类型的任务,并对每个任务进行配置。 - 配置 Javadoc 选项:通过
options.addStringOption方法为 Javadoc 任务添加特定的选项。
Javadoc 选项解释
-
-Xdoclint:none:禁用所有 Javadoc 的 lint 检查。这意味着在生成 Javadoc 时,不会对注释内容进行格式、拼写、标签使用等方面的严格检查。这对于快速生成 Javadoc 或在不完整的注释情况下生成文档非常有用。 -
-quiet:使 Javadoc 工具在生成文档时尽量保持安静,只输出最少的必要信息。这可以减少构建日志中的噪音,尤其是在大型项目中。
作用和场景
这段代码在以下场景中非常有用:
- 快速生成 Javadoc:在不需要严格检查注释内容的情况下,快速生成 Javadoc。
- 减少构建日志噪音:通过
-quiet选项减少 Javadoc 生成过程中的输出信息,使构建日志更加清晰。 - 解决现有注释问题:如果项目中存在很多不完整或格式不 规范的 Javadoc 注释,可以通过禁用 lint 检查来避免构建失败或警告。
示例解释
tasks.withType(Javadoc):获取所有Javadoc类型的任务。configureEach:对每个任务进行配置。options.addStringOption('Xdoclint:none', '-quiet'):为 Javadoc 任务添加-Xdoclint:none和-quiet选项。
完整示例
假设你的项目需要为所有 Javadoc 任务添加这些选项,可以在 build.gradle 文件中添加以下代码:
plugins {
id 'java'
}
tasks.withType(Javadoc).configureEach {
options.addStringOption('Xdoclint:none', '-quiet')
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.13.2'
}
运行效果
在运行 ./gradlew javadoc 任务时,Javadoc 工具会生成文档,但不会进行 lint 检查,并且输出的信息会减少。生成的 Javadoc 文档中可能包含格式不规范的注释,但构建过程不会因此失败或产生大量警告。
gradle配置验证插件行为
这段代码为所有类型为 ValidatePlugins 的任务配置了两个选项:failOnWarning 和 enableStricterValidation。具体来说,它设置了在插件验证过程中,如果出现警告则任务失败,并启用了更严格的验证规则。以下是详细的解释:
代码详解
tasks.withType(ValidatePlugins.class).configureEach {
failOnWarning = true
enableStricterValidation = true
}
主要作用
- 遍历 ValidatePlugins 任务:
tasks.withType(ValidatePlugins.class).configureEach会遍历项目中所有ValidatePlugins类型的任务,并对每个任务进行配置。 - 配置验证 选项:通过设置
failOnWarning和enableStricterValidation选项,控制插件验证过程中的行为。
选项解释
failOnWarning = true:将此选项设置为true,表示如果在插件验证过程中出现任何警告,任务将会失败。这有助于确保插件符合更高的质量标准,并且在发布之前解决所有潜在的问题。enableStricterValidation = true:启用更严格的验证规则。这意味着插件在验证过程中将会经过更严格的检查,确保插件的定义和配置符合最佳实践和最新的标准。
作用和场景
这段代码在以下场景中非常有用:
- 提高插件质量:通过在出现警告时失败并启用更严格的验证规则,确保插件符合高质量标准。
- 发现潜在问题:在开发过程中,早期发现并解决插件配置中的问题,避免发布后出现问题。
- 遵循最佳实践:确保插件的定义和配置符合 Gradle 最新的标准和最佳实践。
示例解释
tasks.withType(ValidatePlugins.class):获取所有ValidatePlugins类型的任务。configureEach:对每个任务进行配置。failOnWarning = true:如果出现警告,任务将失败。enableStricterValidation = true:启用更严格的验证规则。
完整示例
假设你的项目需要对所有 ValidatePlugins 任务添加这些选项,可以在 build.gradle 文件中添加以下代码:
plugins {
id 'java-gradle-plugin'
id 'com.gradle.plugin-publish' version '1.2.1'
}
group = 'com.example'
version = '1.0-SNAPSHOT'
gradlePlugin {
plugins {
simplePlugin {
id = 'com.example.simple-plugin'
implementationClass = 'com.example.SimplePlugin'
}
}
}
tasks.withType(ValidatePlugins.class).configureEach {
failOnWarning = true
enableStricterValidation = true
}
repositories {
mavenCentral()
}
dependencies {
testImplementation 'junit:junit:4.13.2'
}
pluginBundle {
website = 'https://github.com/example/simple-plugin'
vcsUrl = 'https://github.com/example/simple-plugin'
description = 'A simple Gradle plugin'
tags = ['gradle', 'plugin', 'example']
}
publishing {
publications {
pluginMaven(MavenPublication) {
from components.java
}
}
}
运行效果
在运行 ./gradlew validatePlugins 任务时,Gradle 将会验证你的插件配置。如果验证过程中出现任何警告,任务将会失败。此外,启用更严格的验证规则,确保你的插件配置符合最新的标准和最佳实践。
Gradle注册任务
TaskProvider<JooqGenerate> jooq = project.getTasks().register(taskName, JooqGenerate.class, config, jooqGeneratorRuntimeConfiguration, project.getExtensions()); 的详细解释
这段代码在 Gradle 中注册了一个新的 JooqGenerate 任务。JooqGenerate 是一个自定义的任务类,用于生成 jOOQ 源代码。以下是对这段代码的详细解释:
代码分解
-
project.getTasks().register:project:当前的 Gradle 项目对象。getTasks():获取当前项目的任务容器。register:注册一个新的任务。
-
taskName:- 动态生成的任务名称,如
"generateMainJooq"或"generateTestJooq",具体名称取决于配置名称。
- 动态生成的任务名称,如
-
JooqGenerate.class:- 任务的类型是
JooqGenerate,这意味着注册的任务将是一个JooqGenerate类型的任务。
- 任务的类型是
-
config:JooqConfig实例,包含jOOQ配置信息。这个配置将被传递给JooqGenerate任务实例。
-
jooqGeneratorRuntimeConfiguration:jOOQ生成器的运行时配置,通常是一个FileCollection,包含生成jOOQ源代码所需的类路径。
-
project.getExtensions():- 当前项目的扩展容器,用于获取和配置项目的扩展。
详细解释
TaskProvider<JooqGenerate> jooq 的作用是使用 project.getTasks().register 方法注册一个新的 JooqGenerate 任务,并将其绑定到 TaskProvider 上。TaskProvider 是一种延迟任务配置和执行的方式,确保任务只在实际需要时才进行配置和执行。
JooqGenerate 类的构造函数
在 JooqGenerate 类中,构造函数的定义如下:
@Inject
public JooqGenerate(JooqConfig config, FileCollection runtimeClasspath, ExtensionContainer extensions, ObjectFactory objects, ProviderFactory providers, ProjectLayout projectLayout, ExecOperations execOperations, FileSystemOperations fileSystemOperations) {
// 初始化各个属性
}
参数解释
config:JooqConfig实例,包含jOOQ配置信息。runtimeClasspath:运行时类路径,FileCollection类型。extensions:扩展容器,ExtensionContainer类型。objects:对象工厂,ObjectFactory类型,用于创建 Gradle 提供的对象(如Property和Provider)。providers:提供者工厂,ProviderFactory类型,用于创建和操作Provider实例。projectLayout:项目布局,ProjectLayout类型,包含项目目录和文件布局信息。execOperations:执行操作,ExecOperations类型,用于执行外部进程。fileSystemOperations:文件系统操作,FileSystemOperations类型,用于文件系统的操作(如删除目录)。
功能
-
注册任务:
- 使用
project.getTasks().register方法在 Gradle 项目中注册一个新的JooqGenerate任务。
- 使用
-
任务参数传递:
- 将
config、runtimeClasspath和extensions等参数传递给JooqGenerate任务的构造函数。
- 将
-
延迟配置:
TaskProvider允许延迟配置任务,只有在任务实际执行或需要时才进行配置。这提高了 Gradle 构建脚本的性能和效率。
实际任务配置示例
假设你有一个 build.gradle 文件,配置如下:
plugins {
id 'nu.studer.jooq' version '5.2'
}
jooq {
version = '3.14.0'
edition = 'OSS'
configurations {
main { // 对应的配置名称
generateSchemaSourceOnCompilation = true
jdbc {
driver = 'org.h2.Driver'
url = 'jdbc:h2:~/test'
user = 'sa'
password = ''
}
generator {
name = 'org.jooq.codegen.DefaultGenerator'
database {
name = 'org.jooq.meta.h2.H2Database'
inputSchema = 'PUBLIC'
}
target {
packageName = 'org.jooq.example'
directory = 'src/generated/jooq'
}
}
}
}
}
在这个示例中,JooqGenerate 任务将根据 jooq 配置生成 jOOQ 源代码,并将生成的源代码放置在 src/generated/jooq 目录中。
总结
这段代码通过 TaskProvider 注册了一个新的 JooqGenerate 任务,并将必要的配置信息传递给任务实例,以便生成 jOOQ 源代码。TaskProvider 允许延迟配置任务,提高了 Gradle 构建脚本的性能和效率。
Gradle NameDomainObjectContainer
要实现一个自定义的 Gradle 插件,使其能够在 build.gradle 文件中定义类似于 code { configurations { main { ... } } } 的 DSL,你需要按照以下步骤进行配置:
1. 创建扩展类
首先,创建一个扩展类,用于在 DSL 中定义配置项。
CodeConfig.java
package com.example;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import javax.inject.Inject;
public class CodeConfig {
private final ObjectFactory objects;
private final NamedDomainObjectContainer<Configuration> configurations;
@Inject
public CodeConfig(ObjectFactory objects) {
this.objects = objects;
this.configurations = objects.domainObjectContainer(Configuration.class);
}
public NamedDomainObjectContainer<Configuration> getConfigurations() {
return configurations;
}
public static class Configuration {
private final Property<String> a;
private final Property<String> b;
@Inject
public Configuration(ObjectFactory objects) {
this.a = objects.property(String.class);
this.b = objects.property(String.class);
}
public Property<String> getA() {
return a;
}
public Property<String> getB() {
return b;
}
}
}
2. 创建插件类
接下来,创建一个插件类,用于注册和配置扩展。
CodePlugin.java
package com.example;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class CodePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
// Register the 'code' extension
CodeConfig extension = project.getExtensions().create("code", CodeConfig.class, project.getObjects());
// Configure tasks or other behavior based on the extension
project.afterEvaluate(proj -> {
extension.getConfigurations().forEach(config -> {
// Example: Print configuration values
System.out.println("Configuration: " + config.getA().get() + ", " + config.getB().get());
// You can create tasks or apply configurations based on these values
});
});
}
}
3. 应用插件并配置 DSL
在 build.gradle 文件中应用插件并进行配置。
build.gradle
plugins {
id 'com.example.code-plugin'
}
code {
configurations {
main {
a = '1'
b = 'abcd'
}
// You can define more configurations here
test {
a = '2'
b = 'efgh'
}
}
}
4. 在 settings.gradle 中包含插件路径
确保在 settings.gradle 中包含插 件路径,以便在本地开发时能够找到插件。
settings.gradle
includeBuild 'path/to/your/plugin'
总结
通过以上步骤,你创建了一个自定义 Gradle 插件,使其能够在 build.gradle 文件中定义类似于 code { configurations { main { ... } } } 的 DSL。这个插件支持多个配置项,并允许在评估完 build.gradle 后访问和使用这些配置项。
NamedDomainObjectContainer 是 Gradle 中用于管理一组具有唯一名称的对象的容器。它继承自 NamedDomainObjectCollection,并扩展了一些功能,使其非常适合用于 DSL 配置。例如,NamedDomainObjectContainer 常用于插件开发中,以提供类似于 configurations { ... } 或 sourceSets { ... } 的 DSL 块。
主要特性
- 命名对象管理:每个对象都有一个唯一的名称,通过名称可以轻松访问和管理这些对象。
- DSL 支持:提供了一种自然的方式,通过闭包或配置块来配置对象。
- 自动创建:在使用时,如果引用的名称还没有创建对象,会自动创建并配置新对象。
示例解释
假设我们正在开发一个自定义插件,其中包含一个 NamedDomainObjectContainer 用于管理一组名为 Configuration 的对象。
1. 定义 Configuration 类
首先,定义一个简单的 Configuration 类,其中包含一些可配置的属性。
package com.example;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import javax.inject.Inject;
public class Configuration {
private final Property<String> a;
private final Property<String> b;
@Inject
public Configuration(ObjectFactory objects) {
this.a = objects.property(String.class);
this.b = objects.property(String.class);
}
public Property<String> getA() {
return a;
}
public Property<String> getB() {
return b;
}
}
2. 创建 CodeConfig 扩展类
然后,创建一个扩展类 CodeConfig,它包含一个 NamedDomainObjectContainer<Configuration>,用于管理 Configuration 对象。
package com.example;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.model.ObjectFactory;
import javax.inject.Inject;
public class CodeConfig {
private final NamedDomainObjectContainer<Configuration> configurations;
@Inject
public CodeConfig(ObjectFactory objects) {
this.configurations = objects.domainObjectContainer(Configuration.class);
}
public NamedDomainObjectContainer<Configuration> getConfigurations() {
return configurations;
}
}
3. 创建插件类
接下来,创建一个插件类 CodePlugin,用于注册 CodeConfig 扩展,并在项目评估后处理配置。
package com.example;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
public class CodePlugin implements Plugin<Project> {
@Override
public void apply(Project project) {
// Register the 'code' extension
CodeConfig extension = project.getExtensions().create("code", CodeConfig.class, project.getObjects());
// Configure tasks or other behavior based on the extension
project.afterEvaluate(proj -> {
extension.getConfigurations().forEach(config -> {
// Example: Print configuration values
System.out.println("Configuration: " + config.getA().get() + ", " + config.getB().get());
// You can create tasks or apply configurations based on these values
});
});
}
}
4. 配置插件
最后,在 build.gradle 文件中应用插件并配置 configurations。
plugins {
id 'com.example.code-plugin'
}
code {
configurations {
main {
a = '1'
b = 'abcd'
}
test {
a = '2'
b = 'efgh'
}
}
}
如何工作
- 对象创建和配置:当在
configurations块中引用main和test时,NamedDomainObjectContainer会自动创建这些Configuration对象。 - DSL 支持:通过闭包块配置这些对象的属性,例如
a和b。 - 延迟评估:在项目评估完成后,插件可以遍历
configurations容器,处理所有定义的配置。
总结
NamedDomainObjectContainer 是 Gradle 中管理一组命名对象的强大工具,非常适合用于开发需要 DSL 配置的插件。它提供了一种自然的方式,通过闭包或配置块来创建和配置对象,从而使插件的配置更直观和灵活。