Javassist 编写优于 EventBus 事件分发

AOP简介

什么是 AOP

面向切面编程, AOP, Aspect Oriented Program 的首字母缩写。 面向对象(OOP)的特点是把功能分配到不同的对象中, 软件设计中称为指责分配。

假象下,每个对象都可以看做是种个圆柱体,当每个圆柱体都需要做一件有共性事情(加个粉色的圆,突出圆柱)的时候。如果用面向对象的思想,只能每个面都是修改下,而且重复 cv 的修改。

上面问题中有一个大刀, 能一次把所有圆柱切开,一次把所有面都加工好。那么,这个行为就是AOP。可以这么理解,AOP是OOP的横向补充,把每个原本只有二维的面切开,拉伸出第三维度(Z轴)来

AOP 能干什么

android 中比较常用的如

统一添加调用时长统计,日志统计,log输出等

部分页面是需要验证登录通过才能打开

统一添加权限申请验证

按钮防重复点击

等等诸如此类。

AOP 如何实现

传统的实现方式是通过代理模式,这种方式有一定的局限。如果可以通过编译器编译或脚本自动插入代码,这种方式是比较优雅,可拓展性强的。

这就要介绍下 android 的 AOP 三剑客了。APT、AspectJ、Javassist对应编译时期。

今天我要讲的就是这个 Javassist 了。在这之前,先给说下 gradle 插件。

Gradle 插件开发

这两行当代相信大家再熟悉不过了。这两个其实也都是 gradle 插件,一个是可运行的 app module ,一个是依赖库。

这是 gradle 自带的插件,其他也有很多,像我们比较多使用的如 ButterKnife、Lambda 这些常用的也是大牛封装好的在线插件。接下来我们要开发我们自己的插件。

我们新建一个 module 中 配置一下信息

在 目录下新建一个和目录, 这个是固定的格式。如图,上面的下的包名结构可自定义。

plugin 类实现 接口

com.app.plugin.javassist.properties只有一行

写上JavassistPlugin 的全路径

然后执行或者在右边栏找到命令执行。就会生成我们的插件,出现这个就带表我们生成的插件成功了。每次修改后都要执行这个命令更新插件

project 的 build.gradle下需要配置一下插件应用

在 module 中应用下插件,就完成了

Javassist 实现事件分发

类似 EventBus 实现,通过注解的方式, 完成事件分发。因为纵观 EventBus 还是有相当一部分是通过异端分子(反射)来实现的,性能有约束。今天来试试用 Javassist 完美实现 EventBus 事件分发。

写这个是因为目前项目也没有用 EventBus ,是用自己封装的类,用的

三个这样的 Map,-个存 handler 、一个存 handler 的自定义方法、一个存锁引用, 有个好处就是,方法名字参数可以随意定制,不像 EventBus 固定对象传输, 调用又要反射 ,但是这样就比较消耗内存了, 用空间换时间,相对传统方法快一点。调用相对蛋疼,容易写错。 如果大家想了解,关注公众号,跟我交流。

相比传统实现有哪些优势

代码非常简洁。 在或完全不需要手动调用和这样的代码。

高效。 由于 javassist 是在 class 转 dex 的编译期实现的,动态代码插入,完成不涉及反射代码,比 EventBus 优秀。

不关心线程切换问题。 只需要在注解中传入参数, 实现线程自定切换。

用法

事件接收用法跟 EventBus 类似, 注册跟反注册通过注解标记来完成,activity 跟fragment 无需注册反注册。

实现

注册监听实现

反注册

事件分发

首先需要 plugin module 引入 dependencies 来支持 javassist

以下是插件 javassist核心代码, 用来实现自动注入代码。原理就是插入代码,说白了就是字符串拼接。groovy的语法也非常简单,完全兼容 Java

有一点我想吐槽,他的语法跟 kotlin 相似,但是有没有模仿到位,就是 groovy 不支持传入被调用方法少于他需要的参数,kotlin 可以。我觉得可以优化下。

具体实现代码,大家可以去我的github查看https://github.com/luomoBM/AopTest

这个单独抽取出来当个事件分发库使用

目前事件通知接收方法只支持少于等于一个参数,如果需要支持多个参数可自行修改。

Javassist 还有很多 api 用法, 项目中没用到,如果大家感兴趣的话可以去https://jboss-javassist.github.io/javassist/tutorial/tutorial.html看看里面的文档,挺详细的,可以用 Google 翻译配合查看,别告诉我你不会科学上网。。

这里还有个 Gradle 脚本的 Api 文档 对于 Gradle 插件编写有帮助。http://google.github.io/android-gradle-dsl/javadoc/current/

希望这个文章对大家有帮助,并且记录自己的成长,共勉。

如果文章对你有帮助,大家可以赞赏支持鼓励下作者。

有什么疑问可以关注下方我的公众号, 留言就行。

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20180601G0N2EC00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券