Gradle —— 自定义 Plugin(1)

2019-12-16  本文已影响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 可以分别显示当前时间和日期。

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

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

比如上例中,我们通过

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 中的值在使用时才被计算,而不像以前一样声明时就被计算好了。

上一篇 下一篇

猜你喜欢

热点阅读