使用插件是现代自动化构建工具中一个非常重要的概念,Gradle 作为其中一个流行工具,通过插件提供了多种便利。以下是使用插件的几个主要原因:
插件在 Gradle 构建系统中扮演着至关重要的角色,它们为项目提供了额外的功能和自动化能力。以下是插件在项目构建过程中可以完成的一些事情:
src/main/java
作为源代码目录。
插件是 Gradle 强大的扩展机制,它们可以极大地简化构建配置,提供最佳实践,并允许开发者通过标准化的方式来构建项目。通过应用插件,你可以快速获得构建、测试、打包和依赖管理等自动化功能,同时保持项目的灵活性和可维护性。
在 Gradle 中,脚本插件是一种允许你通过外部 Groovy 脚本文件来扩展构建逻辑的方法。这些脚本可以定义变量、任务、配置等,并且可以通过 apply from
语句被导入到主构建脚本中。
version.gradle
。// version.gradle
ext {
company = "阿杰"
cfgs = [
compileSdkVersion: JavaVersion.VERSION_21
]
spring = [
version: '6.0.0'
]
}
在这个脚本中,我们使用了 ext
来定义了一系列的属性,这些属性在导入脚本后可以在构建脚本中使用。
build.gradle
文件中,使用 apply from
来加载外部脚本。// build.gradle
apply from: 'version.gradle'
task taskVersion {
doLast {
println "博主的昵称:${company}, JDK版本是${cfgs.compileSdkVersion}, 版本号是${spring.version}"
}
}
在这个构建脚本中,我们应用了之前创建的 version.gradle
脚本。然后我们定义了一个名为 taskVersion
的任务,它会在执行时打印出从脚本插件中导入的变量。
taskVersion
任务。gradle taskVersion
执行上述命令后,Gradle 会加载并执行 build.gradle
文件中的指令,包括应用外部脚本插件和执行 taskVersion
任务。
脚本插件是 Gradle 提供的一种灵活的扩展机制,允许你通过外部 Groovy 脚本来添加构建逻辑。这种方式非常适合于在多个项目之间共享配置或创建自定义的构建行为。通过使用脚本插件,可按功能把我们的脚本进行拆分一个个公用、职责分明的文件,然后在主脚本文件引用,
比如:将很多共有的库版本号一起管理、应用构建版本一起管理等。可以使构建脚本更加模块化和可重用。
Gradle 的对象插件,也称为二进制插件或 Java 插件,是通过实现 org.gradle.api.Plugin
接口的 Java 类来提供的。这些插件为项目提供了特定的构建功能,并且可以通过一个唯一的插件 ID 来应用到项目中。
Gradle 提供了一系列的核心插件,这些插件覆盖了多种常见的构建需求,包括但不限于:
查找核心插件:
要查找 Gradle 提供的所有核心插件,可以访问官方文档中的插件参考页面:
在这里,你可以找到每个插件的描述、提供的配置和如何应用该插件的指导。
以下是几种应用 Java 插件到项目中的方法:
使用插件 ID:
apply plugin: 'java'
这是应用 Java 插件的推荐方式,简洁且易于理解。
使用闭包:
apply {
plugin 'java'
}
这种方式使用了一个闭包来包裹插件 ID,这在需要应用多个插件时非常有用。
使用全类名:
apply plugin: org.gradle.api.plugins.JavaPlugin
这种方式直接指定了插件的完整类名,这在 IDE 中自动完成代码时可能会看到。
使用导入的类:
apply plugin: JavaPlugin
如果 org.gradle.api.plugins
包已经被导入,你可以直接使用类名来引用插件。
插件 ID 的唯一性: 每个插件都有一个唯一的插件 ID,这有助于避免名称冲突。通常,插件 ID 会采用应用包名来确保其唯一性,如
java
对应的完整类名为org.gradle.api.plugins.JavaPlugin
。
在使用第三方发布的二进制插件时,通常需要确保 Gradle 能够从正确的仓库中获取这些插件。以下是两种常见的方法来应用这些插件:
使用 buildscript
块,你需要指定插件的类路径和仓库:
buildscript {
ext {
springBootVersion = "2.3.3.RELEASE"
}
repositories {
mavenLocal()
maven { url 'http://maven.aliyun.com/nexus/content/groups/public' }
jcenter()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'org.springframework.boot'
在这个例子中,我们首先定义了 buildscript
块,它告诉 Gradle 从哪里查找插件。repositories
块可以包含多个仓库,这里包括了 Maven 本地仓库、阿里云的 Maven 仓库和 JCenter。
Gradle 引入了一种新的 plugins
块,它提供了一种更简洁的方式来应用插件,特别是当插件被托管在 Gradle 插件仓库 时:
plugins {
id 'org.springframework.boot' version '2.4.1'
}
使用 plugins
块时,Gradle 会自动从 Gradle 插件仓库中解析插件的坐标,因此你不需要显式地指定类路径和仓库。
buildscript
块必须位于 build.gradle
文件的顶部。而 plugins
块则没有这个限制,可以放在文件的任何位置。
plugins
块使用 id
和 version
来指定插件的 ID 和版本,这使得构建脚本更加清晰和易于管理。
plugins
块时,Gradle 会自动解析插件的坐标,这意味着你不需要手动添加仓库和类路径。
使用 plugins
块可以简化插件的应用过程,特别是当你使用托管在 Gradle 插件仓库中的插件时。这种方式使得构建脚本更加简洁,同时减少了配置错误的可能性。然而,在一些情况下,你可能仍然需要使用传统的 buildscript
方法,比如当插件不是托管在 Gradle 插件仓库中,或者你需要自定义插件的类路径和仓库时。
在 Gradle 中,用户自定义插件是一种强大的扩展构建功能的方式。自定义插件允许你封装逻辑,创建新的任务,甚至向项目添加自定义的扩展属性和方法。这些插件可以用于单个项目,也可以被设计为可重用和可共享的。
/**
* GreetingPluginExtension 接口定义了问候插件的扩展属性。
* 这个接口规定了插件配置中可以使用的两个属性:getMessage 和 getGreeter。
*/
interface GreetingPluginExtension {
// getMessage 方法:获取问候语。
Property<String> getMessage()
// getGreeter 方法:获取发出问候的实体。
Property<String> getGreeter()
}
/**
* GreetingPlugin 类实现了 Plugin 接口,为 Gradle 提供了一个问候插件。
* 这个插件向项目中添加了一个 'hello' 任务,该任务在执行时会打印一条问候语。
*/
class GreetingPlugin implements Plugin<Project> {
/**
* apply 方法将插件应用到指定的项目上。
* @param project 要应用插件的项目实例。
*/
void apply(Project project) {
// 创建一个名为 'greeting' 的插件扩展,允许用户自定义问候语和发出问候的实体。
def extension = project.extensions.create('greeting', GreetingPluginExtension)
// 创建一个名为 'hello' 的任务,任务执行时会打印配置的问候语。
project.task('hello') {
doLast {
// 打印问候语,使用插件扩展中配置的消息和发出问候的实体。
println "${extension.message.get()} from ${extension.greeter.get()}"
}
}
}
}
// 应用 GreetingPlugin 插件到当前的 Gradle 项目中。
apply plugin: GreetingPlugin
// 配置插件扩展,设置问候语和发出问候的实体。
greeting.message = 'Hello from plugin'
greeting.greeter = 'Gradle'
虽然用户自定义插件非常灵活,但它们通常局限于定义它们的项目。这意味着,如果你在一个项目中定义了一个自定义插件,它可能不适用于其他项目,除非你将插件逻辑提取到一个独立的类或 JAR 文件中,并在其他项目中包含这个类或 JAR 文件。
为了使自定义插件可重用和共享,你可以:
buildSrc
:对于小型或特定于项目的插件,可以将插件代码放置在项目的 buildSrc
目录中。这样,插件可以被当前项目和子项目使用。自定义插件是 Gradle 插件系统的重要组成部分,它们允许开发者根据自己的需求扩展构建过程。通过创建自定义插件,你可以增加新的构建任务,定义配置选项,甚至提供全新的构建逻辑。自定义插件的开发需要对 Gradle 插件机制有深入的理解,并且需要遵循一定的设计原则以确保插件的可重用性和可维护性。
buildSrc
是 Gradle 提供的一个特殊目录,用于存放构建过程中使用的自定义 Groovy 插件和脚本。这个目录被视为一个独立的 Gradle 项目,你可以在这个目录下编写自己的插件和脚本,它们可以在整个构建过程中被重用。
以下是如何使用 buildSrc
目录的步骤:
buildSrc
模块将 buildSrc 从 included modules 移除,重新构建。
然后只保留 build.gradle 和 src/main 目录,其他全部删掉
plugins {
id 'java'
id 'groovy' // 必须
id 'maven-publish'
id 'java-gradle-plugin' // 必须
}
group = 'com.jie'
version = '1.0'
repositories {
google()
jcenter()
mavenCentral() //必须
}
// 项目入口 插件可以使用java groovy kotlin 三种语言进行编写
sourceSets {
main {
groovy {
srcDir 'src/main/groovy'
}
java {
srcDir 'src/main/java'
}
}
}
package com.jie
import org.gradle.api.Plugin
import org.gradle.api.Project
class Txt implements Plugin<Project> {
@Override
void apply(Project project) {
project.task("testPlugin") {
doLast {
println("Hello,Gradle Plugin")
}
}
}
}
// 插件入口
gradlePlugin {
plugins {
DependenciesPlugin {
id = 'com.jie.testPlugin'
implementationClass = 'com.jie.Txt'
}
}
}
然后执行插件的Task。
这种形式的写法,在我们整个工程的 module 都可以使用,但也只是限制在本工程,其他工程不能使用。
有时候我们需要一个插件在多个工程中使用,这时候我们就需要把插件上传 maven 中。
新建一个名称为plugin的Module。
Gradle Plugin可以用java写,也可以用kotlin、groovy,喜欢用什么就可以在main文件下新建对应语言的文件夹接口,比如groovy文件夹。
之前是用的Groovy写,这次用 Java。
// 插件入口
gradlePlugin {
plugins {
DependenciesPlugin {
id = 'com.jie.plugin.txtPlugin'
implementationClass = 'com.jie.plugin.Txt'
}
}
}
到此,Plugin的基本雏形就有了。
首先,比较常用的仓库是maven,在plugin>build.gradle文件中先依赖一个maven发布的插件maven-publish
publishing {
publications {
myLibrary(MavenPublication) {
groupId = 'com.jie.plugin' //指定GAV坐标信息
artifactId = 'txt'
version = '1.0'
from components.java //发布jar包
}
}
repositories {
maven {
url "$rootDir/lib/release"
}
//发布项目到私服中
// maven {
// name = 'myRepo' //name属性可选,表示仓库名称,url必填
// //发布地址:可以是本地仓库或者maven私服
// //url = layout.buildDirectory.dir("repo")
// //url='http://my.org/repo' // // change URLs to point to your repos, e.g. http://my.org/repo // //认证信息:用户名和密码
// credentials {
// username = 'joe'
// password = 'secret'
// }
// }
}
}
没有出现可能是idea 没有加载出来,刷新一下项目即可。
在settings.gradle文件中配置插件仓库地址
pluginManagement {
repositories {
maven {
url "$rootDir/lib/release"
}
}
}
在project>build.gradle文件中添加插件依赖
buildscript {
dependencies {
classpath('com.jie.plugin:txt:1.0')
}
}
再建一个module进行使用。
编译看效果:
在控制台看到自定义插件的输出,说明自定义插件就已经生效了。
最后,至于如何写一个插件,能帮助项目更加自动化或者便捷化,是值得大家未来需要长期思考、关注、努力的点。
apply plugin: '插件名'
当我们在工程中引入插件后,插件会自动的为我们的工程添加一些额外的任务来完成相应的功能。以 Java 插件为例,当
我们加入 java 插件之后,就加入了如下功能:
具体大家可通过 gradle tasks 查看加入某个插件前后的区别。
说明:Gradle 中的任务依赖关系是很重要的,它们之间的依赖关系就形成了构建的基本流程。
一些插件对工程目结构有约定,所以我们一般遵循它的约定结构来创建工程,这也是 Gradle 的“约定优于配置”原则。
例如 java 插件规定的项目源集目录结构如下所示:
如果要使用某个插件就应该按照它约定的目录结构设置,这样能大大提高我们的效率,当然各目录结构也可以自己定义
比如前面我们提到的 依赖的类型[依赖管理]部分,不同的插件提供了不同的依赖管理。
例如:Java 插件会为工程添加一些常用的属性,我们可以直接在编译脚本中直接使用。
属性名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
reportsDirName | String | reports | 生成报告的目录名称 |
reportsDir | File (只读) | buildDir/reportsDirName | 生成报告的目录 |
testResultsDirName | String | test-results | 生成测试.result.xml文件的目录名称 |
testResultsDir | File (只读) | reportsDir/testReportDirName | 生成测试报告的目录 |
libsDirName | String | libs | 生成 lib 库的目录名称 |
libsDir | File (只读) | buildDir/libsDirName | 生成 lib 库的目录 |
distsDirName | String | distributions | 生成发布文件的目录名称 |
distsDir | File (只读) | buildDir/distsDirName | 生成发布文件目录 |
docsDirName | String | docs | 生成帮助文档的目录名称 |
docsDir | File (只读) | buildDir/docsDirName | 生成帮助文档的目录 |
dependencyCacheDirNameString | String | dependency-cache | 存储缓存资源依赖信息的目录名称 |
dependencyCacheDir | File (只读) | buildDir/dependencyCacheDirName | 存储缓存资源依赖信息的目录 |
参考官网:https://docs.gradle.org/current/userguide/plugin_reference.html,以 Java 插件为例,讲解需要关注的几点:
plugins {
id 'java'
}
我们可通过官方文档介绍了解某个插件功能或者百度、再或者大家可以通过 gradle tasks 查看加入 java 插件前后的区别。
一般加入一个插件之后,插件也会提供相应的目录结构,例如:java 插件的目录结构
当然这个默认的目录结构也是可以改动的例如:
sourceSets {
main {
java {
srcDirs = ['src/java']
}
resources {
srcDirs = ['src/resources']
}
}
}
也可设置源集的属性等信息。