序
本文次要钻研一下 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
doc
- generic_filter