聊聊dubbo-go的GenericFilter

最后都变了- 提交于 2020-08-17 09:55:48

本文主要研究一下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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!