最近在研究编译插桩的三种方法: AspectJ
、 ASM
以及 Redex
中的 ASM
,要使用ASM就需要用插件的形式用在项目中,所以这篇的目的是了解并能自己定义一个Gradle插件。
网上现在很很多这样的文章,大家可以结合起来看。
Gradle
插件打包了可重用的构建逻辑,可以在许多不同的项目和构建中使用。
你可以用你喜欢的编码语言来实现一个自定义的Gradle插件,最终都会编译城jvm字节码。现在可以实现插件的语言有 Groovy
、 java
、 kotlin
等。一般来说,使用java或者kotlin实现的插件将优于使用groovy的相同插件。
实现插件的方式有三种,下面我会一一为大家来介绍。
你可以直接在 build.gradle
中构建一些简单的插件代码,这样做可以自动编译并包含在构建脚本的类路径中,无需执行任何操作。但是该插件只能用于本项目中,外部不可见。
class GreetingExtension { String message = null } class GreetingPlugin implements Plugin<Project> { @Override void apply(Project target) { // 利用利用Extension创建greeting 闭包,用于接受外部传递的参数值 def extension = target.extensions.create("greeting", GreetingExtension) target.task("customPlugin") { doLast() { println(extension.message) } } } } /** * 使用 greeting{}要放在 apply plugin 之后,apply plugin会执行apply方法进行绑定操作 * */ apply plugin: GreetingPlugin greeting { message = "Hi this is a cutstom plugin" } 复制代码
我们可以用命令行 或者AS右边的gradle在app中找到 customPlugin
./gradlew -p app customPlugin --stacktrace 复制代码
看下执行结果是什么:
> Task :app:customPlugin Hi this is a cutstom plugin BUILD SUCCESSFUL in 0s 1 actionable task: 1 executed 复制代码
将插件源代码放在 rootProjectDir/buildScr/scr/main/groovy
中,这种的优点在于自动编译项目目录下的buildSrc插件源码,不需要手动指定 classpath。同一项目其他模块也可使用。缺点就是对于其他项目不可用。第三种方式就解决了这个缺点。
这里如果想要了解可以看 这里
第三种和这个很类似,区别在于这是一个独立的插件项目,可以供其他项目使用。
这种方式是现在目前大多数在使用的方式。
在 Android Studio
中新建 Java Library
module customPlugin
,用IJ来开发插件会比AS要方便的很多。
用AS中开发插件需要这三步:
apply plugin: 'groovy' apply plugin: 'maven' repositories { mavenCentral() } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation gradleApi() // gradler sdk implementation localGroovy() // groovy sdk } uploadArchives { repositories { mavenDeployer { //设置插件的GAV参数 pom.groupId = 'com.lenny.plugin' pom.artifactId = 'art'// 这个如果不设置,发布之后应该是com.lenny.plugin.customPlugin pom.version = '1.0.3' //文件发布到下面目录 repository(url: uri('../repo')) } } } 复制代码
修改后的目录应该是这个样子的:
├── build.gradle ├── libs ├── customPlugin.iml └── src └── main ├── groovy │ └── com │ └── lenny │ └── plugin │ ├── CustomPlugin.groovy │ └── resources └── META-INF └── gradle-plugins └── com.lenny.plugin.properties 复制代码
CustomPlugin.groovy
package com.lenny.plugin import org.gradle.api.Plugin import org.gradle.api.Project public class CustomPlugin implements Plugin<Project> { @Override void apply(Project project) { println("hello from custom plugin") } } 复制代码
注意文件的后缀。
com.lenny.plugin.properties
implementation-class=com.lenny.plugin.CustomPlugin 复制代码
到这里就算基本完成了,我们同步下代码,就可以在右侧的Gradle中找到 uploadArchives
命令,执行该命令之后就会在项目同级目录下发现:
└── repo └── com ├── lenny │ └── plugin │ └── art │ └── 1.0.3 │ ├── art-1.0.3.jar │ ├── art-1.0.3.jar.md5 │ ├── art-1.0.3.jar.sha1 │ ├── art-1.0.3.pom │ ├── art-1.0.3.pom.md5 │ ├── art-1.0.3.pom.sha1 复制代码
然后我们在项目中集成:
工程的 build.gradle
中
buildscript { repositories { ... maven { url uri('repo/') } } dependencies { ... classpath 'com.lenny.plugin:art:1.0.3' } } 复制代码
app的 build.gradle
中
apply plugin: 'com.lenny.plugin' 复制代码
如果是发布在上线的,repositoies中就不这么写了。
classpath xxx的由来:groupId:artifactId:version
apply plugin: 'xxx'中则是 properties
的前面的: com.lenny.plugin
执行结果:
> Configure project :app hello from custom plugin > Task :app:createMockableJar UP-TO-DATE > Task :app:preBuild UP-TO-DATE 复制代码