序
本文主要研究一下dubbo-go的GenericFilter
GenericFilter
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
const (
// GENERIC
//generic module name
GENERIC = "generic"
)
func init() {
extension.SetFilter(GENERIC, GetGenericFilter)
}
// when do a generic invoke, struct need to be map
// GenericFilter ...
type GenericFilter struct{}
- GenericFilter的init方法设置了GetGenericFilter
GetGenericFilter
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
// GetGenericFilter ...
func GetGenericFilter() filter.Filter {
return &GenericFilter{}
}
- GetGenericFilter方法创建了GenericFilter
Invoke
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
// Invoke ...
func (ef *GenericFilter) Invoke(ctx context.Context, invoker protocol.Invoker, invocation protocol.Invocation) protocol.Result {
if invocation.MethodName() == constant.GENERIC && len(invocation.Arguments()) == 3 {
oldArguments := invocation.Arguments()
if oldParams, ok := oldArguments[2].([]interface{}); ok {
newParams := make([]hessian.Object, 0, len(oldParams))
for i := range oldParams {
newParams = append(newParams, hessian.Object(struct2MapAll(oldParams[i])))
}
newArguments := []interface{}{
oldArguments[0],
oldArguments[1],
newParams,
}
newInvocation := invocation2.NewRPCInvocation(invocation.MethodName(), newArguments, invocation.Attachments())
newInvocation.SetReply(invocation.Reply())
return invoker.Invoke(ctx, newInvocation)
}
}
return invoker.Invoke(ctx, invocation)
}
- Invoke方法在methodName为generic,且参数长度为3时,通过struct2MapAll方法将oldParams转换为newParams,发起newInvocation
struct2MapAll
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
func struct2MapAll(obj interface{}) interface{} {
if obj == nil {
return obj
}
t := reflect.TypeOf(obj)
v := reflect.ValueOf(obj)
if t.Kind() == reflect.Struct {
result := make(map[string]interface{}, t.NumField())
for i := 0; i < t.NumField(); i++ {
if v.Field(i).Kind() == reflect.Struct || v.Field(i).Kind() == reflect.Slice || v.Field(i).Kind() == reflect.Map {
if v.Field(i).CanInterface() {
setInMap(result, t.Field(i), struct2MapAll(v.Field(i).Interface()))
}
} else {
if v.Field(i).CanInterface() {
setInMap(result, t.Field(i), v.Field(i).Interface())
}
}
}
return result
} else if t.Kind() == reflect.Slice {
value := reflect.ValueOf(obj)
var newTemps = make([]interface{}, 0, value.Len())
for i := 0; i < value.Len(); i++ {
newTemp := struct2MapAll(value.Index(i).Interface())
newTemps = append(newTemps, newTemp)
}
return newTemps
} else if t.Kind() == reflect.Map {
var newTempMap = make(map[string]interface{}, v.Len())
iter := v.MapRange()
for iter.Next() {
mapK := iter.Key().String()
if !iter.Value().CanInterface() {
continue
}
mapV := iter.Value().Interface()
newTempMap[mapK] = struct2MapAll(mapV)
}
return newTempMap
} else {
return obj
}
}
- struct2MapAll方法针对reflect.Struct、reflect.Slice、reflect.Map做了不同的转换
OnResponse
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
// OnResponse ...
func (ef *GenericFilter) OnResponse(_ context.Context, result protocol.Result, _ protocol.Invoker,
_ protocol.Invocation) protocol.Result {
return result
}
- OnResponse方法直接返回result
小结
GenericFilter的Invoke方法在methodName为generic,且参数长度为3时,通过struct2MapAll方法将oldParams转换为newParams,发起newInvocation