📚鸿蒙开发往期学习笔录✒️:
✒️ 鸿蒙(OpenHarmony)南向开发保姆级知识点汇总~
✒️ 鸿蒙应用开发与鸿蒙系统开发哪个更有前景?
✒️ 嵌入式开发适不适合做鸿蒙南向开发?看完这篇你就了解了~
✒️ 对于大前端开发来说,转鸿蒙开发究竟是福还是祸?
✒️ 鸿蒙岗位需求突增!移动端、PC端、IoT到底该怎么选?
✒️ 记录一场鸿蒙开发岗位面试经历~
✒️ 持续更新中……
概述
切面编程(AOP)是一种通过预编译方式和运行期间动态代理实现程序功能的统一维护的技术。AOP的核心思想是将程序的关注点(concern)分离,通过在程序中插入代码来实现横切关注点(cross-cutting concerns),从而实现对业务逻辑的各个部分进行隔离,降低它们之间的耦合度,提高程序的可维护性和可重用性,同时提高了开发的效率。
在AOP中,开发者可以通过定义切面(aspect)来封装横切关注点,而不需要直接修改业务逻辑代码。这种方式要求在不修改源代码的前提下添加功能,常用于将业务代码和非业务代码剥离,比如参数校验、日志记录、性能统计等非业务代码,以达到更好的代码解耦效果。
HarmonyOS主要通过插桩机制来实现切面编程,并提供了 Aspect类 ,包括addBefore、addAfter和replace接口。这些接口可以在运行时对类方法进行前置插桩、后置插桩以及替换实现,为开发者提供了更灵活的操作方式。在具体业务场景中,不同的需求可能需要不同的埋点功能和日志记录。通过调用addBefore、addAfter和replace接口,可以实现对类方法的各种功能增强和定制化需求:
- 对于方法校验类的需求,我们可以在方法执行前或执行后进行参数校验,确保参数、返回值等的合法性。
- 针对方法执行时间和次数统计的需求,我们可以在方法执行前和执行后分别插入统计逻辑,记录方法的执行时间和次数。通过addBefore和addAfter接口的组合运用,可以方便地实现对方法执行情况的监控和统计,为性能优化提供数据支持。
- 对于替换类的需求,我们可以使用AOP的replace接口,动态替换原有方法的实现逻辑。这种灵活的替换机制可以在不改变原有方法调用的情况下,实现对方法功能的替换或增强,为项目的功能扩展提供便利。
- 针对拉起应用时获取目标包名信息的需求,我们可以在应用启动时获取目标包名信息并记录日志。通过在应用启动时调用addBefore接口,可以实现对应用启动过程的监控和记录,为应用性能优化和故障排查提供帮助。
下面,本文将介绍对应接口的基本原理,并针对以上业务场景,具体说明怎么利用运行时插桩的接口完成对类方法的埋点和加日志功能。
插桩原理介绍
addBefore、addAfter、replace接口的原理基于class的ECMAScript语义,即类的静态方法是类的属性,类的实例方法是类的原型对象(prototype)的属性。
图1 class的ECMAScript语义示意
原理解析
类的实例会有一个属性__proto__(称为原型),它是指向类的prototype的引用(如下图2所示)。实例在调用方法时,实际上会先通过__proto__找到类的prototype,再在prototype中找到这个方法,再执行调用逻辑。类的原型对象(prototype)被这个类的所有实例共享,这意味着修改类的原型对象里面存储的方法,会对这个类的所有实例产生效果。
**图2 **类的实例化示意
原型对象也有原型__proto__。类的继承就是通过原型来实现的。实例方法的调用实际上在运行时就是通过在原型串联的链上查找方法,找到方法再执行调用(如下图3所示)。
图3 类的原型与继承
插桩和替换的操作本质上就是将回调参数和原方法组合成一个新的函数,再用新的函数替换原方法(如下图4所示)。
图4 插桩和替换原理示意图
接口原理的伪代码示意
addBefore: 类方法前插桩
// 在类方法执行前插桩
static addBefore(targetClass, methodName, isStatic, before): void {
let target = isStatic ? targetClass : targetClass.prototype;
let origin = target[me