插件介绍
插件可以来自 Gradle 或 Gradle 社区。但是,当用户想要组织他们的构建逻辑或需要现有插件未提供的特定构建功能时,他们可以开发自己的插件。
因此,我们区分三种不同类型的插件
-
核心插件 - 来自 Gradle 的插件。
-
社区插件 - 来自 Gradle 插件门户 或公共仓库的插件。
-
本地或自定义插件 - 您自己开发的插件。
核心插件
术语核心插件指的是 Gradle 发行版的一部分的插件,例如 Java Library 插件。它们始终可用。
社区插件
术语社区插件指的是发布到 Gradle 插件门户(或另一个公共仓库)的插件,例如 Spotless 插件。
本地或自定义插件
术语本地或自定义插件指的是您为自己的构建编写的插件。
脚本插件
脚本插件通常是在脚本文件中编写的小型本地插件,用于特定于单个构建或项目的任务。它们不需要在多个项目中重用。不建议使用脚本插件,但许多其他形式的插件都是从脚本插件演变而来的。
要创建插件,您需要编写一个实现 Plugin 接口的类。
以下示例创建一个 GreetingPlugin
,它在应用时向项目添加一个 hello
任务
class GreetingPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.task("hello") {
doLast {
println("Hello from the GreetingPlugin")
}
}
}
}
// Apply the plugin
apply<GreetingPlugin>()
class GreetingPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hello') {
doLast {
println 'Hello from the GreetingPlugin'
}
}
}
}
// Apply the plugin
apply plugin: GreetingPlugin
$ gradle -q hello Hello from the GreetingPlugin
Project
对象作为参数传递到 apply()
中,插件可以使用它来配置项目所需的任何内容(例如添加任务、配置依赖项等)。在此示例中,插件直接在构建文件中编写,这不是推荐的做法。
当插件在单独的脚本文件中编写时,可以使用 apply(from = "file_name.gradle.kts")
或 apply from: 'file_name.gradle'
应用它。在下面的示例中,插件在 other.gradle(.kts)
脚本文件中编码。然后,使用 apply from
将 other.gradle(.kts)
应用于 build.gradle(.kts)
class GreetingScriptPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.task("hi") {
doLast {
println("Hi from the GreetingScriptPlugin")
}
}
}
}
// Apply the plugin
apply<GreetingScriptPlugin>()
class GreetingScriptPlugin implements Plugin<Project> {
void apply(Project project) {
project.task('hi') {
doLast {
println 'Hi from the GreetingScriptPlugin'
}
}
}
}
// Apply the plugin
apply plugin: GreetingScriptPlugin
apply(from = "other.gradle.kts")
apply from: 'other.gradle'
$ gradle -q hi Hi from the GreetingScriptPlugin
应避免使用脚本插件。
预编译脚本插件
预编译脚本插件在执行之前被编译成类文件并打包到 JAR 中。这些插件使用 Groovy DSL 或 Kotlin DSL 而不是纯 Java、Kotlin 或 Groovy。它们最适合用作约定插件,用于在项目之间共享构建逻辑或作为整洁地组织构建逻辑的方式。
要创建预编译脚本插件,您可以
-
使用 Gradle 的 Kotlin DSL - 插件是一个
.gradle.kts
文件,并应用kotlin-dsl
-
使用 Gradle 的 Groovy DSL - 插件是一个
.gradle
文件,并应用id("groovy-gradle-plugin")
。
要应用预编译脚本插件,您需要知道其 ID。ID 从插件脚本的文件名及其(可选)包声明派生而来。
例如,脚本 src/main/*/some-java-library.gradle(.kts)
的插件 ID 为 some-java-library
(假设它没有包声明)。同样,src/main/*/my/some-java-library.gradle(.kts)
的插件 ID 为 my.some-java-library
,只要它具有 my
的包声明。
预编译脚本插件名称有两个重要的限制
-
它们不能以
org.gradle
开头。 -
它们不能与 核心插件 同名。
当插件应用于项目时,Gradle 会创建插件类的实例并调用该实例的 Plugin.apply() 方法。
在每个应用该插件的项目中都会创建一个新的 Plugin 实例。 |
让我们将 GreetingPlugin
脚本插件重写为预编译脚本插件。由于我们正在使用 Groovy 或 Kotlin DSL,因此该文件实际上变成了插件。原始脚本插件只是创建了一个 hello
任务,该任务打印问候语,这就是我们将在预编译脚本插件中执行的操作
tasks.register("hello") {
doLast {
println("Hello from the convention GreetingPlugin")
}
}
tasks.register("hello") {
doLast {
println("Hello from the convention GreetingPlugin")
}
}
现在可以通过使用其 ID 在其他子项目的构建中应用 GreetingPlugin
plugins {
application
id("GreetingPlugin")
}
plugins {
id 'application'
id('GreetingPlugin')
}
$ gradle -q hello Hello from the convention GreetingPlugin
约定插件
约定插件通常是预编译脚本插件,它使用您自己的约定(即默认值)配置现有的核心和社区插件,例如通过使用 java.toolchain.languageVersion = JavaLanguageVersion.of(17)
设置 Java 版本。约定插件也用于强制执行项目标准并帮助简化构建过程。它们可以应用和配置插件、创建新任务和扩展、设置依赖项等等。
让我们以一个包含三个子项目的示例构建为例:一个用于 data-model
,一个用于 database-logic
,一个用于 app
代码。该项目具有以下结构
.
├── buildSrc
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── data-model
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── database-logic
│ ├── src
│ │ └──...
│ └── build.gradle.kts
├── app
│ ├── src
│ │ └──...
│ └── build.gradle.kts
└── settings.gradle.kts
database-logic
子项目的构建文件如下所示
plugins {
id("java-library")
id("org.jetbrains.kotlin.jvm") version "2.0.21"
}
repositories {
mavenCentral()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(11)
}
// More build logic
plugins {
id 'java-library'
id 'org.jetbrains.kotlin.jvm' version '2.0.21'
}
repositories {
mavenCentral()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
// More build logic
我们应用 java-library
插件并添加 org.jetbrains.kotlin.jvm
插件以获得 Kotlin 支持。我们还配置了 Kotlin、Java、测试等。
我们的构建文件开始变得庞大……
我们应用的插件越多,配置的插件越多,它就变得越大。app
和 data-model
子项目的构建文件中也存在重复,尤其是在配置通用扩展(例如设置 Java 版本和 Kotlin 支持)时。
为了解决这个问题,我们使用约定插件。这使我们能够避免在每个构建文件中重复配置,并使我们的构建脚本更简洁且更易于维护。在约定插件中,我们可以封装任意构建配置或自定义构建逻辑。
为了开发约定插件,我们建议使用 buildSrc
– 它代表一个完全独立的 Gradle 构建。buildSrc
有自己的 settings 文件来定义此构建的依赖项位于何处。
我们在 buildSrc/src/main/kotlin
目录内添加一个名为 my-java-library.gradle.kts
的 Kotlin 脚本。或者,相反,在 buildSrc/src/main/groovy
目录内添加一个名为 my-java-library.gradle
的 Groovy 脚本。我们将来自 database-logic
构建文件的所有插件应用和配置都放入其中
plugins {
id("java-library")
id("org.jetbrains.kotlin.jvm")
}
repositories {
mavenCentral()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(11)
}
plugins {
id 'java-library'
id 'org.jetbrains.kotlin.jvm'
}
repositories {
mavenCentral()
}
java {
toolchain.languageVersion.set(JavaLanguageVersion.of(11))
}
tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain {
languageVersion.set(JavaLanguageVersion.of(11))
}
}
文件名 my-java-library
是我们全新插件的 ID,我们现在可以在所有子项目中使用它。
为什么缺少 id 'org.jetbrains.kotlin.jvm' 的版本?请参阅 将外部插件应用于预编译脚本插件。 |
通过删除所有冗余构建逻辑并应用我们的约定 my-java-library
插件,database-logic
构建文件变得更加简单
plugins {
id("my-java-library")
}
plugins {
id('my-java-library')
}
此约定插件使我们能够轻松地在所有构建文件之间共享通用配置。任何修改都可以在一个地方完成,从而简化维护。
二进制插件
Gradle 中的二进制插件是构建为独立 JAR 文件并使用构建脚本中的 plugins{}
块应用于项目的插件。
让我们将我们的 GreetingPlugin
移动到一个独立项目,以便我们可以发布它并与他人共享。该插件基本上是从 buildSrc
文件夹移动到其自己的名为 greeting-plugin
的构建。
您可以从 buildSrc 发布插件,但这不是推荐的做法。准备发布的插件应位于其自己的构建中。 |
greeting-plugin
只是一个 Java 项目,它生成一个包含插件类的 JAR。
将插件打包和发布到仓库的最简单方法是使用 Gradle 插件开发插件。此插件提供必要的任务和配置(包括插件元数据),以将您的脚本编译成可以在其他构建中应用的插件。
这是使用 Gradle 插件开发插件的 greeting-plugin
项目的简单构建脚本
plugins {
`java-gradle-plugin`
}
gradlePlugin {
plugins {
create("simplePlugin") {
id = "org.example.greeting"
implementationClass = "org.example.GreetingPlugin"
}
}
}
plugins {
id 'java-gradle-plugin'
}
gradlePlugin {
plugins {
simplePlugin {
id = 'org.example.greeting'
implementationClass = 'org.example.GreetingPlugin'
}
}
}
有关发布插件的更多信息,请参阅 发布插件。
Project 插件 vs Settings 插件 vs Init 插件
在本节中使用的示例中,插件接受 Project 类型作为类型参数。或者,插件可以接受类型为 Settings 的参数以在 settings 脚本中应用,或者接受类型为 Gradle 的参数以在初始化脚本中应用。
这些类型的插件之间的区别在于其应用范围
- Project 插件
-
Project 插件是应用于构建中特定项目的插件。它可以自定义构建逻辑、添加任务和配置项目特定的设置。
- Settings 插件
-
Settings 插件是在
settings.gradle
或settings.gradle.kts
文件中应用的插件。它可以配置应用于整个构建的设置,例如定义构建中包含哪些项目、配置构建脚本仓库以及将通用配置应用于所有项目。 - Init 插件
-
Init 插件是在
init.gradle
或init.gradle.kts
文件中应用的插件。它可以配置全局应用于机器上所有 Gradle 构建的设置,例如配置 Gradle 版本、设置默认仓库或将通用插件应用于所有构建。