-
Notifications
You must be signed in to change notification settings - Fork 0
/
GoMybatisProxy.go
134 lines (128 loc) · 3.24 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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package GoMybatisV2
import (
"context"
"reflect"
"strings"
)
type build func(funcField reflect.StructField, field reflect.Value) buildResult
type buildResult func(ctx context.Context, arg ProxyArg) []reflect.Value
// AopProxy 可写入每个函数代理方法.proxyPtr:代理对象指针,buildFunc:构建代理函数
func Proxy(proxyPtr interface{}, buildFunc build) {
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 build) {
buildProxy(mapperValue, buildFunc)
}
func buildProxy(v reflect.Value, buildFunc build) {
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)
sf := et.Field(i)
ft := f.Type()
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 buildResult) {
var tagParams []string
var mapperParams = sf.Tag.Get(`mapperParams`)
if mapperParams != `` {
tagParams = strings.Split(mapperParams, `,`)
}
var tagParamsLen = len(tagParams)
var inputCount int
for i := 0; i < ft.NumIn(); i++ {
if ft.In(i).String() == GoMybatis_Context {
continue
}
inputCount++
}
if tagParamsLen > inputCount {
panic(`[GoMybatisProxy] method fail! the tag "mapperParams" 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 && inputCount != tagArgsLen {
panic(`[GoMybatisProxy] method fail! the tag "mapperParams" length != args length ! filed = ` + sf.Name)
}
var fn = func(args []reflect.Value) (results []reflect.Value) {
ctx := context.TODO()
// 找出context 进行注入和args扔掉 context
var newArgs []reflect.Value
for _, arg := range args {
if arg.Kind() == reflect.Interface {
//arg = arg.Elem()
if v, o := arg.Interface().(context.Context); o {
ctx = v
}
continue
}
newArgs = append(newArgs, arg)
}
proxyResults := proxyFunc(ctx, ProxyArg{}.New(tagArgs, newArgs))
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
}