You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by je...@apache.org on 2019/02/19 08:46:27 UTC

[incubator-dubbo] branch 3.x-dev updated: Mostly modification to satisfy more complexing support scenrio such as service Level model (#3264)

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

jefflv pushed a commit to branch 3.x-dev
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git


The following commit(s) were added to refs/heads/3.x-dev by this push:
     new ea71f0d  Mostly modification to satisfy more complexing support scenrio such as service Level model (#3264)
ea71f0d is described below

commit ea71f0dea6312ad3b3883141d93e5d9fa1022e55
Author: jefflv <lr...@gmail.com>
AuthorDate: Tue Feb 19 16:46:19 2019 +0800

    Mostly modification to satisfy more complexing support scenrio such as service Level model (#3264)
    
    * import servicemetada and associated it with models class
    
    * add a addressListner for extension and assiated it with RegistryDirectory
    
    * add a method for class CodecSupport
    
    * add ApplicationInitListener for extension and associated with ApplicationModel
    
    * rename the varibale name NAME_ID_MAP to
    
    * add a attributeMap to Invocation
    
    * remove unused imported class
    
    * add a SPI annotation to AddressListener
    
    * CompatibleInvocation's get/put attributes
    
    * CompatibleInvocation's get/put attributes
    
    * make methodModel's attributeMap to store Object
    
    * add a method getAttributes for Invocation
    
    * feature-lb-rr refactor OK
    
    * modify the pojo bean of ServiceMetadata
    
    * fix the failure of ListTelnetHandlerTest
---
 .../rpc/cluster/directory/MockDirInvocation.java   | 15 ++++
 .../java/com/alibaba/dubbo/rpc/Invocation.java     | 15 ++++
 .../java/org/apache/dubbo/cache/CacheTest.java     | 15 ++++
 .../org/apache/dubbo/service/MockInvocation.java   | 15 ++++
 .../org/apache/dubbo/config/ReferenceConfig.java   | 20 +++---
 .../org/apache/dubbo/config/ServiceConfig.java     | 24 +++----
 .../org/apache/dubbo/registry/AddressListener.java | 34 +++++++++
 .../registry/integration/RegistryDirectory.java    | 11 +++
 .../dubbo/remoting/transport/CodecSupport.java     |  6 ++
 .../main/java/org/apache/dubbo/rpc/Invocation.java |  5 ++
 .../java/org/apache/dubbo/rpc/RpcInvocation.java   | 15 ++++
 .../dubbo/rpc/model/ApplicationInitListener.java   | 27 +++++++
 .../apache/dubbo/rpc/model/ApplicationModel.java   | 19 ++++-
 .../dubbo/rpc/model/ConsumerMethodModel.java       |  9 ++-
 .../org/apache/dubbo/rpc/model/ConsumerModel.java  | 52 ++++----------
 .../dubbo/rpc/model/ProviderMethodModel.java       | 13 ++--
 .../org/apache/dubbo/rpc/model/ProviderModel.java  | 27 +++----
 .../apache/dubbo/rpc/model/ServiceMetadata.java    | 83 ++++++++++++++++++++++
 .../apache/dubbo/rpc/support/MockInvocation.java   | 15 ++++
 .../rpc/protocol/dubbo/ImplicitCallBackTest.java   |  7 +-
 .../dubbo/telnet/InvokerTelnetHandlerTest.java     | 14 ++--
 .../dubbo/telnet/ListTelnetHandlerTest.java        | 16 ++---
 .../dubbo/rpc/protocol/rest/RestProtocolTest.java  | 17 ++---
 .../dubbo/rpc/protol/rest/RestProtocolTest.java    |  9 ++-
 24 files changed, 373 insertions(+), 110 deletions(-)

diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
index 279160e..977feb2 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java
@@ -55,6 +55,21 @@ public class MockDirInvocation implements Invocation {
         return null;
     }
 
+    @Override
+    public Object put(Object key, Object value) {
+        return null;
+    }
+
+    @Override
+    public Object get(Object key) {
+        return null;
+    }
+
+    @Override
+    public Map<Object, Object> getAttributes() {
+        return null;
+    }
+
     public String getAttachment(String key) {
         return getAttachments().get(key);
     }
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
index b96d14d..475d26c 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java
@@ -73,6 +73,21 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation {
         }
 
         @Override
+        public Object put(Object key, Object value) {
+            return delegate.put(key, value);
+        }
+
+        @Override
+        public Object get(Object key) {
+            return delegate.get(key);
+        }
+
+        @Override
+        public Map<Object, Object> getAttributes() {
+            return delegate.getAttributes();
+        }
+
+        @Override
         public org.apache.dubbo.rpc.Invocation getOriginal() {
             return delegate;
         }
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/cache/CacheTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/cache/CacheTest.java
index 7084bd2..08d7d8d 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/cache/CacheTest.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/cache/CacheTest.java
@@ -83,5 +83,20 @@ public class CacheTest {
         public Invoker<?> getInvoker() {
             return null;
         }
+
+        @Override
+        public Object put(Object key, Object value) {
+            return null;
+        }
+
+        @Override
+        public Object get(Object key) {
+            return null;
+        }
+
+        @Override
+        public Map<Object, Object> getAttributes() {
+            return null;
+        }
     }
 }
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
index 148b5bc..7e03bb9 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java
@@ -61,6 +61,21 @@ public class MockInvocation implements Invocation {
         return null;
     }
 
+    @Override
+    public Object put(Object key, Object value) {
+        return null;
+    }
+
+    @Override
+    public Object get(Object key) {
+        return null;
+    }
+
+    @Override
+    public Map<Object, Object> getAttributes() {
+        return null;
+    }
+
     public String getAttachment(String key) {
         return getAttachments().get(key);
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index bafeffc..8f9c1e1 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -73,7 +73,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
      *
      * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
      * the protocol is <b>DubboProtocol</b></li>
-     *
+     * <p>
      * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
      * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
      */
@@ -300,7 +300,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
 
         ref = createProxy(map);
 
-        ConsumerModel consumerModel = new ConsumerModel(getUniqueServiceName(), interfaceClass, ref, interfaceClass.getMethods(), attributes);
+        ConsumerModel consumerModel = new ConsumerModel(interfaceName, group, version, interfaceClass, interfaceClass.getMethods(), attributes);
         ApplicationModel.initConsumerModel(getUniqueServiceName(), consumerModel);
     }
 
@@ -417,14 +417,14 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
             return;
         }
         setConsumer(
-                        ConfigManager.getInstance()
-                            .getDefaultConsumer()
-                            .orElseGet(() -> {
-                                ConsumerConfig consumerConfig = new ConsumerConfig();
-                                consumerConfig.refresh();
-                                return consumerConfig;
-                            })
-                );
+                ConfigManager.getInstance()
+                        .getDefaultConsumer()
+                        .orElseGet(() -> {
+                            ConsumerConfig consumerConfig = new ConsumerConfig();
+                            consumerConfig.refresh();
+                            return consumerConfig;
+                        })
+        );
     }
 
     private void completeCompoundConfigs() {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index aef5e5c..c02e745 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -84,7 +84,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
      *
      * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
      * the protocol is <b>DubboProtocol</b></li>
-     *
+     * <p>
      * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
      * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
      */
@@ -358,7 +358,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
         if (path == null || path.length() == 0) {
             path = interfaceName;
         }
-        ProviderModel providerModel = new ProviderModel(getUniqueServiceName(), ref, interfaceClass);
+        ProviderModel providerModel = new ProviderModel(interfaceName, group, version, ref, interfaceClass);
         ApplicationModel.initProviderModel(getUniqueServiceName(), providerModel);
         doExportUrls();
     }
@@ -790,7 +790,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
         if (provider != null) {
             return;
         }
-        setProvider (
+        setProvider(
                 ConfigManager.getInstance()
                         .getDefaultProvider()
                         .orElseGet(() -> {
@@ -821,15 +821,15 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
 
         if (StringUtils.isEmpty(protocolIds)) {
             if (CollectionUtils.isEmpty(protocols)) {
-               setProtocols(
-                       ConfigManager.getInstance().getDefaultProtocols()
-                        .filter(CollectionUtils::isNotEmpty)
-                        .orElseGet(() -> {
-                            ProtocolConfig protocolConfig = new ProtocolConfig();
-                            protocolConfig.refresh();
-                            return Arrays.asList(protocolConfig);
-                        })
-               );
+                setProtocols(
+                        ConfigManager.getInstance().getDefaultProtocols()
+                                .filter(CollectionUtils::isNotEmpty)
+                                .orElseGet(() -> {
+                                    ProtocolConfig protocolConfig = new ProtocolConfig();
+                                    protocolConfig.refresh();
+                                    return Arrays.asList(protocolConfig);
+                                })
+                );
             }
         } else {
             String[] arr = Constants.COMMA_SPLIT_PATTERN.split(protocolIds);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
new file mode 100644
index 0000000..c0176d5
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/AddressListener.java
@@ -0,0 +1,34 @@
+/*
+ * 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.registry;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+
+import java.util.List;
+
+@SPI
+public interface AddressListener {
+
+    /**
+     * processing when receiving the address list
+     *
+     * @param addresses
+     */
+    void notify(List<URL> addresses);
+
+}
\ No newline at end of file
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 5ebace2..d9e9765 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.registry.AddressListener;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.Registry;
 import org.apache.dubbo.rpc.Invocation;
@@ -183,6 +184,16 @@ public class RegistryDirectory<T> extends AbstractDirectory<T> implements Notify
                 .collect(Collectors.toList());
 
         /**
+         * 3.x added for extend URL address
+         */
+        ExtensionLoader<AddressListener> addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class);
+        Set<String> surpportedListeners = addressListenerExtensionLoader.getSupportedExtensions();
+        for (String addressListenerName : surpportedListeners) {
+            addressListenerExtensionLoader.getExtension(addressListenerName).notify(categoryUrls);
+        }
+
+
+        /**
          * TODO Try to refactor the processing of these three type of urls using Collectors.groupBy()?
          */
         this.configurators = Configurator.toConfigurators(classifyUrls(categoryUrls, UrlUtils::isConfigurator))
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
index 07da9a3..c8d9ebc 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
@@ -36,6 +36,7 @@ public class CodecSupport {
     private static final Logger logger = LoggerFactory.getLogger(CodecSupport.class);
     private static Map<Byte, Serialization> ID_SERIALIZATION_MAP = new HashMap<Byte, Serialization>();
     private static Map<Byte, String> ID_SERIALIZATIONNAME_MAP = new HashMap<Byte, String>();
+    private static Map<String, Byte> SERIALIZATIONNAME_ID_MAP = new HashMap<String, Byte>();
 
     static {
         Set<String> supportedExtensions = ExtensionLoader.getExtensionLoader(Serialization.class).getSupportedExtensions();
@@ -51,6 +52,7 @@ public class CodecSupport {
             }
             ID_SERIALIZATION_MAP.put(idByte, serialization);
             ID_SERIALIZATIONNAME_MAP.put(idByte, name);
+            SERIALIZATIONNAME_ID_MAP.put(name, idByte);
         }
     }
 
@@ -61,6 +63,10 @@ public class CodecSupport {
         return ID_SERIALIZATION_MAP.get(id);
     }
 
+    public static byte getIDByName(String name) {
+        return SERIALIZATIONNAME_ID_MAP.get(name);
+    }
+
     public static Serialization getSerialization(URL url) {
         return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(
                 url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION));
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
index 2b5f3dd..a2282f0 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
@@ -83,4 +83,9 @@ public interface Invocation {
      */
     Invoker<?> getInvoker();
 
+    Object put(Object key, Object value);
+
+    Object get(Object key);
+
+    Map<Object, Object> getAttributes();
 }
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
index b40f544..2d949d5 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
@@ -42,6 +42,8 @@ public class RpcInvocation implements Invocation, Serializable {
 
     private Map<String, String> attachments;
 
+    private Map<Object, Object> attributes = new HashMap<Object, Object>();
+
     private transient Invoker<?> invoker;
 
     public RpcInvocation() {
@@ -113,6 +115,19 @@ public class RpcInvocation implements Invocation, Serializable {
         this.invoker = invoker;
     }
 
+    public Object put(Object key, Object value) {
+        return attributes.put(key, value);
+    }
+
+    public Object get(Object key) {
+        return attributes.get(key);
+    }
+
+    @Override
+    public Map<Object, Object> getAttributes() {
+        return attributes;
+    }
+
     @Override
     public String getMethodName() {
         return methodName;
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java
new file mode 100644
index 0000000..f38acc4
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java
@@ -0,0 +1,27 @@
+/*
+ * 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.model;
+
+import org.apache.dubbo.common.extension.SPI;
+
+@SPI
+public interface ApplicationInitListener {
+    /**
+     * init the application
+     */
+    void init();
+}
\ No newline at end of file
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index cfad21c..cfdfb45 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@ -16,20 +16,23 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 
 import java.util.Collection;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  * Represent a application which is using Dubbo and store basic metadata info for using
  * during the processing of RPC invoking.
- *
+ * <p>
  * ApplicationModel includes many ProviderModel which is about published services
  * and many Consumer Model which is about subscribed services.
- *
+ * <p>
  * adjust project structure in order to fully utilize the methods introduced here.
  */
 public class ApplicationModel {
@@ -47,6 +50,8 @@ public class ApplicationModel {
 
     private static String application;
 
+    private static AtomicBoolean INIT_FLAG = new AtomicBoolean(false);
+
     public static Collection<ConsumerModel> allConsumerModels() {
         return consumedServices.values();
     }
@@ -63,6 +68,16 @@ public class ApplicationModel {
         return consumedServices.get(serviceName);
     }
 
+    public static void init() {
+        if (INIT_FLAG.compareAndSet(false, true)) {
+            ExtensionLoader<ApplicationInitListener> extensionLoader = ExtensionLoader.getExtensionLoader(ApplicationInitListener.class);
+            Set<String> listenerNames = extensionLoader.getSupportedExtensions();
+            for (String listenerName : listenerNames) {
+                extensionLoader.getExtension(listenerName).init();
+            }
+        }
+    }
+
     public static void initConsumerModel(String serviceName, ConsumerModel consumerModel) {
         if (consumedServices.putIfAbsent(serviceName, consumerModel) != null) {
             LOGGER.warn("Already register the same consumer:" + serviceName);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java
index 5a871ce..3d597f4 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerMethodModel.java
@@ -20,6 +20,8 @@ import org.apache.dubbo.common.Constants;
 
 import java.lang.reflect.Method;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class ConsumerMethodModel {
     private final Method method;
@@ -31,8 +33,9 @@ public class ConsumerMethodModel {
     private final String methodName;
     private final boolean generic;
 
-    private final AsyncMethodInfo asyncInfo;
+    private final ConcurrentMap<String, Object> attributeMap = new ConcurrentHashMap<>();
 
+    private final AsyncMethodInfo asyncInfo;
 
     public ConsumerMethodModel(Method method, Map<String, Object> attributes) {
         this.method = method;
@@ -53,6 +56,10 @@ public class ConsumerMethodModel {
         return method;
     }
 
+    public ConcurrentMap<String, Object> getAttributeMap() {
+        return attributeMap;
+    }
+
     public Class<?> getReturnClass() {
         return returnClass;
     }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
index 4c990a5..039e627 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
@@ -16,8 +16,6 @@
  */
 package org.apache.dubbo.rpc.model;
 
-import org.apache.dubbo.common.utils.Assert;
-
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.IdentityHashMap;
@@ -29,47 +27,22 @@ import java.util.Optional;
  * Consumer Model which is about subscribed services.
  */
 public class ConsumerModel {
-    private final Object proxyObject;
-    private final String serviceName;
-    private final Class<?> serviceInterfaceClass;
-
+    private final ServiceMetadata serviceMetadata;
     private final Map<Method, ConsumerMethodModel> methodModels = new IdentityHashMap<Method, ConsumerMethodModel>();
 
-    /**
-     *  This constructor create an instance of ConsumerModel and passed objects should not be null.
-     *  If service name, service instance, proxy object,methods should not be null. If these are null
-     *  then this constructor will throw {@link IllegalArgumentException}
-     * @param serviceName Name of the service.
-     * @param serviceInterfaceClass Service interface class.
-     * @param proxyObject  Proxy object.
-     * @param methods Methods of service class
-     * @param attributes Attributes of methods.
-     */
-    public ConsumerModel(String serviceName
-            , Class<?> serviceInterfaceClass
-            , Object proxyObject
-            , Method[] methods
-            , Map<String, Object> attributes) {
-
-        Assert.notEmptyString(serviceName, "Service name can't be null or blank");
-        Assert.notNull(serviceInterfaceClass, "Service interface class can't null");
-        Assert.notNull(proxyObject, "Proxy object can't be null");
-        Assert.notNull(methods, "Methods can't be null");
+    public ConsumerModel(String serviceName, String group, String version, Class<?> interfaceClass, Method[] methods, Map<String, Object> attributes) {
+        this.serviceMetadata = new ServiceMetadata(serviceName, group, version, interfaceClass);
 
-        this.serviceName = serviceName;
-        this.serviceInterfaceClass = serviceInterfaceClass;
-        this.proxyObject = proxyObject;
         for (Method method : methods) {
             methodModels.put(method, new ConsumerMethodModel(method, attributes));
         }
     }
 
     /**
-     * Return the proxy object used by called while creating instance of ConsumerModel
-     * @return
+     * @return serviceMetadata
      */
-    public Object getProxyObject() {
-        return proxyObject;
+    public ServiceMetadata getServiceMetadata() {
+        return serviceMetadata;
     }
 
     /**
@@ -94,6 +67,13 @@ public class ConsumerModel {
     }
 
     /**
+     * @return
+     */
+    public Class<?> getServiceInterfaceClass() {
+        return serviceMetadata.getServiceType();
+    }
+
+    /**
      * Return all method models for the current service
      *
      * @return method model list
@@ -102,11 +82,7 @@ public class ConsumerModel {
         return new ArrayList<ConsumerMethodModel>(methodModels.values());
     }
 
-    public Class<?> getServiceInterfaceClass() {
-        return serviceInterfaceClass;
-    }
-
     public String getServiceName() {
-        return serviceName;
+        return this.serviceMetadata.getServiceKey();
     }
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderMethodModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderMethodModel.java
index d7b8a9b..846ab60 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderMethodModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderMethodModel.java
@@ -17,17 +17,18 @@
 package org.apache.dubbo.rpc.model;
 
 import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 public class ProviderMethodModel {
-    private transient final Method method;
+    private final Method method;
     private final String methodName;
     private final String[] methodArgTypes;
-    private final String serviceName;
 
+    private final ConcurrentMap<String, Object> attributeMap = new ConcurrentHashMap<>();
 
-    public ProviderMethodModel(Method method, String serviceName) {
+    public ProviderMethodModel(Method method) {
         this.method = method;
-        this.serviceName = serviceName;
         this.methodName = method.getName();
         this.methodArgTypes = getArgTypes(method);
     }
@@ -44,8 +45,8 @@ public class ProviderMethodModel {
         return methodArgTypes;
     }
 
-    public String getServiceName() {
-        return serviceName;
+    public ConcurrentMap<String, Object> getAttributeMap() {
+        return attributeMap;
     }
 
     private static String[] getArgTypes(Method method) {
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
index 6fb9beb..73b292d 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
@@ -27,30 +27,27 @@ import java.util.Map;
  * ProviderModel which is about published services
  */
 public class ProviderModel {
-    private final String serviceName;
     private final Object serviceInstance;
-    private final Class<?> serviceInterfaceClass;
+    private final ServiceMetadata serviceMetadata;
     private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
 
-    public ProviderModel(String serviceName, Object serviceInstance, Class<?> serviceInterfaceClass) {
+    public ProviderModel(String serviceName, String group, String version, Object serviceInstance, Class<?> serviceInterfaceClass) {
         if (null == serviceInstance) {
             throw new IllegalArgumentException("Service[" + serviceName + "]Target is NULL.");
         }
 
-        this.serviceName = serviceName;
         this.serviceInstance = serviceInstance;
-        this.serviceInterfaceClass = serviceInterfaceClass;
-
-        initMethod();
+        this.serviceMetadata = new ServiceMetadata(serviceName, group, version, serviceInterfaceClass);
+        initMethod(serviceInterfaceClass);
     }
 
 
     public String getServiceName() {
-        return serviceName;
+        return this.serviceMetadata.getServiceKey();
     }
 
     public Class<?> getServiceInterfaceClass() {
-        return serviceInterfaceClass;
+        return this.serviceMetadata.getServiceType();
     }
 
     public Object getServiceInstance() {
@@ -77,9 +74,9 @@ public class ProviderModel {
         return null;
     }
 
-    private void initMethod() {
+    private void initMethod(Class<?> serviceInterfaceClass) {
         Method[] methodsToExport = null;
-        methodsToExport = this.serviceInterfaceClass.getMethods();
+        methodsToExport = serviceInterfaceClass.getMethods();
 
         for (Method method : methodsToExport) {
             method.setAccessible(true);
@@ -89,8 +86,14 @@ public class ProviderModel {
                 methodModels = new ArrayList<ProviderMethodModel>(1);
                 methods.put(method.getName(), methodModels);
             }
-            methodModels.add(new ProviderMethodModel(method, serviceName));
+            methodModels.add(new ProviderMethodModel(method));
         }
     }
 
+    /**
+     * @return serviceMetadata
+     */
+    public ServiceMetadata getServiceMetadata() {
+        return serviceMetadata;
+    }
 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ServiceMetadata.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ServiceMetadata.java
new file mode 100644
index 0000000..bb3f326
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ServiceMetadata.java
@@ -0,0 +1,83 @@
+/*
+ * 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.model;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * data related to service level such as name, version, classloader of business service,
+ * security info, etc. Also with a AttributeMap for extension.
+ */
+public class ServiceMetadata {
+
+    private final String serviceKey;
+    private final String serviceInterfaceName;
+    private final String group;
+    private final String version;
+    private final Class<?> serviceType;
+
+    /* will be transferred to remote side */
+    private final Map<String, Object> attachments = new ConcurrentHashMap<String, Object>();
+    /* used locally*/
+    private final Map<String, Object> attributeMap = new ConcurrentHashMap<String, Object>();
+
+    public ServiceMetadata(String serviceInterfaceName, String group, String version, Class<?> serviceType) {
+        this.serviceInterfaceName = serviceInterfaceName;
+        this.group = group;
+        this.version = version;
+        this.serviceKey = serviceInterfaceName + ":" + version;
+        this.serviceType = serviceType;
+    }
+
+    public String getServiceKey() {
+        return serviceKey;
+    }
+
+    public Map<String, Object> getAttachments() {
+        return attachments;
+    }
+
+    public Map<String, Object> getAttributeMap() {
+        return attributeMap;
+    }
+
+    public void addAttribute(String key, Object value) {
+        this.attributeMap.put(key, value);
+    }
+
+    public void addAttachment(String key, Object value) {
+        this.attributeMap.put(key, value);
+    }
+
+    public Class<?> getServiceType() {
+        return serviceType;
+    }
+
+    public String getServiceInterfaceName() {
+        return serviceInterfaceName;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
index 5b7261d..ce4d7f8 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
@@ -55,6 +55,21 @@ public class MockInvocation implements Invocation {
         return null;
     }
 
+    @Override
+    public Object put(Object key, Object value) {
+        return null;
+    }
+
+    @Override
+    public Object get(Object key) {
+        return null;
+    }
+
+    @Override
+    public Map<Object, Object> getAttributes() {
+        return null;
+    }
+
     public String getAttachment(String key) {
         return getAttachments().get(key);
     }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
index bcb623d..2c1baa6 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ImplicitCallBackTest.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerMethodModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
 import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
+
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
@@ -112,7 +113,7 @@ public class ImplicitCallBackTest {
         asyncMethodInfo.setOnthrowInstance(notify);
         asyncMethodInfo.setOnthrowMethod(onThrowMethod);
         attitudes.put("get", asyncMethodInfo);
-        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), IDemoService.class, demoProxy, IDemoService.class.getMethods(), attitudes));
+        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceInterface(), "Dubbo", "1.0.0", IDemoService.class, IDemoService.class.getMethods(), attitudes));
     }
 
     //================================================================================================
@@ -123,7 +124,7 @@ public class ImplicitCallBackTest {
         asyncMethodInfo.setOnreturnInstance(notify);
         asyncMethodInfo.setOnreturnMethod(onReturnMethod);
         attitudes.put("get", asyncMethodInfo);
-        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), IDemoService.class, demoProxy, IDemoService.class.getMethods(), attitudes));
+        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceInterface(), "Dubbo", "1.0.0", IDemoService.class, IDemoService.class.getMethods(), attitudes));
     }
 
     public void initImplicitCallBackURL_onlyOninvoke() throws Exception {
@@ -132,7 +133,7 @@ public class ImplicitCallBackTest {
         asyncMethodInfo.setOninvokeInstance(notify);
         asyncMethodInfo.setOninvokeMethod(onInvokeMethod);
         attitudes.put("get", asyncMethodInfo);
-        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceKey(), IDemoService.class, demoProxy, IDemoService.class.getMethods(), attitudes));
+        ApplicationModel.initConsumerModel(consumerUrl.getServiceKey(), new ConsumerModel(consumerUrl.getServiceInterface(), "Dubbo", "1.0.0", IDemoService.class, IDemoService.class.getMethods(), attitudes));
     }
 
     @Test
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
index 705eb64..b8e2b24 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/InvokerTelnetHandlerTest.java
@@ -62,7 +62,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = invoke.telnet(mockChannel, "DemoService.echo(\"ok\")");
@@ -77,7 +77,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         // pass null value to parameter of primitive type
@@ -112,7 +112,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = invoke.telnet(mockChannel, "getType(\"High\")");
@@ -128,7 +128,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         // pass json value to parameter of Person type
@@ -145,7 +145,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         // pass json value to parameter of Person type and specify it's type
@@ -168,7 +168,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         // pass json value to parameter of Person type
@@ -191,7 +191,7 @@ public class InvokerTelnetHandlerTest {
         given(mockChannel.getLocalAddress()).willReturn(NetUtils.toAddress("127.0.0.1:5555"));
         given(mockChannel.getRemoteAddress()).willReturn(NetUtils.toAddress("127.0.0.1:20886"));
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = invoke.telnet(mockChannel, "echo(\"ok\")");
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandlerTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandlerTest.java
index 57172a4..b94f3ae 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandlerTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/telnet/ListTelnetHandlerTest.java
@@ -66,7 +66,7 @@ public class ListTelnetHandlerTest {
         mockChannel = mock(Channel.class);
         given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = list.telnet(mockChannel, "-l DemoService");
@@ -80,7 +80,7 @@ public class ListTelnetHandlerTest {
         mockChannel = mock(Channel.class);
         given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = list.telnet(mockChannel, "DemoService");
@@ -94,11 +94,11 @@ public class ListTelnetHandlerTest {
         mockChannel = mock(Channel.class);
         given(mockChannel.getAttribute("telnet.service")).willReturn(null);
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = list.telnet(mockChannel, "");
-        assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService\r\n", result);
+        assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0\r\n", result);
     }
 
     @Test
@@ -106,11 +106,11 @@ public class ListTelnetHandlerTest {
         mockChannel = mock(Channel.class);
         given(mockChannel.getAttribute("telnet.service")).willReturn(null);
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = list.telnet(mockChannel, "-l");
-        assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService ->  published: N\r\n", result);
+        assertEquals("PROVIDER:\r\norg.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0 ->  published: N\r\n", result);
     }
 
     @Test
@@ -118,12 +118,12 @@ public class ListTelnetHandlerTest {
         mockChannel = mock(Channel.class);
         given(mockChannel.getAttribute("telnet.service")).willReturn("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService");
 
-        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", new DemoServiceImpl(), DemoService.class);
+        ProviderModel providerModel = new ProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", "Dubbo", "1.0.0", new DemoServiceImpl(), DemoService.class);
         ApplicationModel.initProviderModel("org.apache.dubbo.rpc.protocol.dubbo.support.DemoService", providerModel);
 
         String result = list.telnet(mockChannel, "");
         assertTrue(result.startsWith("Use default service org.apache.dubbo.rpc.protocol.dubbo.support.DemoService.\r\n" +
-                "org.apache.dubbo.rpc.protocol.dubbo.support.DemoService (as provider):\r\n"));
+                "org.apache.dubbo.rpc.protocol.dubbo.support.DemoService:1.0.0 (as provider):\r\n"));
         for (Method method : DemoService.class.getMethods()) {
             assertTrue(result.contains(method.getName()));
         }
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
index 215bc41..35b78b6 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
@@ -29,6 +29,7 @@ import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+
 import org.hamcrest.CoreMatchers;
 import org.junit.After;
 import org.junit.Test;
@@ -50,7 +51,7 @@ public class RestProtocolTest {
     @Test
     public void testExport() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         RpcContext.getContext().setAttachment("timeout", "200");
@@ -67,7 +68,7 @@ public class RestProtocolTest {
     @Test
     public void testNettyServer() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         URL nettyUrl = exportUrl.addParameter(Constants.SERVER_KEY, "netty");
@@ -84,7 +85,7 @@ public class RestProtocolTest {
     @Test(expected = RpcException.class)
     public void testServletWithoutWebConfig() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         URL servletUrl = exportUrl.addParameter(Constants.SERVER_KEY, "servlet");
@@ -95,7 +96,7 @@ public class RestProtocolTest {
     @Test(expected = RpcException.class)
     public void testErrorHandler() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         URL nettyUrl = exportUrl.addParameter(Constants.SERVER_KEY, "netty");
@@ -109,7 +110,7 @@ public class RestProtocolTest {
     @Test
     public void testInvoke() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
 
@@ -124,7 +125,7 @@ public class RestProtocolTest {
     @Test
     public void testFilter() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         URL nettyUrl = exportUrl.addParameter(Constants.SERVER_KEY, "netty")
@@ -143,7 +144,7 @@ public class RestProtocolTest {
     @Test
     public void testRpcContextFilter() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         // use RpcContextFilter
@@ -166,7 +167,7 @@ public class RestProtocolTest {
     @Test(expected = RuntimeException.class)
     public void testRegFail() {
         IDemoService server = new DemoService();
-        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceKey(), server, IDemoService.class);
+        ProviderModel providerModel = new ProviderModel(exportUrl.getServiceInterface(), "Dubbo", "1.0.0", server, IDemoService.class);
         ApplicationModel.initProviderModel(exportUrl.getServiceKey(), providerModel);
 
         URL nettyUrl = exportUrl.addParameter(Constants.EXTENSION_KEY, "com.not.existing.Filter");
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protol/rest/RestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protol/rest/RestProtocolTest.java
index ab0da76..81b2f79 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protol/rest/RestProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protol/rest/RestProtocolTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc.protol.rest;
 
 import junit.framework.Assert;
+
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.rpc.Exporter;
@@ -25,6 +26,7 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+
 import org.junit.Test;
 
 /**
@@ -39,11 +41,12 @@ public class RestProtocolTest {
     public void testRestProtocol() {
         URL url = URL.valueOf("rest://127.0.0.1:5342/rest/say1?version=1.0.0");
         RestServiceImpl server = new RestServiceImpl();
-        ProviderModel providerModel = new ProviderModel(url.getServiceKey(), server, RestService.class);
+        ProviderModel providerModel = new ProviderModel(url.getServiceInterface(), "Dubbo", "1.0.0", server, RestService.class);
         ApplicationModel.initProviderModel(url.getServiceKey(), providerModel);
 
         Exporter<RestService> exporter = protocol.export(proxyFactory.getInvoker(server, RestService.class, url));
-        Invoker<RestService> invoker = protocol.refer(RestService.class, url);        Assert.assertFalse(server.isCalled());
+        Invoker<RestService> invoker = protocol.refer(RestService.class, url);
+        Assert.assertFalse(server.isCalled());
 
         RestService client = proxyFactory.getProxy(invoker);
         String result = client.sayHello("haha");
@@ -58,7 +61,7 @@ public class RestProtocolTest {
         RestServiceImpl server = new RestServiceImpl();
         Assert.assertFalse(server.isCalled());
         URL url = URL.valueOf("rest://127.0.0.1:5341/a/b/c?version=1.0.0");
-        ProviderModel providerModel = new ProviderModel(url.getServiceKey(), server, RestService.class);
+        ProviderModel providerModel = new ProviderModel(url.getServiceInterface(), "Dubbo", "1.0.0", server, RestService.class);
         ApplicationModel.initProviderModel(url.getServiceKey(), providerModel);
 
         Exporter<RestService> exporter = protocol.export(proxyFactory.getInvoker(server, RestService.class, url));