前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >HarmonyOS 开发实践——如何在鸿蒙中实现AOP(代码插桩)能力?

HarmonyOS 开发实践——如何在鸿蒙中实现AOP(代码插桩)能力?

原创
作者头像
小帅聊鸿蒙
发布2024-11-03 21:02:47
发布2024-11-03 21:02:47
1510
举报
文章被收录于专栏:鸿蒙开发笔记鸿蒙开发笔记

鸿蒙 提供运行时AOP的能力,系统提供接口(见后文介绍),可以分别可以对类方法做执行前插桩、执行后插桩、替换方法实现。使用场景/方法举例:在应用启动的地方调用上述接口对类方法进行埋点或者替换实现。对标IOS的AOP能力(method_swizzling)。

接口介绍:Aspect类用于封装提供切面能力(Aspect Oriented Programming,简写AOP)的接口,这些接口可以用来对类方法进行前后插桩或者替换实现。

系统提供如下接口,支持运行时AOP的能力:

代码语言:ts
复制
class Aspect { 
    static addBefore(targetClass: Object, methodName: string, isStatic: boolean, before: Function): void; 
    static addAfter(targetClass: Object, methodName: string, isStatic: boolean, after: Function): void; 
    static replace(targetClass: Object, methodName: string, isStatic: boolean, instead: Function): void; 
}

这三个接口可以分别可以对方法做执行前插桩、执行后插桩、替换方法实现。

接口使用实例:

1、addBefore–执行前插桩

static addBefore(targetClass: Object, methodName: string, isStatic: boolean, before: Function): void接口说明:在类方法执行前插入一段逻辑。

接口参数:targetClass: 要操作的类对象methodName: 要操作的方法名isStatic: 要操作的方法是否为静态方法before: 要在原方法执行前插入的函数对象

接口作用:对类的方法调用接口后,所有这个类的实例在调用这个方法时,会先执行before,然后执行原方法,并将执行结果返回。

执行before时会将this和原方法的参数依次传递给before;

对于实例方法,this是调用方法的实例;对于静态方法的场景,this是targetClass。

参考代码:

代码语言:ts
复制
class Test { 
    data: string = "initData"; 
    printData(arg: string): number { 
        console.log("execute original printData"); 
        console.log("data is " + this.data); 
        console.log(arg); 
        return 0; 
    } 
} 
let m1 = new Test(); 
m1.printData("m1"); 
 
util.Aspect.addBefore(Test, "printData", false, 
    (instance: Test, arg: string): void => { 
        console.log("execute before"); 
        instance.data = "dataChangedByBefore"; 
        console.log("arg is " + arg); 
    }); 
m1.printData("m1");

运行结果:

2、addAfter–执行后插桩

static addAfter(targetClass: Object, methodName: string, isStatic: boolean, after: Function): void接口说明:在类方法执行后插入一段逻辑。

接口参数:

targetClass: 要操作的类对象methodName: 要操作的方法名isStatic: 要操作的方法是否为静态方法after: 要在原方法执行后插入的函数对象

接口作用:

对类的方法调用接口后,所有这个类的实例在调用这个方法时,会先执行原方法,然后执行after,并将after的执行结果返回。

执行after时会将this、原方法的返回值(如果原方法没有返回值,则此处是undefined)、以及原方法的参数,依次传递给after;

对于实例方法,this是调用方法的实例;对于静态方法的场景,this是targetClass。

参考代码:

代码语言:ts
复制
class Test { 
    data: string = “initData”; 
    printData(arg: string): number { 
        console.log(“execute original printData”); 
        console.log("data is " + this.data); 
        console.log(arg); 
        return 0; 
    } 
} 
let m1 = new Test(); 
let ret1 = m1.printData(“m1”); 
console.log(m1.data); 
console.log(ret1.toString()); 
 
util.Aspect.addAfter(Test, “printData”, false, 
(instance: Test, ret: number, arg: string): number => { 
    console.log(“execute after”); 
    instance.data = “dataChangedByAfter”; 
    console.log("arg is " + arg); 
    return ret + 100; 
}); 
let ret1_2 = m1.printData(“m1”); 
console.log(m1.data); 
console.log(ret1_2.toString());

运行结果:

3、replace–替换方法实现

static replace(targetClass: Object, methodName: string, isStatic: boolean, instead: Function) : void

接口说明:

将类方法替换成另外一段逻辑。

接口参数:

  • targetClass: 要操作的类对象
  • methodName: 要操作的方法名
  • isStatic: 要操作的方法是否为静态方法
  • instead: 要用来替换原方法实现的函数对象

接口作用:

对类的方法调用接口后,所有这个类的实例在调用这个方法时,会只执行instead,并将instead的执行结果返回。

执行instead时会将this和原方法的参数,依次传递给instead;

对于实例方法,this是调用方法的实例;对于静态方法的场景,this是targetClass。

参考代码:

代码语言:ts
复制
class Test { 
  data: string = “initData”; 
  printData(arg: string): number { 
    console.log(“execute original printData”); 
    console.log("data is " + this.data); 
    console.log(arg); 
    return 0; 
  } 
} 
let m1 = new Test(); 
let ret1 = m1.printData(“m1”); 
console.log(m1.data); 
console.log(ret1.toString()); 
 
util.Aspect.replace(Test, “printData”, false, 
(instance: Test, arg: string): number => { 
  console.log(“execute instead”); 
  instance.data = “dataChangedByInstead”; 
  console.log("arg is " + arg); 
  return 100; 
} 
); 
let ret1_2 = m1.printData(“m1”); 
console.log(m1.data); 
console.log(ret1_2.toString());

运行结果:

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙:

  • 点赞,转发,有你们的 『点赞和评论』,才是我创造的动力;
  • 关注小编,同时可以期待后续文章ing🚀,不定期分享原创知识;
  • 想要获取更多完整鸿蒙最新学习知识点,可关注B站:码牛课堂鸿蒙开发;

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 接口使用实例:
    • 1、addBefore–执行前插桩
  • 2、addAfter–执行后插桩
    • 3、replace–替换方法实现
  • 写在最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档