本文代码案例基于Api13。
AOP,也就是Aspect Oriented Programming,它是一种编程范式,旨在通过分离横切关注点来提高代码的模块化,将一些常见的关注点,比如日志记录、事务管理、安全控制等从核心业务逻辑中分离出来,使代码更易维护和扩展。
提到AOP,大家最常见的就是日志的记录,AOP可以在不修改原有业务代码的情况下,通过代码插桩的方式,为应用程序添加日志记录功能;当然了,除了日志记录功能,相信大家肯定见过很多的三方的统计,比如友盟,神策等等,他们是怎么来统计的页面的访问量?没错,就是用到了AOP。
AOP,说的简单直白一点,就是,它可以实现对原有的对象方法,在执行前后,进行插桩,同样,在鸿蒙的开发中,我们也可以直接对其方法进行替换操作,如何实现,在Api 11之后使用Aspect对象即可。
addBefore方法,可以在在指定的类对象的原方法执行前插入一个函数,执行顺序就会先执行插入的函数,后执行原有函数。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
targetClass | Object | 是 | 指定的类对象。 |
methodName | string | 是 | 指定的方法名,不支持read-only方法。 |
isStatic | boolean | 是 | 指定的原方法是否为静态方法,true表示静态方法,false表示实例方法。 |
before | Function | 是 | 要插入的函数对象。函数有参数,则第一个参数是this对象(若isStatic为true,则为类对象即targetClass;若isStatic为false,则为调用方法的实例对象),其余参数是原方法的参数。函数也可以无参数,无参时不做处理。 |
很简单一个案例,有一个对象Test,里面有一个方法,返回一个字符串。
import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button("点击")
.onClick(() => {
let test = new Test()
console.log("===原始方法获取:" + test.getName())
util.Aspect.addBefore(Test, "getName", false, (test: Test) => {
test.name = "程序员一鸣"
})
console.log("===追加逻辑后获取:" + test.getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
以上的代码,当执行util.Aspect.addBefore方法后,就会把name进行修改,再次调用test.getName(),就会发生变化,可以看下输出的日志:
当然,你可以在这里,执行任何你需要的逻辑,比如埋点,比如打印日志,比如网络请求等等,都是可以的。
util.Aspect.addBefore(Test, "getName", false, (instance: Test) => {
instance.name = "程序员一鸣"
console.log("===打印日志:输出一条日志")
})
addAfter方法,在指定的类方法执行后插入一段逻辑,最终返回值是插入函数执行后的返回值。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
targetClass | Object | 是 | 指定的类对象。 |
methodName | string | 是 | 指定的原方法名,不支持read-only方法。 |
isStatic | boolean | 是 | 指定的原方法是否为静态方法,true表示静态方法,false表示实例方法。 |
after | Function | 是 | 要插入的函数。函数有参数时,则第一个参数是this对象(若isStatic为true,则为类对象即targetClass;若isStatic为false,则为调用方法的实例对象),第二个参数是原方法的返回值(如果原方法没有返回值,则为undefined),其余参数是原方法的参数。函数也可以无参,无参时不做处理。 |
import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button("点击")
.onClick(() => {
let test = new Test()
console.log("===原始方法获取:" + test.getName())
util.Aspect.addAfter(Test, "getName", false, (instance: Test) => {
instance.name = "程序员一鸣"
console.log("===打印日志:输出一条日志")
return "程序员大鸣"
})
console.log("===追加逻辑后获取:" + test.getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
还是上述的案例,我们把util.Aspect.addBefore换成util.Aspect.addAfter,其它逻辑不变,需要注意的是,最终返回值是插入函数执行后的返回值,也就是意味着,最后的打印是addAfter中的函数返回值,我们看下日志:
replace方法,会将指定的类中方法的原方法替换为另一个函数,replace接口执行完成后,只会执行替换后的逻辑,原有的函数逻辑不在执行。
参数名 | 类型 | 必填 | 说明 |
---|---|---|---|
targetClass | Object | 是 | 指定的类对象。 |
methodName | string | 是 | 指定的原方法名,不支持read-only方法。 |
isStatic | boolean | 是 | 指定的原方法是否为静态方法,true表示静态方法,false表示实例方法。 |
instead | Function | 是 | 要用来替换原方法的函数。函数有参数时,则第一个参数是this对象(若isStatic为true,则为类对象即targetClass;若isStatic为false,则为调用方法的实例对象),其余参数是原方法的参数。函数也可以无参,无参时不做处理。 |
import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
console.log("===方法中打印")
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button("点击")
.onClick(() => {
let test = new Test()
util.Aspect.replace(Test, "getName", false, (instance: Test) => {
instance.name = "程序员一鸣"
console.log("===打印日志:输出一条日志")
return "程序员大鸣"
})
console.log("===追加逻辑后获取:" + test.getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}
我们在getName方法中打印了一条日志,当我们执行replace方法之后,可以发现并没有执行打印,因为函数已经被替换,原始的函数逻辑就不在执行。
正确的运用AOP,可以提升代码的模块化、复用性、可维护性和灵活性,同时降低了耦合度,使系统更易于扩展和维护。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。