// 使用代理调用
result := proxy.Invoke("Process", "测试数据")go
func (p *Proxy) Invoke(methodName string, args ...interface{}) []interface{} {
// 前置处理
for _, handler := range p.handlers {
handler(methodName, args)
}// 反射调用目标方法 targetValue := reflect.ValueOf(p.target) method := targetValue.MethodByName(methodName) inArgs := make([]reflect.Value, len(args)) for i, arg := range args { inArgs[i] = reflect.ValueOf(arg) } out := method.Call(inArgs) // 后置处理 result := make([]interface{}, len(out)) for i, v := range out { result[i] = v.Interface() } return result}
关键点解析 :
- MethodByName动态查找方法
- Call()执行反射方法调用
- 参数和返回值需要做reflect.Value与普通值的转换go
proxy := NewProxy(&Service{})
proxy.handlers = append(proxy.handlers, func(method string, args []interface{}) {
fmt.Printf("[AOP] 方法%s被调用 ,
上述方案需要手动调用Invoke,优化方案 :
1. 缓存反射对象:将MethodByName的结果缓存起来
2. 减少类型转换:尽量保持reflect.Value形态传递
3. 选择性代理:仅对需要AOP的方法进行代理go
// 方法缓存示例
type Proxy struct {
methodCache map[string]reflect.Value
}func (p *Proxy) initCache() {
p.methodCache = make(map[string]reflect.Value)
t := reflect.TypeOf(p.target)
for i := 0; i < t.NumMethod(); i++ {
method := t.Method(i)
p.methodCache[method.Name] = method.Func
}
}在Java等语言中,实际应用场景日志记录:自动记录方法入参 、个人免签码支付》
↓点击下方了解更多↓🔥《微信域名检测接口