stdx.aspectCJ
功能介绍
stdx.aspectCJ
包提供了 Cangjie 中面向切面编程(Aspect Oriented Programming, AOP)的相关注解,配合 libcollect-aspects 和 libwave-aspects 两个编译插件使用,可以对函数进行前后插桩以及替换实现。
API 列表
类
类名 | 功能 |
---|---|
InsertAtEntry | 一个注解类,提供一种切面能力。在注解所指定方法的入口,织入对被注解标注的函数的调用。 |
InsertAtExit | 一个注解类,提供一种切面能力。在注解所指定方法的退出点,织入对被注解标注的函数的调用。 |
ReplaceFuncBody | 一个注解类,提供一种切面能力。将注解所指定方法的方法体,替换为对被注解标注的函数的调用。 |
规格和使用
规格
标注范围:
- 注解暂不支持标注在泛型函数上,也不支持织入泛型函数;
- 注解只允许标注在 public 函数上;
- 注解可以标注在全局函数上,支持:
- 织入另一个全局函数,
- 织入另一个实例成员函数,
- 织入另一个静态成员函数;
- 注解可以标注在静态成员函数上,支持:
- 织入另一个全局函数,
- 织入另一个实例成员函数,
- 织入另一个静态成员函数;
- 注解可以标注在实例成员函数上,支持:
- 织入同类型的其它实例成员函数。
全局变量定义约束:
- 定义了切面的包中,只允许定义基本类型(整型、浮点、Rune、Bool)字面值的全局变量,否则编译报错;若需要使用超规格的全局变量,需要将其定义在另外的包再导入使用,以避免在编译后可能产生的循环依赖;
形参约束:
- 被标注 @InsertAtEntry/@InsertAtExit 的函数,其返回类型只能是 Unit;
- 被标注 @ReplaceFuncBody 的函数,其返回类型应和被织入的函数的返回类型相同;
- 被标注 @InsertAtEntry/@InsertAtExit/@ReplaceFuncBody 的函数如果没有形参,那么其织入后总是被无参调用 ;
- 被标注 @InsertAtEntry/@InsertAtExit/@ReplaceFuncBody 的函数如果有形参,其形参列表应和被织入函数的源码形参列表相同,此外:
- 特别地,如果被织入的函数是实例成员函数,那么需要将 this 参数显式地写在形参中;
- 对于被标注 @ReplaceFuncBody 的函数,需要额外添加一个形参,形参的类型和被织入的函数相同,该形参表示被织入函数原始版本的闭包。
使用
要实现 AOP 的完整功能,除了使用上述的注解类来定义切面,还需要两个编译插件:
- libcollect-aspects.so(.dll/.dylib)
- libwave-aspects.so(.dll/.dylib)
这两个编译插件以动态库的形式在 stdx.aspectCJ 中提供,不同平台提供不同版本。
应先使用 libcollect-aspects,在编译时收集所有切面、连接点信息;再使用 libwave-aspects 进行二次编译,把之前收集的切面织入到连接点。