面向切面编程(Aspect-Oriented Programming,简称AOP)是一种编程范式,旨在提高模块化程度,通过分离关注点来简化软件开发。HarmonyOS NEXT 提供了运行时AOP的能力,允许开发者在类方法执行前、执行后插入额外的逻辑,甚至替换方法的实现。这为性能监控、日志记录、权限检查等跨切面功能的实现提供了极大的便利。

接口介绍

HarmonyOS NEXT 中的 Aspect 类封装了提供切面能力的接口,支持对类方法进行前后插桩或替换实现。以下是 Aspect 类提供的主要接口:

1. addBefore – 执行前插桩

static addBefore(targetClass: Object, methodName: string, isStatic: boolean, before: Function): void;

接口说明:在类方法执行前插入一段逻辑。

接口参数

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

接口作用:对类的方法调用接口后,所有这个类的实例在调用这个方法时,会先执行 before,然后执行原方法,并将执行结果返回。执行 before 时会将 this 和原方法的参数依次传递给 before;对于实例方法,this 是调用方法的实例;对于静态方法的场景,thistargetClass

2. addAfter – 执行后插桩

static addAfter(targetClass: Object, methodName: string, isStatic: boolean, after: Function): void;

接口说明:在类方法执行后插入一段逻辑。

接口参数

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

接口作用:对类的方法调用接口后,所有这个类的实例在调用这个方法时,会先执行原方法,然后执行 after,并将 after 的执行结果返回。执行 after 时会将 this、原方法的返回值(如果原方法没有返回值,则此处是 undefined)、以及原方法的参数,依次传递给 after;对于实例方法,this 是调用方法的实例;对于静态方法的场景,thistargetClass

3. replace – 替换方法实现

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

接口说明:将类方法替换成另外一段逻辑。

接口参数

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

接口作用:对类的方法调用接口后,所有这个类的实例在调用这个方法时,会只执行 instead,并将 instead 的执行结果返回。执行 instead 时会将 this 和原方法的参数,依次传递给 instead;对于实例方法,this 是调用方法的实例;对于静态方法的场景,thistargetClass

示例代码

1. addBefore – 执行前插桩

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");

运行结果

HarmonyOS开发之运行时AOP能力_AOP

HarmonyOS开发之运行时AOP能力_面向切面编程_02

2. addAfter – 执行后插桩

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());

运行结果

HarmonyOS开发之运行时AOP能力_AOP_03

HarmonyOS开发之运行时AOP能力_面向切面编程_04

3. replace – 替换方法实现

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());

运行结果

HarmonyOS开发之运行时AOP能力_面向切面编程_05

HarmonyOS开发之运行时AOP能力_AOP_06

总结

通过 Aspect 类提供的 addBeforeaddAfterreplace 方法,开发者可以在不修改原有代码的情况下,动态地增强或修改类方法的行为。这对于实现日志记录、性能监控、权限检查等功能非常有用。希望本文能帮助你在 HarmonyOS 开发中更好地利用 AOP 技术。