aop概念简介

在这里插入图片描述一、AOP即面向切向编程
AOP 是 Aspect Oriented Programming 的缩写,译为面向切向编程。用我们最常用的 OOP 来对比理解:纵向关系 OOP,横向角度 AOP举个小例子:设计一个日志打印模块。按 OOP 思想,我们会设计一个打印日志 LogUtils 类,然后在需要打印的地方引用即可。public class ClassA { private void initView() { LogUtils.d(TAG, “onInitView”); }}public class ClassB { private void onDataComplete(Bean bean) { LogUtils.d(TAG, bean.attribute); }}public class ClassC { private void onError() { LogUtils.e(TAG, “onError”); }}看起来没有任何问题是吧?但是这个类是横跨并嵌入众多模块里的,在各个模块里分散得很厉害,到处都能见到。从对象组织角度来讲,我们一般采用的分类方法都是使用类似生物学分类的方法,以「继承」关系为主线,我们称之为纵向,也就是 OOP。设计时只使用 OOP思想可能会带来两个问题:对象设计的时候一般都是纵向思维,如果这个时候考虑这些不同类对象的共性,不仅会增加设计的难度和复杂性,还会造成类的接口过多而难以维护(共性越多,意味着接口契约越多)。需要对现有的对象 动态增加 某种行为或责任时非常困难。而AOP就可以很好地解决以上的问题,怎么做到的?除了这种纵向分类之外,我们从横向的角度去观察这些对象,无需再去到处调用 LogUtils 了,声明哪些地方需要打印日志,这个地方就是一个切面,AOP 会在适当的时机为你把打印语句插进切面。// 只需要声明哪些方法需要打印 log,打印什么内容public class ClassA { @Log(msg = “onInitView”) private void initView() { }}public class ClassB { @Log(msg = “bean.attribute”) private void onDataComplete(Bean bean) { }}public class ClassC { @Log(msg = “onError”) private void onError() { }}如果说 OOP 是把问题划分到单个模块的话,那么 AOP 就是把涉及到众多模块的某一类问题进行统一管理。AOP的目标是把这些功能集中起来,放到一个统一的地方来控制和管理。利用 AOP 思想,这样对业务逻辑的各个部分进行了隔离,从而降低业务逻辑各部分之间的耦合,提高程序的可重用性,提高开发效率。OOP 与 AOP 的区别面向目标不同:简单来说 OOP 是面向名词领域,AOP 面向动词领域。思想结构不同:OOP 是纵向结构,AOP 是横向结构。注重方面不同:OOP 注重业务逻辑单元的划分,AOP 偏重业务处理过程中的某个步骤或阶段。OOP 与 AOP 的联系两者之间是一个相互补充和完善的关系。二、应用场景那AOP既然这么有用,除了上面提到的打印日志场景,还有没有其他用处呢?当然有!只要系统的业务模块都需要引用通用模块,就可以使用AOP。以下是一些常用的业务场景:1. 参数校验和判空系统之间在进行接口调用时,往往是有入参传递的,入参是接口业务逻辑实现的先决条件,有时入参的缺失或错误会导致业务逻辑的异常,大量的异常捕获无疑增加了接口实现的复杂度,也让代码显得雍肿冗长,因此提前对入参进行验证是有必要的,可以提前处理入参数据的异常,并封装好异常转化成结果对象返回给调用方,也让业务逻辑解耦变得独立。2. Android API23+的权限控制避免到处都是申请权限和处理权限的代码3. 无痕埋点4. 安全控制比如全局的登录状态流程控制。5. 日志记录6. 事件防抖防止View被连续点击触发多次事件7. 性能统计检测方法耗时其实已经有一些现成的工具,比如 trace view。痛点是这些工具使用起来都比较麻烦,效率低下,而且无法针对某一个块代码或者某个指定的sdk进行查看方法耗时。可以采用 AOP 思想对每个方法做一个切点,在执行之后打印方法耗时。8. 事务处理声明方法,为特定方法加上事务,指定情况下(比如抛出异常)回滚事务9. 异常处理替代防御性的 try-Catch。10. 缓存缓存某方法的返回值,下次执行该方法时,直接从缓存里获取。11. 软件破解使用 Hook 修改软件的验证类的判断逻辑。12. 热修复AOP 可以让我们在执行一个方法的前插入另一个方法,运用这个思路,我们可以把有 bug 的方法替换成我们下发的新方法。三、AOP 方法本篇为入门篇,重在理解 AOP 思想和应用,辅助你快速进行 AOP 方法选型,所以 AOP 方法这块暂不会深入原理和术语。Android AOP 常用的方法有 JNI HOOK 和 静态织入。动态织入 Hook 方式在运行期,目标类加载后,为接口动态生成代理类,将切面植入到代理类中。相对于静态AOP更加灵活。但切入的关注点需要实现接口。对系统有一点性能影响。DexposedXposedepic在 native 层修改 java method 对应的 native 指针动态字节码生成Cglib + DexmakerCglib 是一个强大的,高性能的 Code 生成类库, 原理是在运行期间目标字节码加载后,通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。由于是通过子类来代理父类,因此不能代理被 final 字段修饰的方法。但是 Cglib 有一个很致命的缺点:底层是采用著名的 ASM 字节码生成框架,使用字节码技术生成代理类,也就是通过操作字节码来生成的新的 .class 文件,而我们在 Android 中加载的是优化后的 .dex 文件,也就是说我们需要可以动态生成 .dex 文件代理类,因此 Cglib 不能在 Android 中直接使用。有大神根据 Dexmaker 框架(dex代码生成工具)来仿照 Cglib 库动态生成 .dex 文件,实现了类似于 Cglib 的 AOP 的功能。详细的用法可参考:将cglib动态代理思想带入Android开发静态织入方式在编译期织入,切面直接以字节码的形式编译到目标字节码文件中,,这要求使用特殊的 Java 编译器。在类装载期织入,这要求使用特殊的类装载器。静态织入对系统无性能影响。但灵活性不够。APTAspectJASMJavassistDexMakerASMDEX这么多方法?有什么区别?方法作用期比对一图胜千言AOP 方法作用时期比对.pngAOP 是思想,上面的方法其实都是工具,只不过是插入时机和方式不同。同:都可以织入逻辑,都体现了 AOP 思想异:作用的时机不一样,且适用的注解的类型不一样。方法优缺点、难点比对方法作用时机操作对象优点缺点为了上手,我需要掌握什么?APT编译期:还未编译为 class 时.java 文件1. 可以织入所有类;2. 编译期代理,减少运行时消耗1. 需要使用 apt 编译器编译;2. 需要手动拼接代理的代码(可以使用 Javapoet 弥补);3. 生成大量代理类设计模式和解耦思想的灵活应用AspectJ编译期、加载时.java 文件功能强大,除了 hook 之外,还可以为目标类添加变量,接口。也有抽象,继承等各种更高级的玩法。1. 不够轻量级;2. 定义的切点依赖编程语言,无法兼容Lambda语法;3. 无法织入第三方库;4. 会有一些兼容性问题,如:D8、Gradle 4.x等复杂的语法,但掌握几个简单的,就能实现绝大多数场景Javassist编译期:class 还未编译为 dex 时或运行时class 字节码1. 减少了生成子类的开销;2. 直接操作修改编译后的字节码,直接绕过了java编译器,所以可以做很多突破限制的事情,例如,跨 dex 引用,解决热修复中 CLASS_ISPREVERIFIED 问题。运行时加入切面逻辑,产生性能开销。1. 自定义 Gradle 插件;2. 掌握groovy 语言ASM编译期或运行期字节码注入class 字节码小巧轻便、性能好,效率比Javassist高学习成本高需要熟悉字节码语法,ASM 通过树这种数据结构来表示复杂的字节码结构,并利用 Push 模型来对树进行遍历,在遍历过程中对字节码进行修改。ASMDEX编译期和加载时:转化为 .dex 后Dex 字节码,创建 class 文件可以织入所有类学习成本高需要对 class 文件比较熟悉,编写过程复杂。DexMaker同ASMDEXDex 字节码,创建 dex 文件同ASMDEX同ASMDEX同ASMDEXCglib运行期生成子类拦截方法字节码没有接口也可以织入1. 不能代理被final字段修饰的方法;2. 需要和 dexmaker 结合使用–xposed运行期hook–能hook自己应用进程的方法,能hook其他应用的方法,能hook系统的方法依赖三方包的支持,兼容性差,手机需要root–dexposed运行期hook–只能hook自己应用进程的方法,但无需root1. 依赖三方包的支持,兼容性差;2. 只能支持 Dalvik 虚拟机–epic运行期hook–支持 Dalvik

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值