美文网首页
Gradle —— 自定义 Plugin(1)

Gradle —— 自定义 Plugin(1)

作者: 你可记得叫安可 | 来源:发表于2019-12-16 15:49 被阅读0次

自定义 Plugin 可以向任意一个 Gradle 类进行操作。比如向 Project 添加 TaskConfigurationProperty 等。
Task 一样,我们会用 3 种方式来创建自定义 Plugin

在 build.gradle 中直接定义 Plugin

apply plugin: DateAndTimePlugin

// 运行时配置的 extension
dateAndTime {
    timeFormat = 'HH:mm:ss.SSS'
    dateFormat = 'MM/dd/yyyy'
}

class DateAndTimePlugin implements Plugin<Project> {
    void apply(Project project) {
        project.extensions.create("dateAndTime", DateAndTimePluginExtension)
        project.task('showTime') {
            doLast{
                println "Current time is " + new Date().format(project.dateAndTime.timeFormat)
            }
        }
        project.task('showDate') {
            doLast {
                println "Current date is " + new Date().format(project.dateAndTime.dateFormat)
            }
        }
    }
}

// 插件默认的 extension
class DateAndTimePluginExtension {
    String timeFormat = "MM/dd/yyyyHH:mm:ss.SSS"
    String dateFormat = "yyyy-MM-dd"
}

执行命令 gradle :showTimegradle :showDate 可以分别显示当前时间和日期。

  • 我们自定义 Plugin 就需要实现 Plugin<T> 接口。该接口接收一个 Gradle 类,而且它只有一个 apply(T t) 方法。因此一个 Plugin 实际上是一个 hook 方法,它在 Gradle 的打包流程中 hook Gradle 的某些类。

比如我们上面的例子,就是向 Project 添加了 2 个 Task,一个名为 showTime,一个名为 showDate

  • Project#apply() 会在 Configure 阶段被执行。

  • 每个 GradleProject 都维护了一个 ExtensionContainer,我们可以向其中添加自定义扩展,并附上默认值。

比如上面例子,我们就给 Project 添加了一个名为 dateAndTimeextension,它的默认值是 DateAndTimePluginExtension 的实例,它已经有了两个默认扩展值,分别是 timeFormatdateFormat。例子中 create 方法使用的是create(String name, Class<T> type, Object... constructionArguments)

  • 在使用时,我们可以通过 project.extensions 来访问已定义的扩展,并对其中的配置重新赋值。

比如上例中,我们通过

dateAndTime {
   timeFormat = 'HH:mm:ss.SSS'
   dateFormat = 'MM/dd/yyyy'
}

在运行时对名为 dateAndTime 的扩展配置进行了重新赋值。之所以没有显式调用 extensions,这是因为 Gradle 中大量应用了代理模式。这里 Project 将参数 dateAndTime 代理给了 ExtensionContainer,因此最后操作的是 ExtensionContainer 中已有的 dateAndTime 扩展。

在当前工程中定义 Plugin

创建如下的工程目录

gradle 工程
Gradle 会默认去寻找 /buildSrc/src/main/groovy 下的所有文件,如果发现有 Plugin 则会将该 Plugin 添加到 PluginContainer 中。类 DateAndTimePluginDateAndTimePluginExtension 分别来自上节中的 pluginextension 代码,只不过多了一个包名 learning。在使用该 Pluginbuild.gralde 文件中,在 applyPlugin 时,我们需要声明对该 Plugin 的全限定名:apply plugin: learning.DateAndTimePlugin。之后我们就可以配置自定义扩展 dateAndTime了。
apply plugin: learning.DateAndTimePlugin

 dateAndTime {
     timeFormat = 'HH:mm:ss.SSS'
     dateFormat = 'MM/dd/yyyy'
 }

运行 gradle :showTime 可得结果。


关于 Extension 的写法

我们上面写的 Extension 就是一个 Java Bean 类,但是其实 Extension 还有另外的写法。

public class BinaryRepositoryExtension {
    private final Property<String> serverUrl;

    public BinaryRepositoryExtension(Project project) {
        serverUrl = project.getObjects().property(String.class);
    }

    public Property<String> getServerUrl() {
        return serverUrl;
    }
}

上面的 BinaryRepositoryExtension 使用了 Property 来保存 serverUrl。从构造函数中传入 project,这样就形成了 ExtensionProject 之间的桥梁。
同时,Plugin 中构造 Extension 的方法也需要改变:

BinaryRepositoryExtension extension = target.getExtensions().create("binaryRepo", BinaryRepositoryExtension.class, target);

target.getTasks().register("latestArtifactVersion", LatestArtifactVersion.class, new Action<LatestArtifactVersion>() {
            @Override
            public void execute(LatestArtifactVersion latestArtifactVersion) {
                latestArtifactVersion.getServerUrl().set(extension.getServerUrl());
            }
        });

这里使用的是接受 Project 参数的 create 方法。

Property 是什么?

Extension 之前的写法中,就是一个纯粹的 Java Bean,我们在使用时本质上也是直接给 Extension 中的变量进行赋值。
例如

dateAndTime {
     timeFormat = 'HH:mm:ss.SSS'
     dateFormat = 'MM/dd/yyyy'
 }

就是直接对 timeFormat 进行赋值。这里 timeFormatString 类型。
而我们使用改进写法的 BinaryRepositoryExtension 中,它的 serverUrl 不再是单纯的 String 类型,而是由 Property 进行包装后的类型。
那么这里的 Property 是什么呢?这是 Gradle 提供的延迟加载机制,是 Gradle 4.0 之后提供的。这主要是为了保证 Property 中的值在使用时才被计算,而不像以前一样声明时就被计算好了。

相关文章

网友评论

      本文标题:Gradle —— 自定义 Plugin(1)

      本文链接:https://www.haomeiwen.com/subject/xjqtgctx.html