You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/10/23 14:34:09 UTC

[dubbo] branch 3.0 updated: Add some test cases and adjust the code format (#9102)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 6a37d45  Add some test cases and adjust the code format (#9102)
6a37d45 is described below

commit 6a37d45ee9c7adca9750ed9538452e99281569ed
Author: 灼华 <43...@users.noreply.github.com>
AuthorDate: Sat Oct 23 22:33:53 2021 +0800

    Add some test cases and adjust the code format (#9102)
---
 .../registry/integration/RegistryProtocol.java     |  2 -
 .../java/org/apache/dubbo/rpc/AppResponse.java     |  2 +-
 .../java/org/apache/dubbo/rpc/AsyncRpcResult.java  |  2 +-
 .../src/main/java/org/apache/dubbo/rpc/Filter.java |  2 +-
 .../apache/dubbo/rpc/filter/ActiveLimitFilter.java |  6 +--
 .../org/apache/dubbo/rpc/filter/ContextFilter.java |  9 ++--
 .../dubbo/rpc/filter/ExecuteLimitFilter.java       |  4 +-
 .../org/apache/dubbo/rpc/filter/TokenFilter.java   |  2 +-
 .../apache/dubbo/rpc/protocol/InvokerWrapper.java  |  2 +-
 .../dubbo/rpc/proxy/AbstractProxyFactory.java      |  3 +-
 .../rpc/proxy/wrapper/StubProxyFactoryWrapper.java |  2 +-
 .../java/org/apache/dubbo/rpc/AppResponseTest.java |  2 +-
 .../rpc/filter/CompatibleFilterFilterTest.java     |  2 +-
 .../apache/dubbo/rpc/proxy/AbstractProxyTest.java  | 15 ++++--
 .../proxy/wrapper/StubProxyFactoryWrapperTest.java | 56 ++++++++++++++++++++++
 .../apache/dubbo/rpc/support/DemoServiceStub.java} | 30 +++---------
 .../org/apache/dubbo/rpc/support/MyInvoker.java    |  6 +++
 .../dubbo/rpc/protocol/dubbo/DubboExporter.java    |  1 +
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |  1 -
 19 files changed, 99 insertions(+), 50 deletions(-)

diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index 48cea93..e9ed322 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -645,7 +645,6 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
     }
 
     public static class InvokerDelegate<T> extends InvokerWrapper<T> {
-        private final Invoker<T> invoker;
 
         /**
          * @param invoker
@@ -653,7 +652,6 @@ public class RegistryProtocol implements Protocol, ScopeModelAware {
          */
         public InvokerDelegate(Invoker<T> invoker, URL url) {
             super(invoker, url);
-            this.invoker = invoker;
         }
 
         public Invoker<T> getInvoker() {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AppResponse.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AppResponse.java
index 118e701..3eb5f17 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AppResponse.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/AppResponse.java
@@ -44,7 +44,7 @@ import static org.apache.dubbo.rpc.Constants.INVOCATION_KEY;
  *  }
  * </pre>
  * AsyncRpcResult is a future representing an unfinished RPC call, while AppResponse is the actual return type of this call.
- * In theory, AppResponse does'n have to implement the {@link Result} interface, this is done mainly for compatibility purpose.
+ * In theory, AppResponse doesn't have to implement the {@link Result} interface, this is done mainly for compatibility purpose.
  *
  * @serial Do not change the class name and properties.
  */
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 1feeead..1accccd 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
@@ -80,7 +80,7 @@ public class AsyncRpcResult implements Result {
 
     /**
      * CompletableFuture can only be completed once, so try to update the result of one completed CompletableFuture will
-     * has no effect. To avoid this problem, we check the complete status of this future before update it's value.
+     * have no effect. To avoid this problem, we check the complete status of this future before update its value.
      *
      * But notice that trying to give an uncompleted CompletableFuture a new specified value may face a race condition,
      * because the background thread watching the real result will also change the status of this CompletableFuture.
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
index 4d6752e..79fea6e 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Filter.java
@@ -35,7 +35,7 @@ import org.apache.dubbo.common.extension.SPI;
  *    remote call configured caching type's (e.g. Thread Local, JCache etc) implementation invoke method gets called.
  * </pre>
  *
- * Starting from 3.0, Filter on consumer side has been refactored. There're two different kinds of Filters working at different stages
+ * Starting from 3.0, Filter on consumer side has been refactored. There are two different kinds of Filters working at different stages
  * of an RPC request.
  * 1. Filter. Works at the instance level, each Filter is bond to one specific Provider instance(invoker).
  * 2. ClusterFilter. Newly introduced in 3.0, intercepts request before Loadbalancer picks one specific Filter(Invoker).
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
index e1d8af7..dc954d7 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ActiveLimitFilter.java
@@ -44,7 +44,7 @@ import static org.apache.dubbo.rpc.Constants.ACTIVES_KEY;
 @Activate(group = CONSUMER, value = ACTIVES_KEY)
 public class ActiveLimitFilter implements Filter, Filter.Listener {
 
-    private static final String ACTIVELIMIT_FILTER_START_TIME = "activelimit_filter_start_time";
+    private static final String ACTIVE_LIMIT_FILTER_START_TIME = "active_limit_filter_start_time";
 
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
@@ -76,7 +76,7 @@ public class ActiveLimitFilter implements Filter, Filter.Listener {
             }
         }
 
-        invocation.put(ACTIVELIMIT_FILTER_START_TIME, System.currentTimeMillis());
+        invocation.put(ACTIVE_LIMIT_FILTER_START_TIME, System.currentTimeMillis());
 
         return invoker.invoke(invocation);
     }
@@ -108,7 +108,7 @@ public class ActiveLimitFilter implements Filter, Filter.Listener {
     }
 
     private long getElapsed(Invocation invocation) {
-        Object beginTime = invocation.get(ACTIVELIMIT_FILTER_START_TIME);
+        Object beginTime = invocation.get(ACTIVE_LIMIT_FILTER_START_TIME);
         return beginTime != null ? System.currentTimeMillis() - (Long) beginTime : 0;
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
index c813384..75a52b2 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ContextFilter.java
@@ -40,6 +40,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
 import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_ATTACHMENT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_KEY;
@@ -58,8 +59,6 @@ import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
 @Activate(group = PROVIDER, order = -10000)
 public class ContextFilter implements Filter, Filter.Listener {
 
-    private static final String TAG_KEY = "dubbo.tag";
-
     private static final Set<String> UNLOADING_KEYS;
 
     static {
@@ -100,11 +99,11 @@ public class ContextFilter implements Filter, Filter.Listener {
 //                .setAttachments(attachments)  // merged from dubbox
         context.setLocalAddress(invoker.getUrl().getHost(), invoker.getUrl().getPort());
 
-        String remoteApplication = (String) invocation.getAttachment(REMOTE_APPLICATION_KEY);
+        String remoteApplication = invocation.getAttachment(REMOTE_APPLICATION_KEY);
         if (StringUtils.isNotEmpty(remoteApplication)) {
             RpcContext.getServiceContext().setRemoteApplicationName(remoteApplication);
         } else {
-            RpcContext.getServiceContext().setRemoteApplicationName((String) context.getAttachment(REMOTE_APPLICATION_KEY));
+            RpcContext.getServiceContext().setRemoteApplicationName(context.getAttachment(REMOTE_APPLICATION_KEY));
         }
 
         long timeout = RpcUtils.getTimeout(invocation, -1);
@@ -114,7 +113,7 @@ public class ContextFilter implements Filter, Filter.Listener {
         }
 
         // merged from dubbox
-        // we may already added some attachments into RpcContext before this filter (e.g. in rest protocol)
+        // we may already add some attachments into RpcContext before this filter (e.g. in rest protocol)
         if (attachments != null) {
             if (context.getObjectAttachments() != null) {
                 context.getObjectAttachments().putAll(attachments);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
index 63e8caf..c7efb40 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/ExecuteLimitFilter.java
@@ -31,8 +31,8 @@ import static org.apache.dubbo.rpc.Constants.EXECUTES_KEY;
 
 /**
  * The maximum parallel execution request count per method per service for the provider.If the max configured
- * <b>executes</b> is set to 10 and if invoke request where it is already 10 then it will throws exception. It
- * continue the same behaviour un till it is <10.
+ * <b>executes</b> is set to 10 and if invoke request where it is already 10 then it will throw exception. It
+ * continues the same behaviour un till it is <10.
  */
 @Activate(group = CommonConstants.PROVIDER, value = EXECUTES_KEY)
 public class ExecuteLimitFilter implements Filter, Filter.Listener {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TokenFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TokenFilter.java
index f3ed745..3e5616b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TokenFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/TokenFilter.java
@@ -32,7 +32,7 @@ import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
 
 /**
  * Perform check whether given provider token is matching with remote token or not. If it does not match
- * it will not allow to invoke remote method.
+ * it will not allow invoking remote method.
  *
  * @see Filter
  */
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java
index 0ab182a..a2e0dae 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/InvokerWrapper.java
@@ -27,7 +27,7 @@ import org.apache.dubbo.rpc.RpcException;
  */
 public class InvokerWrapper<T> implements Invoker<T> {
 
-    private final Invoker<T> invoker;
+    protected final Invoker<T> invoker;
 
     private final URL url;
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java
index afb1c11..f65576c 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/AbstractProxyFactory.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc.proxy;
 
 import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.Constants;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.ProxyFactory;
@@ -52,7 +53,7 @@ public abstract class AbstractProxyFactory implements ProxyFactory {
         LinkedHashSet<Class<?>> interfaces = new LinkedHashSet<>();
 
         String config = invoker.getUrl().getParameter(INTERFACES);
-        if (config != null && config.length() > 0) {
+        if (StringUtils.isNotEmpty(config)) {
             String[] types = COMMA_SPLIT_PATTERN.split(config);
             for (String type : types) {
                 try {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java
index e8b0f19..a49b975 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapper.java
@@ -90,7 +90,7 @@ public class StubProxyFactoryWrapper implements ProxyFactory {
                             urlBuilder.addParameter(STUB_EVENT_METHODS_KEY, StringUtils.join(Wrapper.getWrapper(proxy.getClass()).getDeclaredMethodNames(), ","));
                             urlBuilder.addParameter(IS_SERVER_KEY, Boolean.FALSE.toString());
                             try {
-                                export(proxy, (Class) invoker.getInterface(), urlBuilder.build());
+                                export(proxy, invoker.getInterface(), urlBuilder.build());
                             } catch (Exception e) {
                                 LOGGER.error("export a stub service error.", e);
                             }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
index 3641185..7549692 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/AppResponseTest.java
@@ -92,7 +92,7 @@ public class AppResponseTest {
             }
         }
         /**
-         * may be there is -XX:-OmitStackTraceInFastThrow or run in Debug mode
+         * maybe there is -XX:-OmitStackTraceInFastThrow or run in Debug mode
          */
         if (throwable == null) {
             System.out.println("###buildEmptyStackTraceException fail to construct NPE");
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
index 0bee557..7750195 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/filter/CompatibleFilterFilterTest.java
@@ -68,7 +68,7 @@ public class CompatibleFilterFilterTest {
     }
 
     @Test
-    public void testResulthasException() {
+    public void testResultHasException() {
         invocation = mock(Invocation.class);
         given(invocation.getMethodName()).willReturn("enumlength");
         given(invocation.getParameterTypes()).willReturn(new Class<?>[]{Enum.class});
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/AbstractProxyTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/AbstractProxyTest.java
index b505ee8..aece1d6 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/AbstractProxyTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/AbstractProxyTest.java
@@ -21,6 +21,8 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.service.Destroyable;
+import org.apache.dubbo.rpc.service.EchoService;
 import org.apache.dubbo.rpc.support.DemoService;
 import org.apache.dubbo.rpc.support.DemoServiceImpl;
 import org.apache.dubbo.rpc.support.MyInvoker;
@@ -39,20 +41,23 @@ public abstract class AbstractProxyTest {
     public void testGetProxy() throws Exception {
         URL url = URL.valueOf("test://test:11/test?group=dubbo&version=1.1");
 
-        Invoker<DemoService> invoker = new MyInvoker<>(url);
+        MyInvoker<DemoService> invoker = new MyInvoker<>(url);
 
         DemoService proxy = factory.getProxy(invoker);
 
         Assertions.assertNotNull(proxy);
 
         Assertions.assertTrue(Arrays.asList(proxy.getClass().getInterfaces()).contains(DemoService.class));
-
-        // Not equal
-        //Assertions.assertEquals(proxy.toString(), invoker.toString());
-        //Assertions.assertEquals(proxy.hashCode(), invoker.hashCode());
+        Assertions.assertTrue(Arrays.asList(proxy.getClass().getInterfaces()).contains(Destroyable.class));
+        Assertions.assertTrue(Arrays.asList(proxy.getClass().getInterfaces()).contains(EchoService.class));
 
         Assertions.assertEquals(invoker.invoke(new RpcInvocation("echo", DemoService.class.getName(), DemoService.class.getName() + ":dubbo", new Class[]{String.class}, new Object[]{"aa"})).getValue()
                 , proxy.echo("aa"));
+
+        Destroyable destroyable = (Destroyable)proxy;
+        destroyable.$destroy();
+        Assertions.assertTrue(invoker.isDestroyed());
+
     }
 
     @Test
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapperTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapperTest.java
new file mode 100644
index 0000000..c120df5
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/proxy/wrapper/StubProxyFactoryWrapperTest.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.proxy.wrapper;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.support.DemoService;
+import org.apache.dubbo.rpc.support.DemoServiceStub;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.Mockito;
+
+import static org.apache.dubbo.common.constants.CommonConstants.STUB_EVENT_KEY;
+import static org.apache.dubbo.rpc.Constants.STUB_KEY;
+
+/**
+ * {@link StubProxyFactoryWrapper }
+ */
+public class StubProxyFactoryWrapperTest {
+
+    @Test
+    public void test() {
+        ProxyFactory proxyFactory = Mockito.mock(ProxyFactory.class);
+        Protocol protocol = Mockito.mock(Protocol.class);
+        StubProxyFactoryWrapper stubProxyFactoryWrapper = new StubProxyFactoryWrapper(proxyFactory);
+        stubProxyFactoryWrapper.setProtocol(protocol);
+
+        URL url = URL.valueOf("test://127.0.0.1/test?stub=true");
+        url = url.addParameter(STUB_KEY, "true");
+        url = url.addParameter(STUB_EVENT_KEY, "true");
+        Invoker<DemoService> invoker = Mockito.mock(Invoker.class);
+        Mockito.when(invoker.getInterface()).thenReturn(DemoService.class);
+        Mockito.when(invoker.getUrl()).thenReturn(url);
+
+        DemoService proxy = stubProxyFactoryWrapper.getProxy(invoker, false);
+        Assertions.assertTrue(proxy instanceof DemoServiceStub);
+        Mockito.verify(protocol, Mockito.times(1)).export(Mockito.any());
+
+    }
+}
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceStub.java
similarity index 56%
copy from dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java
copy to dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceStub.java
index 367f308..2b13b36 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/DemoServiceStub.java
@@ -14,32 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.rpc.protocol.dubbo;
+package org.apache.dubbo.rpc.support;
 
-import org.apache.dubbo.rpc.Exporter;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.protocol.AbstractExporter;
+public class DemoServiceStub extends DemoServiceImpl{
+    private DemoService demoService;
 
-import java.util.Map;
-
-/**
- * DubboExporter
- */
-public class DubboExporter<T> extends AbstractExporter<T> {
-
-    private final String key;
-
-    private final Map<String, Exporter<?>> exporterMap;
-
-    public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap) {
-        super(invoker);
-        this.key = key;
-        this.exporterMap = exporterMap;
+    public DemoServiceStub(DemoService demoService) {
+        this.demoService = demoService;
     }
 
-    @Override
-    public void afterUnExport() {
-        exporterMap.remove(key);
+    public DemoService getDemoService() {
+        return demoService;
     }
-
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
index e15f244..f2dbe07 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MyInvoker.java
@@ -34,6 +34,7 @@ public class MyInvoker<T> implements Invoker<T> {
     URL url;
     Class<T> type;
     boolean hasException = false;
+    boolean destroyed = false;
 
     public MyInvoker(URL url) {
         this.url = url;
@@ -74,6 +75,11 @@ public class MyInvoker<T> implements Invoker<T> {
 
     @Override
     public void destroy() {
+        destroyed = true;
+    }
+
+    public boolean isDestroyed() {
+        return destroyed;
     }
 
     @Override
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java
index 367f308..3ad06cc 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboExporter.java
@@ -35,6 +35,7 @@ public class DubboExporter<T> extends AbstractExporter<T> {
         super(invoker);
         this.key = key;
         this.exporterMap = exporterMap;
+        exporterMap.put(key, this);
     }
 
     @Override
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 7605959..3291c50 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -295,7 +295,6 @@ public class DubboProtocol extends AbstractProtocol {
         // export service.
         String key = serviceKey(url);
         DubboExporter<T> exporter = new DubboExporter<T>(invoker, key, exporterMap);
-        exporterMap.put(key, exporter);
 
         //export an stub service for dispatching event
         Boolean isStubSupportEvent = url.getParameter(STUB_EVENT_KEY, DEFAULT_STUB_EVENT);