如果 Gradle 或 Gradle 社区无法提供您的项目所需的特定功能,创建自己的自定义插件可能是一个解决方案。
此外,如果您发现自己跨子项目重复构建逻辑,并且需要更好的方式来组织它,约定插件可以提供帮助。
脚本插件
插件是实现 Plugin
接口的任何类。例如,这是一个“hello world”插件
abstract class SamplePlugin : Plugin<Project> { (1)
override fun apply(project: Project) { (2)
project.tasks.register("ScriptPlugin") {
doLast {
println("Hello world from the build file!")
}
}
}
}
apply<SamplePlugin>() (3)
class SamplePlugin implements Plugin<Project> { (1)
void apply(Project project) { (2)
project.tasks.register("ScriptPlugin") {
doLast {
println("Hello world from the build file!")
}
}
}
}
apply plugin: SamplePlugin (3)
1 | 扩展 org.gradle.api.Plugin 接口。 |
2 | 覆盖 apply 方法。 |
3 | 将插件 apply 到项目中。 |
1. 扩展 org.gradle.api.Plugin
接口
创建一个扩展 Plugin
接口的类
abstract class SamplePlugin : Plugin<Project> {
}
class SamplePlugin implements Plugin<Project> {
}
2. 覆盖 apply
方法
在 apply()
方法中添加任务和其他逻辑
override fun apply() {
}
void apply(Project project) {
}
3. 将插件 apply
到您的项目中
当 SamplePlugin
应用到您的项目中时,Gradle 会调用定义的 fun apply() {}
方法。这会将 ScriptPlugin
任务添加到您的项目中
apply<SamplePlugin>()
apply plugin: SamplePlugin
请注意,这只是一个简单的 hello-world
示例,并**不**反映最佳实践。
不推荐使用脚本插件。 |
开发插件的最佳实践是创建*约定插件*或*二进制插件*。
预编译脚本插件
预编译脚本插件提供了一种快速原型设计和实验的简单方法。它们允许您使用 Groovy 或 Kotlin DSL 将构建逻辑打包为 *.gradle(.kts)
脚本文件。这些脚本位于特定目录中,例如 src/main/groovy
或 src/main/kotlin
。
要应用其中一个,只需使用其从脚本文件名(不带 .gradle
)派生的 ID
。您可以将文件本身视为插件,因此在预编译脚本中无需子类化 Plugin
接口。
让我们看一个具有以下结构的示例
.
└── buildSrc
├── build.gradle.kts
└── src
└── main
└── kotlin
└── my-create-file-plugin.gradle.kts
我们的 my-create-file-plugin.gradle.kts
文件包含以下代码
abstract class CreateFileTask : DefaultTask() {
@get:Input
abstract val fileText: Property<String>
@Input
val fileName = "myfile.txt"
@OutputFile
val myFile: File = File(fileName)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
tasks.register<CreateFileTask>("createMyFileTaskInConventionPlugin") {
group = "from my convention plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY CONVENTION PLUGIN")
}
abstract class CreateFileTask extends DefaultTask {
@Input
abstract Property<String> getFileText()
@Input
String fileName = "myfile.txt"
@OutputFile
File getMyFile() {
return new File(fileName)
}
@TaskAction
void action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
tasks.register("createMyFileTaskInConventionPlugin", CreateFileTask) {
group = "from my convention plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY CONVENTION PLUGIN")
}
预编译脚本现在可以应用于任何子项目的 build.gradle(.kts
) 文件中
plugins {
id("my-create-file-plugin") // Apply the pre-compiled convention plugin
`kotlin-dsl`
}
plugins {
id 'my-create-file-plugin' // Apply the pre-compiled convention plugin
id 'groovy' // Apply the Groovy DSL plugin
}
插件中的 createMyFileTaskInConventionPlugin
任务现在可以在您的子项目中使用了。
二进制插件
二进制插件是用编译语言实现的插件,并打包为 JAR 文件。它作为依赖项解析,而不是从源代码编译。
对于大多数用例,约定插件无需频繁更新。让每个开发人员在开发过程中执行插件构建是浪费的,我们可以将其分发为二进制依赖项。
有两种方法可以将上述示例中的约定插件更新为二进制插件。
我们选择第二种方案。这个插件已经用 Kotlin 重写,并命名为 MyCreateFileBinaryPlugin.kt
。它仍然存储在 buildSrc
中
import org.gradle.api.DefaultTask
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
import java.io.File
abstract class MyCreateFileTask : DefaultTask() {
@get:Input
abstract val fileText: Property<String>
@Input
val filePath = project.layout.settingsDirectory.file("myfile.txt").asFile.path
@OutputFile
val myFile: File = File(filePath)
@TaskAction
fun action() {
myFile.createNewFile()
myFile.writeText(fileText.get())
}
}
class MyCreateFileBinaryPlugin : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.register("createFileTaskFromBinaryPlugin", MyCreateFileTask::class.java) {
group = "from my binary plugin"
description = "Create myfile.txt in the current directory"
fileText.set("HELLO FROM MY BINARY PLUGIN")
}
}
}
插件可以通过 gradlePlugin{}
块发布并给定一个 id
,以便可以在根目录中引用它
group = "com.example"
version = "1.0.0"
gradlePlugin {
plugins {
create("my-binary-plugin") {
id = "com.example.my-binary-plugin"
implementationClass = "MyCreateFileBinaryPlugin"
}
}
}
publishing {
repositories {
mavenLocal()
}
}
group = 'com.example'
version = '1.0.0'
gradlePlugin {
plugins {
create("my-binary-plugin") {
id = "com.example.my-binary-plugin"
implementationClass = "MyCreateFileBinaryPlugin"
}
}
}
publishing {
repositories {
mavenLocal()
}
}
然后,插件可以在构建文件中应用
plugins {
id("my-create-file-plugin") // Apply the pre-compiled convention plugin
id("com.example.my-binary-plugin") // Apply the binary plugin
`kotlin-dsl`
}
plugins {
id 'my-create-file-plugin' // Apply the pre-compiled convention plugin
id 'com.example.my-binary-plugin' // Apply the binary plugin
id 'groovy' // Apply the Groovy DSL plugin
}
查阅开发插件章节以了解更多信息。