转载

聊聊dubbo-go的GenericFilter

本文主要研究一下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
原文  https://segmentfault.com/a/1190000023279582
正文到此结束
Loading...