Android中的AOP

Android中的AOP

什么是AOP

AOP(Aspect Oriented Program的首字母缩写)是一种面向切面编程的思想。这种编程思想是相对于OOP(ObjectOriented Programming即面向对象编程)来讲的。html

先来讲一下你们熟悉的面向对象编程:面向对象的特色是继承、多态和封装。而封装就要求将功能分散到不一样的对象中去,这在软件设计中每每称为职责分配。实际上也就是说,让不一样的类设计不一样的方法。这样代码就分散到一个个的类中去了。这样作的好处是下降了代码的复杂程度,使类可重用。可是面向对象的编程天生有个缺点就是分散代码的同时,也增长了代码的重复性
好比我但愿在项目里面全部的模块都增长日志统计模块,按照OOP的思想,咱们须要在各个模块里面都添加统计代码,可是若是按照AOP的思想,能够将统计的地方抽象成切面,只须要在切面里面添加统计代码就OK了。java

image.png

其实在服务端的领域AOP已经被玩的风生水起,例如Spring的框架。

代码demo连接 github.com/xsfelvis/an…android

一、APT + JavaPoet

APT(Annotation Processing Tool 的简称),能够在代码编译期解析注解,结合JavaPoet 生成新的 Java 文件,减小手动的代码输入。如今有不少主流库都用上了 APT,好比 Dagger2, ButterKnife, EventBus3 等
更多能够参考编译时注解之APTgit

一、定义注解

例如github

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
int value();
}
复制代码

二、定义Processor派生自AbstractProcessor 而且使用@AutoService标注

AutoService会自动在META-INF文件夹下生成Processor配置信息文件,该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,
就能经过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入编程

三、提取注解信息

在Processor中提取注解信息 结合一些手段去处理,好比JavaPoet,或者 JavaPoet使用指南api

核心点

  • 处理Processor中的 注解信息的套路
  • javapoet中的代码生成 Elements

二、AspectJ

简单介绍

  • AspectJ 是使用最为普遍的 AOP 实现方案,适用于 Java 平台,官网地址:www.eclipse.org/aspectj/  其中AspectJ 是在静态织入代码,即在编译期注入代码的
  • AspectJ 提供了一套全新的语法实现,彻底兼容 Java(跟 Java 之间的区别,只是多了一些关键词而已)。同时,还提供了纯 Java 语言的实现,经过注解的方式,完成代码编织的功能。所以咱们在使用 AspectJ 的时候有如下两种方式
    • 使用 AspectJ 的语言进行开发
    • 经过 AspectJ 提供的注解在 Java 语言上开发
  • 由于最终的目的其实都是须要在字节码文件中织入咱们本身定义的切面代码,无论使用哪一种方式接入 AspectJ,都须要使用 AspectJ 提供的代码编译工具 ajc 进行编译。
  • 在 Android Studio 上通常使用注解的方式使用 AspectJ,由于 Android Studio 没有 AspectJ 插件,没法识别 AspectJ 的语法(不过在 Intellij IDEA 收费版上可使用 AspectJ 插件),因此后面的语法说明和示例都是以注解的实现方式

术语

  • JoinPoints(链接点)

JoinPoints(链接点),程序中可能做为代码注入目标的特定的点。在AspectJ中能够做为JoinPoints的地方包括
安全

image.png

  • PointCuts(切入点)

PointCuts(切入点),其实就是代码注入的位置。与前面的JoinPoints不一样的地方在于,其实PointCuts是有条件限定的JoinPoints。好比说,在一个Java源文件中,会有不少的JoinPoints,可是咱们只但愿对其中带有@debug注解的地方才注入代码。因此,PointCuts是经过语法标准给JoinPoints添加了筛选条件限定oracle

  • Advice(通知)

Advice(通知),其实就是注入到class文件中的代码片。典型的 Advice 类型有 before、after 和 around,分别表示在目标方法执行以前、执行后和彻底替代目标方法执行的代码框架

  • Aspect(切面)

Aspect(切面),Pointcut 和 Advice 的组合看作切面。

  • Weaving

注入代码(advices)到目标位置(joint points)的过程

三、Javassit

简介

Javassist做用是在编译器间修改class文件,与之类似的ASM(热修复框架女娲)也有这个功能,可让咱们直接修改编译后的class二进制代码,

首先咱们得知道何时编译完成,而且咱们要赶在class文件被转化为dex文件以前去修改。在Transfrom这个api出来以前,想要在项目被打包成dex以前对class进行操做,必须自定义一个Task,而后插入到predex或者dex以前,在自定义的Task中可使用javassist或者asm对class进行操做。而Transform则更为方便,Transfrom会有他本身的执行时机,不须要咱们插入到某个Task前面。Tranfrom一经注册便会自动添加到Task执行序列中,而且正好是项目被打包成dex以前。

image.png

经常使用方式

须要配合自定义 GradlePlugin、TransForm,每每在TransForm期间使用Javassit 去完成一些须要的aop,关于自定义Gradle插件这里就不继续展开了

ClassPool、CtClass、CtMethod核心类的使用在这里展现的很详细。

一、初始化ClassPool设置 二、经过包名取到对应的CtClass 三、CtMethodi插入代码块,写文件,释放,结束整个注入代码过程。

结语

这几种AOP方式各自最大的特色就是编织代码的时机不一样,这个须要在使用的时候根据实际须要来,

image.png

上图中 javaassit和asm也能够结合apt使用的,好比建立类,不过目前建立类通常都是javapoet,它们只是工具而已 一般aop能够用来处理如下问题

  • 日志、监控
  • 登录
  • 修复第三方代码,好比第三方jar包
  • hook 某些代码为封装过的安全性更好的代码, 好比hook系统toast或者Gson等等
  • ……

参考

相关文章
相关标签/搜索