go_aop
以源码生成为蓝本的golang的aop解决方案
实现原理
秉承了java的aop的基本思想,对项目中满足要求的函数(满足切入点表达式)按需添加前置通知、环绕通知和后置通知
实现效果
会对项目中的全部函数添加添加前置通知、环绕通知和后置通知,它们需要满足如下的样式
// variadic 原函数入参的最后1个是不是可变参数
func Before(variadic bool, params ...any) {
}
// variadic 原函数入参的最后1个是不是可变参数
func Around(function any, variadic bool, params ...any) []any {
// 根据实际的情况自由发挥 以下是样例
functionValue := reflect.ValueOf(function)
paramValues := utils.ConvertSlice(params, func(param any) reflect.Value {
return reflect.ValueOf(param)
})
var returnedValues []reflect.Value
if variadic {
returnedValues = functionValue.CallSlice(paramValues)
} else {
returnedValues = functionValue.Call(paramValues)
}
return utils.ConvertSlice(returnedValues, func(returnedValue reflect.Value) any {
return returnedValue.Interface()
})
}
func After(returnedValues... any) {
}
如果原来函数是这样的
package util
func (car *Car) operate(a int) (b int) {
b = a + 1
return
}
那么修改后的是这样的
package util
import "go_aop/processor"
func (car *Car) operate_original(a int) (b int) {
b = a + 1
return
}
func (car *Car) operate(a int) (b int) {
processor.Before(false, a)
returnedValues := processor.Around(car.operate, false, a)
b, _ = returnedValues[0].(int)
processor.After(b)
return
}
如何使用
go install gitee.com/fenquen/go_aop@latest
go_aop ${项目根目录} ${配置文件的path}
配置文件
使用配置文件来明确你需要对哪些函数使用什么样的通知
{
"before": {
"pointcutExprs": [
"*"
],
"aspectPath": "go_aop/processor.Before"
},
"around": {
"pointcutExprs": [
"*"
],
"aspectPath": "go_aop/processor.Around"
},
"after": {
"pointcutExprs": [
"*"
],
"aspectPath": "go_aop/processor.After"
}
}