仿照java的jdk动态代理实现go语言动态代理
通过学习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{}
methods map[string]*Method
handle InvocationHandler
}
func NewProxy(target interface{}, h InvocationHandler) *Proxy {
typ := reflect.TypeOf(target)
value := reflect.ValueOf(target)
methods := make(map[string]*Method, 0)
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"
}
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
}
输出
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)