在进入Gradle7.0 后,基于Gradle7.0 自定义的 Plugin
插件,处理 Asm
的代码插桩是非常简单的事情。我们只要关心查找和插桩代码就行了,一句话,把要修改的类找出来,在类对应的方法中 插入业务代码。
例如:我们在开发中,进行log 调试时,需要手动编写log代码,如果这一步骤交给asm就省了很多工作。 先来看看个简单的效果
在 MainActivity 的 onCreate 、onResume 方法中我们是没有写任何代码的,但是我运行打开app后能在控制台看到日志输出。而且我们知道了MainActivity 会走哪些方法。如下:
这其实是由我们的插件来完成的。 基于Gradle7.0 ,我们用5分钟来写一个插件看看:
一、构建一个能根据id 来获取 Plugin
的模块
插件可以放在本地,方便修改和调试,有需要可以上传至远程库。
说明:
-
1、 插件模块,是一个包含settings.gradle 的一个单独的模块,这里面,你可以创建多个自己想要的插件,其实也就是一个个module
-
2、定义好一个
DemoPlugin
,继承至Plugin<Project>
-
3、定义好一个
ModuleClassVisitorFactory
,继承至AsmClassVisitorFactory
-
4、创建 一个 resources , 定义插件由
com.demo.plugin.DemoPlugin
而来,注意插件包名要一致 -
5、build.gradle 中 ,定义好插件id
-
6、添加构建到setting.gradle 就可以了
以上都是简单的构建部分:
gradlePlugin {
plugins {
version {
id = 'com.demo.plugin'
displayName = 'DemoPlugin'
description = 'DemoPlugin'
implementationClass = 'com.demo.plugin.DemoPlugin'
}
}
}
二、处理 DemoPlugin
- 插件要对应的在
com.android.application
中添加 - 调用
variant.instrumentation
的transformClassesWith
方法添加我们处理class 的Factory
- 设置
setAsmFramesComputationMode
模式
三、处理 AsmClassVisitorFactory
-
在
AsmClassVisitorFactory
的isInstrumentable
方法中,所有class 类都会在这里被扫描到,依据这个,我们可以过滤出对应的 class ,添加到集合里面,返回 true ,即表示要进行代码手术了。 -
createClassVisitor
是isInstrumentable
方法之后被调用的,在这里进行代码手术,可以自定义一个ModuleClassVisitor
继承ClassVisitor
- 在
visitCode
方法中, class 类会在这里处理,也是手术的关键。这里 asm 的使用细节暂不多说。
四、使用 插件
在项目根目录build.gradle下,添加 id 'com.demo.plugin'
,多模块中,哪个模块需要用这个插件,就在他的build.gradle 也添加id 'com.demo.plugin'
,至此,准备工作就完了。
最后运行项目,能看到打印,即说明代码插入完成。