AOP(Aspect Oriented Program的首字母缩写)是一种面向切面编程的思想。这种编程思想是相对于OOP(ObjectOriented Programming即面向对象编程)来说的。
先来说一下大家熟悉的面向对象编程:面向对象的特点是 继承、多态和封装 。而封装就要求将功能分散到不同的对象中去,这在软件设计中往往称为职责分配。实际上也就是说,让不同的类设计不同的方法。这样代码就分散到一个个的类中去了。这样做的好处是降低了代码的复杂程度,使类可重用。但是面向对象的编程天生有个 缺点就是分散代码的同时,也增加了代码的重复性 。
比如我希望在项目里面所有的模块都增加日志统计模块,按照OOP的思想,我们需要在各个模块里面都添加统计代码,但是如果按照AOP的思想,可以将统计的地方抽象成切面,只需要在切面里面添加统计代码就OK了。
其实在服务端的领域AOP已经被玩的风生水起,例如Spring的框架。
代码demo链接 github.com/xsfelvis/an…
APT(Annotation Processing Tool 的简称),可以在 代码编译期解析注解 ,结合JavaPoet 生成新的 Java 文件,减少手动的代码输入。现在有很多主流库都用上了 APT,比如 Dagger2, ButterKnife, EventBus3 等
更多可以参考编译时注解之APT
例如
@Retention(RetentionPolicy.CLASS) @Target(ElementType.FIELD) public @interface BindView { int value(); } 复制代码
AutoService会自动在META-INF文件夹下生成Processor配置信息文件,该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,
就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入
在Processor中提取注解信息 结合一些手段去处理,比如 JavaPoet ,或者 JavaPoet使用指南
JoinPoints(连接点),程序中可能作为代码注入目标的特定的点。在AspectJ中可以作为JoinPoints的地方包括
PointCuts(切入点),其实就是代码注入的位置。与前面的JoinPoints不同的地方在于,其实PointCuts是有条件限定的JoinPoints。比如说,在一个Java源文件中,会有很多的JoinPoints,但是我们只希望对其中带有@debug注解的地方才注入代码。所以,PointCuts是通过语法标准给JoinPoints添加了筛选条件限定
Advice(通知),其实就是注入到class文件中的代码片。典型的 Advice 类型有 before、after 和 around ,分别表示在目标方法执行之前、执行后和完全替代目标方法执行的代码
Aspect(切面),Pointcut 和 Advice 的组合看做切面。
注入代码(advices)到目标位置(joint points)的过程
Javassist作用是在 编译器间修改class文件 ,与之相似的ASM(热修复框架女娲)也有这个功能,可以让我们直接修改编译后的class二进制代码,
首先我们得知道什么时候编译完成,并且我们要赶在class文件被转化为dex文件之前去修改。在Transfrom这个api出来之前,想要在项目被打包成dex之前对class进行操作,必须自定义一个Task,然后插入到predex或者dex之前,在自定义的Task中可以使用javassist或者asm对class进行操作。而Transform则更为方便,Transfrom会有他自己的执行时机,不需要我们插入到某个Task前面。Tranfrom一经注册便会自动添加到Task执行序列中,并且正好是项目被打包成dex之前。
需要配合自定义 GradlePlugin、TransForm,往往在TransForm期间使用Javassit 去完成一些需要的aop,关于自定义Gradle插件这里就不继续展开了
ClassPool、CtClass、CtMethod核心类的使用在这里展示的很详细。
1、初始化ClassPool设置 2、通过包名取到对应的CtClass 3、CtMethodi插入代码块,写文件,释放,结束整个注入代码过程。