APT和AOP在android那些事情

APT和AOP在android那些事情

业务背景

apt

大家对eventbus应该不会陌生吧,eventbus是一个非常优秀的事件总线框架,在设计模式中,有点类似观察者模式,只不过一个升级版本的观察者模式,并且发送跟接收是切割的,解决很多让人头疼的内存泄漏问。其中eventbus所用到的技术就是apt,如果大家在项目中有使用到观察者模式,不妨用eventbus来改善一下。

aop

想象一个业务场景,业务要统计activity的启动耗时,也就是oncreate,onstart这些生命周期方法的耗时,一种原始的方式就是在每个activity的生命周期中添加重复的代码,比如:

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        long start=System.currentTimeMillis();
        super.onCreate(savedInstanceState);  //1
        setContentView(R.layout.activity_main);
        long spend=System.currentTimeMillis()-start; //2
    }

想想一个activity那么多生命周期,一个android项目那么多activity,是不是很繁琐呢。这时候aop就出场了,为什么不用谷歌亲儿子apt呢,因为apt一个比较大的局限性是:无法在当前类添加删除代码,只能创建一个新的类。简单点概括就是aop是一个比apt更强大的代码生成框架。

简介

  • APT:(Annotation Processing Tool)即注解处理器,是一种注解处理的工具,用来在编译器扫描以及处理注解。以注解作为桥梁,通过预先设定好的代码规则来生成对应的Java代码
  • AOP:AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。所以这里所代表的其实是一种思想,实现这个思想的技术有:ASPECTJ,ASM,JAVASIST,主要是这三个派系
    ## 对比
能力 APT AOP
创建新类 y y
修改当前类 n y
实现技术 AutoService ASPECTJ,ASM,JAVASIST
注解 y y
sdk代码修改 n y

android打包流程

android官方文档
build-process_2x

上一张图中,compilers阶段其实是有很多个transform组成的
4821599-9f88c2f9936af805

其中apt,aop都是作用于compilers阶段apt作用于class -->.dex阶段,aop作用于class-->.dex或者jar-->.dex阶段。可以进一步看到aop更加强大

使用小建议

apt,aop虽然能够减少很多重复代码量,代码结构优化,但是也看出来了,没有源代码,不利于排查问题,所以使用者一定要克制,不是这两个技术很黑科技就喜欢去使用,否则就是给自己的项目埋下风险。同学编写这些apt,aop代码的同学一定要留够足够的调试信息,方便后续的问题追踪

细讲apt

其实网络上已经有很多优秀apt的案例,就不想重复的编写这个demo.贴一个推荐的案例
apt案例

细讲aop

asm实现

用来动态生成类或者增强既有类的功能,ASM是可以直接产生二进制 class 文件,也可以在类被加载入 Java 虚拟机之前动态改变类行为,底层字节码框架,操纵的级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解。

总体思路讲解

  • 注册transform,接收编译阶段代码的输入,这里主要有class和jar包
  • 使用java的jarfile接口解析jar包,并且获得jar包里面的class文件
 JarFile jarFile = new JarFile(inFile)
  Enumeration<JarEntry> entries = jarFile.entries()
  • 使用asm借口解析jar包里面的class,更改自己想要的代码操作,建议使用asm5版本,gradle默认会有这个sdk,无需集成,示例:
ClassReader reader = new ClassReader(entryBytes)
ClassWriter classWriter = new ClassWriter(reader, ClassWriter.COMPUTE_MAXS);
ClassVisitor visitor = new MyClassVisitor(classWriter)
  • 无论更改与否jar包或者class,都要将文件拷贝到下一个输入位置,参考示例:
 File outFile = transformInvocation.outputProvider.getContentLocation(
                                    jarInput.file.absolutePath,
                                    jarInput.contentTypes,
                                    jarInput.scopes,
                                    Format.JAR)
FileUtils.copyFile(jarInput.file, outFile)

网上有一个非常好的讲解,并且有示例源码:
案例

aspectj实现

aspectj是通过注解来实现aop的切面方案,也是最容易上手的一个方案
案例

javassit实现

案例

总结

上面的讲究都是引用了其他人的讲解成果,后面会输出个人编写demo的文章,更加细致的讲解aop这块,当然估计可能没有我现在所引用的案例优秀,透彻。


希望我的文字能给你带来帮助,同时也欢迎关注个人公众号,我的所有文章第一手信息回优先发布这里。
个人公众号:河边的小黑屋

发布了8 篇原创文章 · 获赞 5 · 访问量 9989

猜你喜欢

转载自blog.csdn.net/a498415077/article/details/104591191