You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2020/01/16 09:18:43 UTC

[dubbo] branch master updated: allow user to pass AsyncMethodInfo at runtime. (#5635)

This is an automated email from the ASF dual-hosted git repository.

liujieqin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/master by this push:
     new 80646ba  allow user to pass AsyncMethodInfo at runtime. (#5635)
80646ba is described below

commit 80646ba28fd5c06aeeabaa81e90c469b91e5745d
Author: Ian Luo <ia...@gmail.com>
AuthorDate: Thu Jan 16 17:18:07 2020 +0800

    allow user to pass AsyncMethodInfo at runtime. (#5635)
---
 .../apache/dubbo/common/utils/ReflectUtils.java    | 30 ++++++++++++++++++++++
 .../java/org/apache/dubbo/rpc/AsyncRpcResult.java  | 13 ++++++++--
 .../main/java/org/apache/dubbo/rpc/Constants.java  |  2 ++
 .../dubbo/rpc/proxy/InvokerInvocationHandler.java  | 15 ++++++++++-
 .../rpc/proxy/InvokerInvocationHandlerTest.java    | 12 ++++-----
 .../apache/dubbo/rpc/protocol/dubbo/Constants.java |  2 ++
 .../rpc/protocol/dubbo/filter/FutureFilter.java    |  8 +++++-
 7 files changed, 72 insertions(+), 10 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
index 304a0c3..7bb9256 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
@@ -136,6 +136,20 @@ public final class ReflectUtils {
 
     private static final ConcurrentMap<String, Method> Signature_METHODS_CACHE = new ConcurrentHashMap<String, Method>();
 
+    private static Map<Class<?>, Object> primitiveDefaults = new HashMap<>();
+
+    static {
+        primitiveDefaults.put(int.class, 0);
+        primitiveDefaults.put(long.class, 0L);
+        primitiveDefaults.put(byte.class, (byte) 0);
+        primitiveDefaults.put(char.class, (char) 0);
+        primitiveDefaults.put(short.class, (short) 0);
+        primitiveDefaults.put(float.class, (float) 0);
+        primitiveDefaults.put(double.class, (double) 0);
+        primitiveDefaults.put(boolean.class, false);
+        primitiveDefaults.put(void.class, null);
+    }
+
     private ReflectUtils() {
     }
 
@@ -1066,6 +1080,22 @@ public final class ReflectUtils {
         }
     }
 
+    public static Object defaultReturn(Method m) {
+        if (m.getReturnType().isPrimitive()) {
+            return primitiveDefaults.get(m.getReturnType());
+        } else {
+            return null;
+        }
+    }
+
+    public static Object defaultReturn(Class<?> classType) {
+        if (classType != null && classType.isPrimitive()) {
+            return primitiveDefaults.get(classType);
+        } else {
+            return null;
+        }
+    }
+
     public static boolean isBeanPropertyReadMethod(Method method) {
         return method != null
                 && Modifier.isPublic(method.getModifiers())
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AsyncRpcResult.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AsyncRpcResult.java
index 542195d..751715b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AsyncRpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AsyncRpcResult.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.threadpool.ThreadlessExecutor;
+import org.apache.dubbo.rpc.model.ConsumerMethodModel;
 
 import java.util.Map;
 import java.util.concurrent.CompletableFuture;
@@ -29,6 +30,8 @@ import java.util.concurrent.TimeoutException;
 import java.util.function.BiConsumer;
 import java.util.function.Function;
 
+import static org.apache.dubbo.common.utils.ReflectUtils.defaultReturn;
+
 /**
  * This class represents an unfinished RPC call, it will hold some context information for this call, for example RpcContext and Invocation,
  * so that when the call finishes and the result returns, it can guarantee all the contexts being recovered as the same as when the call was made
@@ -144,7 +147,8 @@ public class AsyncRpcResult implements Result {
             // This should never happen;
             logger.error("Got exception when trying to fetch the underlying result from AsyncRpcResult.", e);
         }
-        return new AppResponse();
+
+        return createDefaultValue(invocation);
     }
 
     /**
@@ -240,8 +244,8 @@ public class AsyncRpcResult implements Result {
      * tmp context to use when the thread switch to Dubbo thread.
      */
     private RpcContext tmpContext;
-    private RpcContext tmpServerContext;
 
+    private RpcContext tmpServerContext;
     private BiConsumer<Result, Throwable> beforeContext = (appResponse, t) -> {
         tmpContext = RpcContext.getContext();
         tmpServerContext = RpcContext.getServerContext();
@@ -284,5 +288,10 @@ public class AsyncRpcResult implements Result {
         future.complete(result);
         return new AsyncRpcResult(future, invocation);
     }
+
+    private static Result createDefaultValue(Invocation invocation) {
+        ConsumerMethodModel method = (ConsumerMethodModel) invocation.get(Constants.METHOD_MODEL);
+        return method != null ? new AppResponse(defaultReturn(method.getReturnClass())) : new AppResponse();
+    }
 }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java
index b3eb025..c856b58 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Constants.java
@@ -85,4 +85,6 @@ public interface Constants {
     String INPUT_KEY = "input";
     String OUTPUT_KEY = "output";
 
+    String CONSUMER_MODEL = "consumerModel";
+    String METHOD_MODEL = "methodModel";
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
index c10369c..fc0f8b3 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
@@ -18,8 +18,11 @@ package org.apache.dubbo.rpc.proxy;
 
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.Constants;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ConsumerModel;
 
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -30,9 +33,14 @@ import java.lang.reflect.Method;
 public class InvokerInvocationHandler implements InvocationHandler {
     private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
     private final Invoker<?> invoker;
+    private ConsumerModel consumerModel;
 
     public InvokerInvocationHandler(Invoker<?> handler) {
         this.invoker = handler;
+        String serviceKey = invoker.getUrl().getServiceKey();
+        if (serviceKey != null) {
+            this.consumerModel = ApplicationModel.getConsumerModel(serviceKey);
+        }
     }
 
     @Override
@@ -55,7 +63,12 @@ public class InvokerInvocationHandler implements InvocationHandler {
             return invoker.equals(args[0]);
         }
         RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), args);
-        rpcInvocation.setTargetServiceUniqueName(invoker.getUrl().getServiceKey());
+        String serviceKey = invoker.getUrl().getServiceKey();
+        rpcInvocation.setTargetServiceUniqueName(serviceKey);
+        if (consumerModel != null) {
+            rpcInvocation.put(Constants.CONSUMER_MODEL, consumerModel);
+            rpcInvocation.put(Constants.METHOD_MODEL, consumerModel.getMethodModel(method));
+        }
 
         return invoker.invoke(rpcInvocation).recreate();
     }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandlerTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandlerTest.java
index 73f8c68..8dc8d15 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandlerTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandlerTest.java
@@ -16,13 +16,12 @@
  */
 package org.apache.dubbo.rpc.proxy;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.rpc.Invoker;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.InjectMocks;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
+import org.mockito.Mockito;
 
 import java.lang.reflect.Method;
 
@@ -30,14 +29,15 @@ import static org.mockito.Mockito.when;
 
 public class InvokerInvocationHandlerTest {
 
-    @Mock
     private Invoker<?> invoker;
-    @InjectMocks
     private InvokerInvocationHandler invokerInvocationHandler;
 
     @BeforeEach
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
+        URL url = URL.valueOf("mock://localhost:8080/FooService?group=mock&version=1.0.0");
+        invoker = Mockito.mock(Invoker.class);
+        when(invoker.getUrl()).thenReturn(url);
+        invokerInvocationHandler = new InvokerInvocationHandler(invoker);
     }
 
     @Test
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/Constants.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/Constants.java
index 56a1951..6ab8e40 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/Constants.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/Constants.java
@@ -66,4 +66,6 @@ public interface Constants {
 
     String ON_DISCONNECT_KEY = "ondisconnect";
 
+    String ASYNC_METHOD_INFO = "async-method-info";
+
 }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
index 28f67e1..7fd3f10 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
@@ -33,6 +33,7 @@ import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 
 import static org.apache.dubbo.common.constants.CommonConstants.$INVOKE;
+import static org.apache.dubbo.rpc.protocol.dubbo.Constants.ASYNC_METHOD_INFO;
 
 /**
  * EventFilter
@@ -186,7 +187,12 @@ public class FutureFilter implements Filter, Filter.Listener2 {
     }
 
     private AsyncMethodInfo getAsyncMethodInfo(Invoker<?> invoker, Invocation invocation) {
-        final ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());
+        AsyncMethodInfo asyncMethodInfo = (AsyncMethodInfo) invocation.get(ASYNC_METHOD_INFO);
+        if (asyncMethodInfo != null) {
+            return asyncMethodInfo;
+        }
+
+        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());
         if (consumerModel == null) {
             return null;
         }