forked from zhuxiujia/GoMybatis
-
Notifications
You must be signed in to change notification settings - Fork 0
/
GoMybatisProxy.go
115 lines (109 loc) · 2.89 KB
/
GoMybatisProxy.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package GoMybatis
import (
"reflect"
"strings"
)
type TagArg struct {
Name string
Index int
}
// AopProxy 可写入每个函数代理方法.proxyPtr:代理对象指针,buildFunc:构建代理函数
func Proxy(proxyPtr interface{}, buildFunc func(funcField reflect.StructField, field reflect.Value) func(arg ProxyArg) []reflect.Value) {
v := reflect.ValueOf(proxyPtr)
if v.Kind() != reflect.Ptr {
panic("AopProxy: AopProxy arg must be a pointer")
}
buildProxy(v, buildFunc)
}
// AopProxy 可写入每个函数代理方法
func ProxyValue(mapperValue reflect.Value, buildFunc func(funcField reflect.StructField, field reflect.Value) func(arg ProxyArg) []reflect.Value) {
buildProxy(mapperValue, buildFunc)
}
func buildProxy(v reflect.Value, buildFunc func(funcField reflect.StructField, field reflect.Value) func(arg ProxyArg) []reflect.Value) {
for {
if v.Kind() == reflect.Ptr {
v = v.Elem()
} else {
break
}
}
t := v.Type()
et := t
if et.Kind() == reflect.Ptr {
et = et.Elem()
}
ptr := v
var obj reflect.Value
if ptr.Kind() == reflect.Ptr {
obj = ptr.Elem()
} else {
obj = ptr
}
count := obj.NumField()
for i := 0; i < count; i++ {
f := obj.Field(i)
ft := f.Type()
sf := et.Field(i)
if ft.Kind() == reflect.Ptr {
ft = ft.Elem()
}
if f.CanSet() {
switch ft.Kind() {
case reflect.Struct:
if buildFunc != nil {
buildProxy(f, buildFunc) //循环扫描
}
case reflect.Func:
if buildFunc != nil {
buildRemoteMethod(v, f, ft, sf, buildFunc(sf, f))
}
}
}
}
if t.Kind() == reflect.Ptr {
v.Set(ptr)
} else {
v.Set(obj)
}
}
func buildRemoteMethod(source reflect.Value, f reflect.Value, ft reflect.Type, sf reflect.StructField, proxyFunc func(arg ProxyArg) []reflect.Value) {
var tagParams []string
var args = sf.Tag.Get(`args`)
if args != `` {
tagParams = strings.Split(args, `,`)
}
var tagParamsLen = len(tagParams)
if tagParamsLen > ft.NumIn() {
panic(`[GoMybatisProxy] method fail! the tag "args" length can not > arg length ! filed=` + sf.Name)
}
var tagArgs = make([]TagArg, 0)
if tagParamsLen != 0 {
for index, v := range tagParams {
var tagArg = TagArg{
Index: index,
Name: v,
}
tagArgs = append(tagArgs, tagArg)
}
}
var tagArgsLen = len(tagArgs)
if tagArgsLen > 0 && ft.NumIn() != tagArgsLen {
panic(`[GoMybatisProxy] method fail! the tag "args" length != args length ! filed = ` + sf.Name)
}
var fn = func(args []reflect.Value) (results []reflect.Value) {
proxyResults := proxyFunc(ProxyArg{}.New(tagArgs, args))
for _, returnV := range proxyResults {
results = append(results, returnV)
}
return results
}
if f.Kind() == reflect.Ptr {
fp := reflect.New(ft)
fp.Elem().Set(reflect.MakeFunc(ft, fn))
f.Set(fp)
} else {
f.Set(reflect.MakeFunc(ft, fn))
}
//println("[GoMybatis] write method success:" + source.Type().Name() + " > " + sf.Name + " " + f.Type().String())
tagParams = nil
}