通过学习java的jdk动态代理和Cglib动态代理,仿照jdk动态代理用go实现了一个简单的动态代理
代理模式中分为静态代理和动态代理。静态代理需要在编译前就要写好,而动态代理需要在运行时通过反射来实现方法增强。
package pro
import (
"errors"
"fmt"
"reflect"
)
//提供动态调用方法接口
type InvocationHandler interface {
Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error)
}
//代理,用来总管代理类的生成
type Proxy struct {
target interface{} //目标类,后面的类型和java的Object一样
methods map[string]*Method //map用来装载待增强的不同的方法
handle InvocationHandler //用来暴露统一invoke接口,类似多态
}
//创建新的代理
func NewProxy(target interface{}, h InvocationHandler) *Proxy {
typ := reflect.TypeOf(target) //用来显示目标类动态的真实类型
value := reflect.ValueOf(target) //获取目标类的值
methods := make(map[string]*Method, 0) //初始化目标类的方法map
//将目标类的方法逐个装载
for i := 0; i < value.NumMethod(); i++ {
method := value.Method(i)
methods[typ.Method(i).Name] = &Method{value: method}
}
return &Proxy{target: target, methods: methods, handle: h}
}
//代理调用代理方法
func (p *Proxy) InvokeMethod(name string, args ...interface{}) ([]interface{}, error) {
return p.handle.Invoke(p, p.methods[name], args)
}
//用来承载目标类的方法定位和调用
type Method struct {
value reflect.Value //用来装载方法实例
}
//这里相当于调用原方法,在该方法外可以做方法增强,需要调用者自己实现!!!
func (m *Method) Invoke(args ...interface{}) (res []interface{}, err error) {
defer func() {
//用来捕捉异常
if p := recover(); p != nil {
err = errors.New(fmt.Sprintf("%s", p))
}
}()
//处理参数
params := make([]reflect.Value, 0)
if args != nil {
for i := 0; i < len(args); i++ {
params = append(params, reflect.ValueOf(args[i]))
}
}
//调用方法
call := m.value.Call(params)
//接收返回值
res = make([]interface{}, 0)
if call != nil && len(call) > 0 {
for i := 0; i < len(call); i++ {
res = append(res, call[i].Interface())
}
}
return
}
package pro
import (
"fmt"
"testing"
"time"
)
func TestName(t *testing.T) {
//这里对活动时长做统计
people := &People{} //创建目标类
h := new(PeopleProxy) //创建接口实现类
proxy := NewProxy(people, h)
//调用方法
ret, err := proxy.InvokeMethod("Work", "敲代码", "学习")
if err != nil {
fmt.Println(err)
}
fmt.Println(ret)
}
//目标类
type People struct {
}
func (p *People) Work(content string, next string) string {
fmt.Println("活动内容是:" + content + ",接下来需要做:" + next)
return "all right"
}
//用户需要自己实现的增强内容,需要实现InvocationHandler接口
type PeopleProxy struct {
}
//在这里做方法增强
func (p *PeopleProxy) Invoke(proxy *Proxy, method *Method, args []interface{}) ([]interface{}, error) {
start := time.Now()
defer fmt.Printf("耗时:%v\n", time.Since(start))
fmt.Println("before method")
invoke, err := method.Invoke(args...)
fmt.Println("after method")
return invoke, err
}
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9hKFwyme-1659607080908)(C:/Users/86158/AppData/Roaming/Typora/typora-user-images/image-20220804175747463.png)]](https://1000bd.com/contentImg/2022/08/10/133219423.png)