HarmonyOS Development: Realize AOP Code Interpolation Ability

AbnerMingAbnerMing
6 min read

Foreword

this article code case based on api13.

AOP, that is. Aspect Oriented Programming, which it is a programming paradigm designed to improve the modularity of code by separating cross-cutting concerns, separating common concerns such as logging, transaction management, and security controls from core business logic, making code easier to maintain and extend.

When it comes to AOP, the most common thing is log recording. AOP can add logging function to applications by inserting piles of codes without modifying the original business code. Of course, in addition to the logging function, I believe you have certainly seen many statistics of three parties, such as AU, Shence, etc. How do they count the number of page visits? Yes, I used AOP.

AOP, to put it simply and bluntly, is that it can implement the original object method before and after execution. Pile insertion similarly, in the development of Hongmeng, we can also directly replace its methods, how to implement it, and use it after Api 11 Aspect object.

Insert function before method

the addBefore method can insert a function before the execution of the original method of the specified class object. The execution sequence will execute the inserted function first and then the original function.

Parameter Description

parameter Name

type

required

description

targetClass

Object

yes

the specified class object.

methodName

string

yes

the specified method name. The read-only method is not supported.

isStatic

boolean

yes

specifies whether the original method is a static method. true indicates a static method and false indicates an instance method.

before

Function

yes

the function object to insert. If the function has parameters, the first parameter is this object (if isStatic is true, the class object is targetClass; If isStatic is false, it is the instance object of the calling method), and the remaining parameters are the parameters of the original method. Functions can also have no parameters and do not process when there are no parameters.

Simple example

A very simple case, there is an object Test, there is a method, return a string.

import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button (click)
.onClick(() => {
let test = new Test()
Console. log ("===raw method fetch:"+test. getName())
util.Aspect.addBefore(Test, "getName", false, (test: Test) => {
Test.name="Programmer's Cry"
})
Console. log ("===append logic to get:"+test. getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}

The above code, after executing the util.Aspect.addBefore method, will modify the name and call test.getName() again, which will change. You can see the output log:

Of course, you can execute any logic you need here, such as embedding points, printing logs, network requests, etc.

util.Aspect.addBefore(Test, "getName", false, (instance: Test) => {
Instance.name="Programmer's Voice"
Console.log ("===Print log: output one log")
})

Insert function after Method

the addAfter method inserts a piece of logic after the execution of the specified class method, and the final return value is the return value after the execution of the inserted function.

Parameter Description

parameter Name

type

required

description

targetClass

Object

yes

the specified class object.

methodName

string

yes

the original method name. The read-only method is not supported.

isStatic

boolean

yes

specifies whether the original method is a static method. true indicates a static method and false indicates an instance method.

after

Function

yes

The function to insert. When the function has parameters, the first parameter is this object (if isStatic is true, the class object is targetClass; If isStatic is false, it is the instance object of the calling method), the second parameter is the return value of the original method (if the original method has no return value, it is undefined), and the remaining parameters are the parameters of the original method. Functions can also have no parameters and do not process when there are no parameters.

Simple example

import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
Console.log ("==printed in method")
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button (click)
.onClick(() => {
let test = new Test()
util.Aspect.replace(Test, "getName", false, (instance: Test) => {
Instance.name="Programmer's Voice"
Console.log ("===Print log: output one log")
Return "Programmer's Big Cry"
})
Console. log ("===append logic to get:"+test. getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}

again in the above case, we put util.Aspect.addBefore is replaced by util.Aspect.addAfter. Other logic remains unchanged. It should be noted that the final return value is the return value after the execution of the inserted function, which means that the final print is the return value of the function in addAfter. Let's look at the log:

replace function

the replace method replaces the original method of the method in the specified class with another function. After the replace interface is executed, only the replaced logic is executed, and the original function logic is not executed.

Parameter Description

parameter Name

type

required

description

targetClass

Object

yes

the specified class object.

methodName

string

yes

The original method name. The read-only method is not supported.

isStatic

boolean

yes

specifies whether the original method is a static method. true indicates a static method and false indicates an instance method.

instead

Function

yes

the function with which to replace the original method. When the function has parameters, the first parameter is this object (if isStatic is true, the class object is targetClass; If isStatic is false, it is the instance object of the calling method), and the remaining parameters are the parameters of the original method. Functions can also have no parameters and do not process when there are no parameters.

Simple Case

import util from '@ohos.util'
class Test {
name: string = "AbnerMing"
getName(): string {
Console.log ("==printed in method")
return this.name
}
}
@Entry
@Component
struct Index {
build() {
Column() {
Button (click)
.onClick(() => {
let test = new Test()
util.Aspect.replace(Test, "getName", false, (instance: Test) => {
Instance.name="Programmer's Voice"
Console.log ("===Print log: output one log")
Return "Programmer's Big Cry"
})
Console. log ("===append logic to get:"+test. getName())
})
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
}
}

we printed a log in the getName method. When we execute the replace method, we can find that the printing was not executed because the function has been replaced and the original function logic is not executed.

the correct use of AOP, can improve the modularity, reusability, maintainability and flexibility of the code, while reducing the coupling, making the system easier to extend and maintain.

0
Subscribe to my newsletter

Read articles from AbnerMing directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

AbnerMing
AbnerMing