dubbo.apache.org/dubbo-go/v3@v3.1.1/proxy/proxy_factory/default.go (about) 1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package proxy_factory 19 20 import ( 21 "context" 22 "reflect" 23 "strings" 24 ) 25 26 import ( 27 "github.com/dubbogo/gost/log/logger" 28 29 perrors "github.com/pkg/errors" 30 ) 31 32 import ( 33 "dubbo.apache.org/dubbo-go/v3/common" 34 "dubbo.apache.org/dubbo-go/v3/common/constant" 35 "dubbo.apache.org/dubbo-go/v3/common/extension" 36 "dubbo.apache.org/dubbo-go/v3/protocol" 37 "dubbo.apache.org/dubbo-go/v3/proxy" 38 ) 39 40 func init() { 41 extension.SetProxyFactory("default", NewDefaultProxyFactory) 42 } 43 44 // DefaultProxyFactory is the default proxy factory 45 type DefaultProxyFactory struct { // delegate ProxyFactory 46 } 47 48 // you can rewrite DefaultProxyFactory in extension and delegate the default proxy factory like below 49 50 //func WithDelegate(delegateProxyFactory ProxyFactory) Option { 51 // return func(proxy ProxyFactory) { 52 // proxy.(*DefaultProxyFactory).delegate = delegateProxyFactory 53 // } 54 //} 55 56 // NewDefaultProxyFactory returns a proxy factory instance 57 func NewDefaultProxyFactory(_ ...proxy.Option) proxy.ProxyFactory { 58 return &DefaultProxyFactory{} 59 } 60 61 // GetProxy gets a proxy 62 func (factory *DefaultProxyFactory) GetProxy(invoker protocol.Invoker, url *common.URL) *proxy.Proxy { 63 return factory.GetAsyncProxy(invoker, nil, url) 64 } 65 66 // GetAsyncProxy gets a async proxy 67 func (factory *DefaultProxyFactory) GetAsyncProxy(invoker protocol.Invoker, callBack interface{}, url *common.URL) *proxy.Proxy { 68 // create proxy 69 attachments := map[string]string{} 70 attachments[constant.AsyncKey] = url.GetParam(constant.AsyncKey, "false") 71 attachments[constant.EnvironmentKey] = url.GetParam(constant.EnvironmentKey, "dev") 72 return proxy.NewProxy(invoker, callBack, attachments) 73 } 74 75 // GetInvoker gets a invoker 76 func (factory *DefaultProxyFactory) GetInvoker(url *common.URL) protocol.Invoker { 77 return &ProxyInvoker{ 78 BaseInvoker: *protocol.NewBaseInvoker(url), 79 } 80 } 81 82 // ProxyInvoker is a invoker struct 83 type ProxyInvoker struct { 84 protocol.BaseInvoker 85 } 86 87 // Invoke is used to call service method by invocation 88 func (pi *ProxyInvoker) Invoke(ctx context.Context, invocation protocol.Invocation) protocol.Result { 89 result := &protocol.RPCResult{} 90 result.SetAttachments(invocation.Attachments()) 91 92 // get providerUrl. The origin url may be is registry URL. 93 url := getProviderURL(pi.GetURL()) 94 95 methodName := invocation.MethodName() 96 proto := url.Protocol 97 path := strings.TrimPrefix(url.Path, "/") 98 args := invocation.Arguments() 99 100 // get service 101 svc := common.ServiceMap.GetServiceByServiceKey(proto, url.ServiceKey()) 102 if svc == nil { 103 logger.Errorf("cannot find service [%s] in %s", path, proto) 104 result.SetError(perrors.Errorf("cannot find service [%s] in %s", path, proto)) 105 return result 106 } 107 108 // get method 109 method := svc.Method()[methodName] 110 if method == nil { 111 logger.Errorf("cannot find method [%s] of service [%s] in %s", methodName, path, proto) 112 result.SetError(perrors.Errorf("cannot find method [%s] of service [%s] in %s", methodName, path, proto)) 113 return result 114 } 115 116 in := []reflect.Value{svc.Rcvr()} 117 if method.CtxType() != nil { 118 ctx = context.WithValue(ctx, constant.AttachmentKey, invocation.Attachments()) 119 in = append(in, method.SuiteContext(ctx)) 120 } 121 122 // prepare argv 123 if (len(method.ArgsType()) == 1 || len(method.ArgsType()) == 2 && method.ReplyType() == nil) && method.ArgsType()[0].String() == "[]interface {}" { 124 in = append(in, reflect.ValueOf(args)) 125 } else { 126 for i := 0; i < len(args); i++ { 127 t := reflect.ValueOf(args[i]) 128 if !t.IsValid() { 129 at := method.ArgsType()[i] 130 if at.Kind() == reflect.Ptr { 131 at = at.Elem() 132 } 133 t = reflect.New(at) 134 } 135 in = append(in, t) 136 } 137 } 138 139 // prepare replyv 140 var replyv reflect.Value 141 var retErr interface{} 142 143 returnValues, callErr := callLocalMethod(method.Method(), in) 144 145 if callErr != nil { 146 logger.Errorf("Invoke function error: %+v, service: %#v", callErr, url) 147 result.SetError(callErr) 148 return result 149 } 150 151 if len(returnValues) == 1 { 152 retErr = returnValues[0].Interface() 153 } else { 154 replyv = returnValues[0] 155 retErr = returnValues[1].Interface() 156 } 157 158 if retErr != nil { 159 result.SetError(retErr.(error)) 160 return result 161 } 162 if replyv.IsValid() && (replyv.Kind() != reflect.Ptr || replyv.Kind() == reflect.Ptr && replyv.Elem().IsValid()) { 163 result.SetResult(replyv.Interface()) 164 } 165 166 return result 167 } 168 169 func getProviderURL(url *common.URL) *common.URL { 170 if url.SubURL == nil { 171 return url 172 } 173 return url.SubURL 174 }