本文主要研究一下dubbo-go的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{}
dubbo-go-v1.4.2/filter/filter_impl/generic_filter.go
// GetGenericFilter ... func GetGenericFilter() filter.Filter { return &GenericFilter{} }
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) }
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 } }
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 }
GenericFilter的Invoke方法在methodName为generic,且参数长度为3时,通过struct2MapAll方法将oldParams转换为newParams,发起newInvocation