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 2022/07/15 01:22:57 UTC

[dubbo] branch 3.0 updated: Decoupling ConfigBase and ServiceModel (#10110)

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

liujun 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 807fc12203 Decoupling ConfigBase and ServiceModel (#10110)
807fc12203 is described below

commit 807fc1220382aa962523476d54080791493dedab
Author: huazhongming <cr...@gmail.com>
AuthorDate: Fri Jul 15 09:22:47 2022 +0800

    Decoupling ConfigBase and ServiceModel (#10110)
---
 .../org/apache/dubbo/rpc/model/ConsumerModel.java  |  27 +++---
 .../org/apache/dubbo/rpc/model/ModuleModel.java    |  11 ++-
 .../dubbo/rpc/model/ModuleServiceRepository.java   |  23 +++--
 .../org/apache/dubbo/rpc/model/ProviderModel.java  |  37 +++++---
 .../org/apache/dubbo/rpc/model/ServiceModel.java   | 101 +++++++++++++--------
 .../rpc/model/FrameworkServiceRepositoryTest.java  |   8 +-
 .../rpc/model/ModuleServiceRepositoryTest.java     |   8 +-
 .../dubbo/rpc/model/ServiceRepositoryTest.java     |   8 +-
 .../src/main/resources/DubboGrpcStub.mustache      |   9 +-
 .../main/resources/ReactorDubboGrpcStub.mustache   |   9 +-
 .../src/main/resources/RxDubboGrpcStub.mustache    |   9 +-
 .../org/apache/dubbo/config/ReferenceConfig.java   |  16 +++-
 .../org/apache/dubbo/config/ServiceConfig.java     |  50 ++++++----
 .../dubbo/config/deploy/DefaultModuleDeployer.java |   8 +-
 ...MetadataServiceURLParamsMetadataCustomizer.java |   2 +-
 .../org/apache/dubbo/qos/command/impl/LsTest.java  |   6 +-
 .../apache/dubbo/qos/command/impl/OfflineTest.java |   4 +-
 .../apache/dubbo/qos/command/impl/OnlineTest.java  |   4 +-
 .../qos/command/util/ServiceCheckUtilsTest.java    |   4 +-
 .../registry/client/metadata/MetadataUtils.java    |  21 ++++-
 .../dubbo/rpc/proxy/AbstractProxyFactory.java      |   4 +-
 .../rpc/protocol/dubbo/CallbackServiceCodec.java   |   2 +-
 .../rpc/protocol/dubbo/ArgumentCallbackTest.java   |  11 ++-
 .../dubbo/rpc/protocol/grpc/GrpcProtocol.java      |   7 +-
 .../dubbo/rpc/protocol/grpc/GrpcProtocolTest.java  |   4 +-
 .../protocol/grpc/support/DubboGreeterGrpc.java    |  10 +-
 .../rpc/protocol/injvm/InjvmClassLoaderTest.java   |   5 +-
 .../rpc/protocol/injvm/InjvmDeepCopyTest.java      |   5 +-
 .../dubbo/rpc/protocol/tri/TripleProtocolTest.java |   4 +-
 29 files changed, 241 insertions(+), 176 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
index 72892d55e2..24876bc196 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.utils.Assert;
-import org.apache.dubbo.config.ReferenceConfigBase;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -49,11 +48,11 @@ public class ConsumerModel extends ServiceModel {
      */
     public ConsumerModel(String serviceKey,
                          Object proxyObject,
-                         ServiceDescriptor serviceModel,
-                         ReferenceConfigBase<?> referenceConfig,
-                         Map<String, AsyncMethodInfo> methodConfigs) {
+                         ServiceDescriptor serviceDescriptor,
+                         Map<String, AsyncMethodInfo> methodConfigs,
+                         ClassLoader interfaceClassLoader) {
 
-        super(proxyObject, serviceKey, serviceModel, referenceConfig);
+        super(proxyObject, serviceKey, serviceDescriptor, null, interfaceClassLoader);
         Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
 
         this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
@@ -61,12 +60,12 @@ public class ConsumerModel extends ServiceModel {
 
     public ConsumerModel(String serviceKey,
                          Object proxyObject,
-                         ServiceDescriptor serviceModel,
-                         ReferenceConfigBase<?> referenceConfig,
+                         ServiceDescriptor serviceDescriptor,
                          ServiceMetadata metadata,
-                         Map<String, AsyncMethodInfo> methodConfigs) {
+                         Map<String, AsyncMethodInfo> methodConfigs,
+                         ClassLoader interfaceClassLoader) {
 
-        super(proxyObject, serviceKey, serviceModel, referenceConfig, metadata);
+        super(proxyObject, serviceKey, serviceDescriptor, null, metadata, interfaceClassLoader);
         Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
 
         this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
@@ -74,13 +73,13 @@ public class ConsumerModel extends ServiceModel {
 
     public ConsumerModel(String serviceKey,
                          Object proxyObject,
-                         ServiceDescriptor serviceModel,
-                         ReferenceConfigBase<?> referenceConfig,
+                         ServiceDescriptor serviceDescriptor,
                          ModuleModel moduleModel,
                          ServiceMetadata metadata,
-                         Map<String, AsyncMethodInfo> methodConfigs) {
+                         Map<String, AsyncMethodInfo> methodConfigs,
+                         ClassLoader interfaceClassLoader) {
+        super(proxyObject, serviceKey, serviceDescriptor, moduleModel, metadata, interfaceClassLoader);
 
-        super(proxyObject, serviceKey, serviceModel, referenceConfig, moduleModel, metadata);
         Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
 
         this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
@@ -101,7 +100,7 @@ public class ConsumerModel extends ServiceModel {
     public void initMethodModels() {
         Class<?>[] interfaceList;
         if (getProxyObject() == null) {
-            Class<?> serviceInterfaceClass = getReferenceConfig().getServiceInterfaceClass();
+            Class<?> serviceInterfaceClass = getServiceInterfaceClass();
             if (serviceInterfaceClass != null) {
                 interfaceList = new Class[]{serviceInterfaceClass};
             } else {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
index 89929a9b5b..ce8df358bb 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.config.context.ModuleConfigManager;
 
 import java.util.HashMap;
@@ -183,13 +184,13 @@ public class ModuleModel extends ScopeModel {
         serviceMetadata.setDefaultGroup(url.getGroup());
         serviceMetadata.setServiceInterfaceName(internalService.getName());
         serviceMetadata.setServiceType(internalService);
-        String servyceKey = URL.buildKey(internalService.getName(), url.getGroup(), url.getVersion());
-        serviceMetadata.setServiceKey(servyceKey);
+        String serviceKey = URL.buildKey(internalService.getName(), url.getGroup(), url.getVersion());
+        serviceMetadata.setServiceKey(serviceKey);
 
-        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), "jdk", serviceRepository.lookupService(serviceMetadata.getServiceInterfaceName()), null,
-            this, serviceMetadata, new HashMap<>());
+        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), "jdk", serviceRepository.lookupService(serviceMetadata.getServiceInterfaceName()),
+            this, serviceMetadata, new HashMap<>(0), ClassUtils.getClassLoader(internalService));
 
-        logger.info("Dynamically registering consumer model " + servyceKey + " into model " + this.getDesc());
+        logger.info("Dynamically registering consumer model " + serviceKey + " into model " + this.getDesc());
         serviceRepository.registerConsumer(consumerModel);
         return consumerModel;
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleServiceRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleServiceRepository.java
index 5a24a0bf8a..748b21deef 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleServiceRepository.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleServiceRepository.java
@@ -71,8 +71,12 @@ public class ModuleServiceRepository {
                                  ReferenceConfigBase<?> rc,
                                  Object proxy,
                                  ServiceMetadata serviceMetadata) {
-        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor, rc,
-            serviceMetadata, null);
+        ClassLoader classLoader = null;
+        if (rc != null) {
+            classLoader = rc.getInterfaceClassLoader();
+        }
+        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor,
+            serviceMetadata, null, classLoader);
         this.registerConsumer(consumerModel);
     }
 
@@ -89,8 +93,14 @@ public class ModuleServiceRepository {
                                  ServiceDescriptor serviceModel,
                                  ServiceConfigBase<?> serviceConfig,
                                  ServiceMetadata serviceMetadata) {
+        ClassLoader classLoader = null;
+        Class<?> cla = null;
+        if (serviceConfig != null) {
+            classLoader = serviceConfig.getInterfaceClassLoader();
+            cla = serviceConfig.getInterfaceClass();
+        }
         ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel,
-            serviceConfig, serviceMetadata);
+            serviceMetadata, classLoader);
         this.registerProvider(providerModel);
     }
 
@@ -100,14 +110,15 @@ public class ModuleServiceRepository {
     }
 
     public ServiceDescriptor registerService(ServiceDescriptor serviceDescriptor) {
-        return registerService(serviceDescriptor.getServiceInterfaceClass(),serviceDescriptor);
+        return registerService(serviceDescriptor.getServiceInterfaceClass(), serviceDescriptor);
     }
 
     public ServiceDescriptor registerService(Class<?> interfaceClazz) {
         ServiceDescriptor serviceDescriptor = new ReflectionServiceDescriptor(interfaceClazz);
-        return registerService(interfaceClazz,serviceDescriptor);
+        return registerService(interfaceClazz, serviceDescriptor);
     }
-    public ServiceDescriptor registerService(Class<?> interfaceClazz,ServiceDescriptor serviceDescriptor) {
+
+    public ServiceDescriptor registerService(Class<?> interfaceClazz, ServiceDescriptor serviceDescriptor) {
         List<ServiceDescriptor> serviceDescriptors = services.computeIfAbsent(interfaceClazz.getName(),
             k -> new CopyOnWriteArrayList<>());
         synchronized (serviceDescriptors) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
index a1d877269b..b30a30826e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.config.ServiceConfigBase;
 
 import java.lang.reflect.Method;
 import java.util.ArrayList;
@@ -36,11 +35,16 @@ public class ProviderModel extends ServiceModel {
     private final List<RegisterStatedURL> urls;
     private final Map<String, List<ProviderMethodModel>> methods = new HashMap<>();
 
+    /**
+     * The url of the reference service
+     */
+    private List<URL> serviceUrls = new ArrayList<URL>();
+
     public ProviderModel(String serviceKey,
                          Object serviceInstance,
-                         ServiceDescriptor serviceModel,
-                         ServiceConfigBase<?> serviceConfig) {
-        super(serviceInstance, serviceKey, serviceModel, serviceConfig);
+                         ServiceDescriptor serviceDescriptor,
+                         ClassLoader interfaceClassLoader) {
+        super(serviceInstance, serviceKey, serviceDescriptor, null, interfaceClassLoader);
         if (null == serviceInstance) {
             throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
         }
@@ -50,25 +54,25 @@ public class ProviderModel extends ServiceModel {
 
     public ProviderModel(String serviceKey,
                          Object serviceInstance,
-                         ServiceDescriptor serviceModel,
-                         ServiceConfigBase<?> serviceConfig,
-                         ServiceMetadata serviceMetadata) {
-        super(serviceInstance, serviceKey, serviceModel, serviceConfig, serviceMetadata);
+                         ServiceDescriptor serviceDescriptor,
+                         ServiceMetadata serviceMetadata,
+                         ClassLoader interfaceClassLoader) {
+        super(serviceInstance, serviceKey, serviceDescriptor, null, serviceMetadata, interfaceClassLoader);
         if (null == serviceInstance) {
             throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
         }
 
-        initMethod(serviceModel.getServiceInterfaceClass());
+        initMethod(serviceDescriptor.getServiceInterfaceClass());
         this.urls = new ArrayList<>(1);
     }
 
     public ProviderModel(String serviceKey,
                          Object serviceInstance,
                          ServiceDescriptor serviceModel,
-                         ServiceConfigBase<?> serviceConfig,
                          ModuleModel moduleModel,
-                         ServiceMetadata serviceMetadata) {
-        super(serviceInstance, serviceKey, serviceModel, serviceConfig, moduleModel, serviceMetadata);
+                         ServiceMetadata serviceMetadata,
+                         ClassLoader interfaceClassLoader) {
+        super(serviceInstance, serviceKey, serviceModel, moduleModel, serviceMetadata, interfaceClassLoader);
         if (null == serviceInstance) {
             throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
         }
@@ -163,6 +167,15 @@ public class ProviderModel extends ServiceModel {
         }
     }
 
+    public List<URL> getServiceUrls() {
+        return serviceUrls;
+    }
+
+    public void setServiceUrls(List<URL> urls) {
+        this.serviceUrls = urls;
+    }
+
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java
index 23bb654aca..16b1c8ca54 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java
@@ -30,38 +30,81 @@ public class ServiceModel {
     private Object proxyObject;
     private Callable<Void> destroyCaller;
     private ClassLoader classLoader;
+
+    private final ClassLoader interfaceClassLoader;
+
     private final ModuleModel moduleModel;
     private final ServiceDescriptor serviceModel;
-    private final AbstractInterfaceConfig config;
 
-    private ServiceMetadata serviceMetadata;
+    private AbstractInterfaceConfig config;
 
-    public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config) {
-        this(proxyObject, serviceKey, serviceModel, config, null);
-    }
+    private final ServiceMetadata serviceMetadata;
 
-    public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ServiceMetadata serviceMetadata) {
-        this(proxyObject, serviceKey, serviceModel, config, ScopeModelUtil.getModuleModel(config != null ? config.getScopeModel() : null), serviceMetadata);
+    public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, ModuleModel moduleModel, ClassLoader interfaceClassLoader) {
+        this(proxyObject, serviceKey, serviceModel, moduleModel, null, interfaceClassLoader);
     }
 
-    public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ModuleModel moduleModel, ServiceMetadata serviceMetadata) {
+    public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, ModuleModel moduleModel, ServiceMetadata serviceMetadata,
+                        ClassLoader interfaceClassLoader) {
         this.proxyObject = proxyObject;
         this.serviceKey = serviceKey;
         this.serviceModel = serviceModel;
-        this.moduleModel = moduleModel;
-        this.config = config;
+        this.moduleModel = ScopeModelUtil.getModuleModel(moduleModel);
         this.serviceMetadata = serviceMetadata;
+        this.interfaceClassLoader = interfaceClassLoader;
         if (serviceMetadata != null) {
             serviceMetadata.setServiceModel(this);
         }
-        if (config != null) {
-            this.classLoader = config.getInterfaceClassLoader();
+        if (interfaceClassLoader != null) {
+            this.classLoader = interfaceClassLoader;
         }
         if (this.classLoader == null) {
             this.classLoader = Thread.currentThread().getContextClassLoader();
         }
     }
 
+    @Deprecated
+    public AbstractInterfaceConfig getConfig() {
+        return config;
+    }
+
+    @Deprecated
+    public void setConfig(AbstractInterfaceConfig config) {
+        this.config = config;
+    }
+
+    /**
+     * ServiceModel should be decoupled from AbstractInterfaceConfig and removed in a future version
+     * @return
+     */
+    @Deprecated
+    public ReferenceConfigBase<?> getReferenceConfig() {
+        if (config == null) {
+            return null;
+        }
+        if (config instanceof ReferenceConfigBase) {
+            return (ReferenceConfigBase<?>) config;
+        } else {
+            throw new IllegalArgumentException("Current ServiceModel is not a ConsumerModel");
+        }
+    }
+
+    /**
+     * ServiceModel should be decoupled from AbstractInterfaceConfig and removed in a future version
+     * @return
+     */
+    @Deprecated
+    public ServiceConfigBase<?> getServiceConfig() {
+        if (config == null) {
+            return null;
+        }
+        if (config instanceof ServiceConfigBase) {
+            return (ServiceConfigBase<?>) config;
+        } else {
+            throw new IllegalArgumentException("Current ServiceModel is not a ProviderModel");
+        }
+    }
+
     public String getServiceKey() {
         return serviceKey;
     }
@@ -99,32 +142,6 @@ public class ServiceModel {
         return serviceModel.getServiceInterfaceClass();
     }
 
-    public AbstractInterfaceConfig getConfig() {
-        return config;
-    }
-
-    public ReferenceConfigBase<?> getReferenceConfig() {
-        if (config == null) {
-            return null;
-        }
-        if (config instanceof ReferenceConfigBase) {
-            return (ReferenceConfigBase<?>) config;
-        } else {
-            throw new IllegalArgumentException("Current ServiceModel is not a ConsumerModel");
-        }
-    }
-
-    public ServiceConfigBase<?> getServiceConfig() {
-        if (config == null) {
-            return null;
-        }
-        if (config instanceof ServiceConfigBase) {
-            return (ServiceConfigBase<?>) config;
-        } else {
-            throw new IllegalArgumentException("Current ServiceModel is not a ProviderModel");
-        }
-    }
-
     public void setServiceKey(String serviceKey) {
         this.serviceKey = serviceKey;
         if (serviceMetadata != null) {
@@ -156,6 +173,10 @@ public class ServiceModel {
         this.destroyCaller = destroyCaller;
     }
 
+    public ClassLoader getInterfaceClassLoader() {
+        return interfaceClassLoader;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) {
@@ -165,11 +186,11 @@ public class ServiceModel {
             return false;
         }
         ServiceModel that = (ServiceModel) o;
-        return Objects.equals(serviceKey, that.serviceKey) && Objects.equals(proxyObject, that.proxyObject) && Objects.equals(moduleModel, that.moduleModel) && Objects.equals(serviceModel, that.serviceModel) && Objects.equals(config, that.config) && Objects.equals(serviceMetadata, that.serviceMetadata);
+        return Objects.equals(serviceKey, that.serviceKey) && Objects.equals(proxyObject, that.proxyObject) && Objects.equals(destroyCaller, that.destroyCaller) && Objects.equals(classLoader, that.classLoader) && Objects.equals(interfaceClassLoader, that.interfaceClassLoader) && Objects.equals(moduleModel, that.moduleModel) && Objects.equals(serviceModel, that.serviceModel) && Objects.equals(serviceMetadata, that.serviceMetadata);
     }
 
     @Override
     public int hashCode() {
-        return Objects.hash(serviceKey, proxyObject, moduleModel, serviceModel, config, serviceMetadata);
+        return Objects.hash(serviceKey, proxyObject, destroyCaller, classLoader, interfaceClassLoader, moduleModel, serviceModel, serviceMetadata);
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/FrameworkServiceRepositoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/FrameworkServiceRepositoryTest.java
index 3969583b2d..03742dbc7a 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/FrameworkServiceRepositoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/FrameworkServiceRepositoryTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.support.DemoService;
 import org.apache.dubbo.rpc.support.DemoServiceImpl;
@@ -62,9 +63,8 @@ public class FrameworkServiceRepositoryTest {
         ProviderModel providerModel = new ProviderModel(serviceKey,
             new DemoServiceImpl(),
             serviceDescriptor,
-            null,
             moduleModel,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         frameworkServiceRepository.registerProvider(providerModel);
 
         ProviderModel lookupExportedService = frameworkServiceRepository.lookupExportedService(serviceKey);
@@ -89,8 +89,8 @@ public class FrameworkServiceRepositoryTest {
         Assertions.assertEquals(urls.get(0), url);
 
         ConsumerModel consumerModel = new ConsumerModel(
-            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor, null,
-            moduleModel, serviceMetadata, null);
+            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor,
+            moduleModel, serviceMetadata, null, ClassUtils.getClassLoader(DemoService.class));
         moduleServiceRepository.registerConsumer(consumerModel);
         List<ConsumerModel> consumerModels = frameworkServiceRepository.allConsumerModels();
         Assertions.assertEquals(consumerModels.size(), 1);
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ModuleServiceRepositoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ModuleServiceRepositoryTest.java
index ca91caad0d..a10bf7f250 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ModuleServiceRepositoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ModuleServiceRepositoryTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.rpc.support.DemoService;
 import org.apache.dubbo.rpc.support.DemoServiceImpl;
 
@@ -70,8 +71,8 @@ public class ModuleServiceRepositoryTest {
 
         // 2.test consumerModule
         ConsumerModel consumerModel = new ConsumerModel(
-            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor, null,
-            moduleModel, serviceMetadata, null);
+            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor,
+            moduleModel, serviceMetadata, null, ClassUtils.getClassLoader(DemoService.class));
         repository.registerConsumer(consumerModel);
 
         List<ConsumerModel> allReferredServices = repository.getReferredServices();
@@ -89,9 +90,8 @@ public class ModuleServiceRepositoryTest {
         ProviderModel providerModel = new ProviderModel(DemoService.class.getName(),
             new DemoServiceImpl(),
             serviceDescriptor,
-            null,
             moduleModel,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         repository.registerProvider(providerModel);
         List<ProviderModel> allExportedServices = repository.getExportedServices();
         Assertions.assertEquals(allExportedServices.size(), 1);
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ServiceRepositoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ServiceRepositoryTest.java
index 6daa425678..a5dda91d7e 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ServiceRepositoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/rpc/model/ServiceRepositoryTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.rpc.support.DemoService;
 import org.apache.dubbo.rpc.support.DemoServiceImpl;
 
@@ -63,17 +64,16 @@ public class ServiceRepositoryTest {
 
         // registerConsumer
         ConsumerModel consumerModel = new ConsumerModel(
-            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor, null,
-            moduleModel, serviceMetadata, null);
+            serviceMetadata.getServiceKey(), new DemoServiceImpl(), serviceDescriptor,
+            moduleModel, serviceMetadata, null, ClassUtils.getClassLoader(DemoService.class));
         repository.registerConsumer(consumerModel);
 
         // registerProvider
         ProviderModel providerModel = new ProviderModel(DemoService.class.getName(),
             new DemoServiceImpl(),
             serviceDescriptor,
-            null,
             moduleModel,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         repository.registerProvider(providerModel);
 
         // verify allProviderModels, allConsumerModels
diff --git a/dubbo-compiler/src/main/resources/DubboGrpcStub.mustache b/dubbo-compiler/src/main/resources/DubboGrpcStub.mustache
index 9677ae0c31..80456bcfa4 100644
--- a/dubbo-compiler/src/main/resources/DubboGrpcStub.mustache
+++ b/dubbo-compiler/src/main/resources/DubboGrpcStub.mustache
@@ -20,7 +20,6 @@
 {{/packageName}}
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.config.ReferenceConfigBase;
 
 import java.util.concurrent.TimeUnit;
 
@@ -44,15 +43,13 @@ private {{className}}() {}
 public static class Dubbo{{serviceName}}Stub implements I{{serviceName}} {
 
 protected URL url;
-protected ReferenceConfigBase<?> referenceConfig;
 
 protected {{serviceName}}Grpc.{{serviceName}}BlockingStub blockingStub;
 protected {{serviceName}}Grpc.{{serviceName}}FutureStub futureStub;
 protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
 
-public Dubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+public Dubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
 this.url = url;
-this.referenceConfig = referenceConfig;
 
 blockingStub = {{serviceName}}Grpc.newBlockingStub(channel).build(channel, callOptions);
 futureStub = {{serviceName}}Grpc.newFutureStub(channel).build(channel, callOptions);
@@ -120,8 +117,8 @@ stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
 {{/biStreamingMethods}}
 }
 
-public static Dubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
-return new Dubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+public static Dubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
+return new Dubbo{{serviceName}}Stub(channel, callOptions, url);
 }
 
 public interface I{{serviceName}} {
diff --git a/dubbo-compiler/src/main/resources/ReactorDubboGrpcStub.mustache b/dubbo-compiler/src/main/resources/ReactorDubboGrpcStub.mustache
index 07451eb468..952b615180 100644
--- a/dubbo-compiler/src/main/resources/ReactorDubboGrpcStub.mustache
+++ b/dubbo-compiler/src/main/resources/ReactorDubboGrpcStub.mustache
@@ -20,7 +20,6 @@
 {{/packageName}}
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.config.ReferenceConfigBase;
 
 import java.util.concurrent.TimeUnit;
 
@@ -40,8 +39,8 @@ import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
 public final class {{className}} {
 private {{className}}() {}
 
-public static ReactorDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
-return new ReactorDubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+public static ReactorDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
+return new ReactorDubbo{{serviceName}}Stub(channel, callOptions, url);
 }
 
 {{#javaDoc}}
@@ -50,13 +49,11 @@ return new ReactorDubbo{{serviceName}}Stub(channel, callOptions, url, referenceC
 public static final class ReactorDubbo{{serviceName}}Stub implements IReactor{{serviceName}} {
 
 protected URL url;
-protected ReferenceConfigBase<?> referenceConfig;
 
 protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
 
-public ReactorDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+public ReactorDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
 this.url = url;
-this.referenceConfig = referenceConfig;
 stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
 }
 
diff --git a/dubbo-compiler/src/main/resources/RxDubboGrpcStub.mustache b/dubbo-compiler/src/main/resources/RxDubboGrpcStub.mustache
index 3f49cc493c..f27a0a209b 100644
--- a/dubbo-compiler/src/main/resources/RxDubboGrpcStub.mustache
+++ b/dubbo-compiler/src/main/resources/RxDubboGrpcStub.mustache
@@ -20,7 +20,6 @@
 {{/packageName}}
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.config.ReferenceConfigBase;
 
 import java.util.concurrent.TimeUnit;
 
@@ -40,8 +39,8 @@ import static io.grpc.stub.ServerCalls.asyncBidiStreamingCall;
 public final class {{className}} {
 private {{className}}() {}
 
-public static RxDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
-return new RxDubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig);
+public static RxDubbo{{serviceName}}Stub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
+return new RxDubbo{{serviceName}}Stub(channel, callOptions, url);
 }
 
 {{#javaDoc}}
@@ -50,13 +49,11 @@ return new RxDubbo{{serviceName}}Stub(channel, callOptions, url, referenceConfig
 public static final class RxDubbo{{serviceName}}Stub implements IRx{{serviceName}} {
 
 protected URL url;
-protected ReferenceConfigBase<?> referenceConfig;
 
 protected {{serviceName}}Grpc.{{serviceName}}Stub stub;
 
-public RxDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url, ReferenceConfigBase<?> referenceConfig) {
+public RxDubbo{{serviceName}}Stub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
 this.url = url;
-this.referenceConfig = referenceConfig;
 stub = {{serviceName}}Grpc.newStub(channel).build(channel, callOptions);
 }
 
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 3b1fab9dde..0c57145d0f 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
@@ -60,6 +60,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.Callable;
 
 import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
@@ -274,8 +275,11 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
             } else {
                 serviceDescriptor = repository.registerService(interfaceClass);
             }
-            consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor, this,
-                getScopeModel(), serviceMetadata, createAsyncMethodInfo());
+            consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor,
+                getScopeModel(), serviceMetadata, createAsyncMethodInfo(), interfaceClassLoader);
+
+            // Compatible with dependencies on ServiceModel#getReferenceConfig() , and will be removed in a future version.
+            consumerModel.setConfig(this);
 
             repository.registerConsumer(consumerModel);
 
@@ -286,6 +290,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
             serviceMetadata.setTarget(ref);
             serviceMetadata.addAttribute(PROXY_CLASS_REF, ref);
 
+            consumerModel.setDestroyCaller(getDestroyRunner());
             consumerModel.setProxyObject(ref);
             consumerModel.initMethodModels();
 
@@ -670,4 +675,11 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
     public Invoker<?> getInvoker() {
         return invoker;
     }
+
+    public Callable<Void> getDestroyRunner() {
+        return () -> {
+            this.destroy();
+            return null;
+        };
+    }
 }
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 7123818e24..2238b868f4 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
@@ -56,6 +56,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.UUID;
+import java.util.concurrent.Callable;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -277,7 +278,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
         // init some null configuration.
         List<ConfigInitializer> configInitializers = this.getExtensionLoader(ConfigInitializer.class)
-                .getActivateExtension(URL.valueOf("configInitializer://", getScopeModel()), (String[]) null);
+            .getActivateExtension(URL.valueOf("configInitializer://", getScopeModel()), (String[]) null);
         configInitializers.forEach(e -> e.initServiceConfig(this));
 
         // if protocol is not injvm checkRegistry
@@ -367,34 +368,39 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         ModuleServiceRepository repository = getScopeModel().getServiceRepository();
         ServiceDescriptor serviceDescriptor;
         final boolean serverService = ref instanceof ServerService;
-        if(serverService){
-            serviceDescriptor=((ServerService) ref).getServiceDescriptor();
+        if (serverService) {
+            serviceDescriptor = ((ServerService) ref).getServiceDescriptor();
             repository.registerService(serviceDescriptor);
-        }else{
+        } else {
             serviceDescriptor = repository.registerService(getInterfaceClass());
         }
         providerModel = new ProviderModel(getUniqueServiceName(),
             ref,
             serviceDescriptor,
-            this,
             getScopeModel(),
-            serviceMetadata);
+            serviceMetadata, interfaceClassLoader);
+
+        // Compatible with dependencies on ServiceModel#getServiceConfig(), and will be removed in a future version
+        providerModel.setConfig(this);
 
+        providerModel.setDestroyCaller(getDestroyRunner());
         repository.registerProvider(providerModel);
 
         List<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
 
         for (ProtocolConfig protocolConfig : protocols) {
             String pathKey = URL.buildKey(getContextPath(protocolConfig)
-                    .map(p -> p + "/" + path)
-                    .orElse(path), group, version);
+                .map(p -> p + "/" + path)
+                .orElse(path), group, version);
             // stub service will use generated service name
-            if(!serverService) {
+            if (!serverService) {
                 // In case user specified path, register service one more time to map it to path.
                 repository.registerService(pathKey, interfaceClass);
             }
             doExportUrlsFor1Protocol(protocolConfig, registryURLs);
         }
+
+        providerModel.setServiceUrls(urls);
     }
 
     private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
@@ -464,7 +470,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             }
         }
 
-        if(ref instanceof ServerService){
+        if (ref instanceof ServerService) {
             map.put(PROXY_KEY, CommonConstants.NATIVE_STUB);
         }
 
@@ -554,9 +560,9 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
         // You can customize Configurator to append extra parameters
         if (this.getExtensionLoader(ConfiguratorFactory.class)
-                .hasExtension(url.getProtocol())) {
+            .hasExtension(url.getProtocol())) {
             url = this.getExtensionLoader(ConfiguratorFactory.class)
-                    .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
+                .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
         }
         url = url.setScopeModel(getScopeModel());
         url = url.setServiceModel(providerModel);
@@ -648,10 +654,10 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
      */
     private void exportLocal(URL url) {
         URL local = URLBuilder.from(url)
-                .setProtocol(LOCAL_PROTOCOL)
-                .setHost(LOCALHOST_VALUE)
-                .setPort(0)
-                .build();
+            .setProtocol(LOCAL_PROTOCOL)
+            .setHost(LOCALHOST_VALUE)
+            .setPort(0)
+            .build();
         local = local.setScopeModel(getScopeModel())
             .setServiceModel(providerModel);
         doExportUrl(local, false);
@@ -665,12 +671,12 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
      */
     private boolean isOnlyInJvm() {
         return getProtocols().size() == 1
-                && LOCAL_PROTOCOL.equalsIgnoreCase(getProtocols().get(0).getName());
+            && LOCAL_PROTOCOL.equalsIgnoreCase(getProtocols().get(0).getName());
     }
 
     private void postProcessConfig() {
         List<ConfigPostProcessor> configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class)
-                .getActivateExtension(URL.valueOf("configPostProcessor://", getScopeModel()), (String[]) null);
+            .getActivateExtension(URL.valueOf("configPostProcessor://", getScopeModel()), (String[]) null);
         configPostProcessors.forEach(component -> component.postProcessServiceConfig(this));
     }
 
@@ -753,7 +759,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     private static synchronized Integer findConfiguredPort(ProtocolConfig protocolConfig,
                                                            ProviderConfig provider,
                                                            ExtensionLoader<Protocol> extensionLoader,
-                                                           String name,Map<String, String> map) {
+                                                           String name, Map<String, String> map) {
         Integer portToBind;
 
         // parse bind port from environment
@@ -830,4 +836,10 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         }
     }
 
+    public Callable<Void> getDestroyRunner() {
+        return () -> {
+            this.unexport();
+            return null;
+        };
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java
index ec9c489043..d81e5b34cb 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/DefaultModuleDeployer.java
@@ -213,9 +213,7 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
 
             for (ConsumerModel consumerModel : consumerModels) {
                 try {
-                    if (consumerModel.getReferenceConfig() != null) {
-                        consumerModel.getReferenceConfig().destroy();
-                    } else if (consumerModel.getDestroyCaller() != null) {
+                    if (consumerModel.getDestroyCaller() != null) {
                         consumerModel.getDestroyCaller().call();
                     }
                 } catch (Throwable t) {
@@ -226,9 +224,7 @@ public class DefaultModuleDeployer extends AbstractDeployer<ModuleModel> impleme
             List<ProviderModel> exportedServices = serviceRepository.getExportedServices();
             for (ProviderModel providerModel : exportedServices) {
                 try {
-                    if (providerModel.getServiceConfig() != null) {
-                        providerModel.getServiceConfig().unexport();
-                    } else if (providerModel.getDestroyCaller() != null) {
+                    if (providerModel.getDestroyCaller() != null) {
                         providerModel.getDestroyCaller().call();
                     }
                 } catch (Throwable t) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizer.java
index f8f016d9ef..6e1f677b3c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/MetadataServiceURLParamsMetadataCustomizer.java
@@ -62,7 +62,7 @@ public class MetadataServiceURLParamsMetadataCustomizer implements ServiceInstan
         ProviderModel providerModel = serviceRepository.lookupExportedService(key);
         String metadataValue = "";
         if (providerModel != null) {
-            List<URL> metadataURLs = providerModel.getServiceConfig().getExportedUrls();
+            List<URL> metadataURLs = providerModel.getServiceUrls();
             if (CollectionUtils.isNotEmpty(metadataURLs)) {
                 metadataValue = getMetadataServiceParameter(metadataURLs.get(0));
             }
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
index 601f8ad76f..58b1a40175 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.qos.command.impl;
 
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.qos.DemoService;
 import org.apache.dubbo.qos.DemoServiceImpl;
@@ -83,7 +84,7 @@ public class LsTest {
             new DemoServiceImpl(),
             serviceDescriptor,
             null,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         repository.registerProvider(providerModel);
     }
 
@@ -96,8 +97,7 @@ public class LsTest {
         Map<String, AsyncMethodInfo> methodConfigs = new HashMap<>();
         ConsumerModel consumerModel = new ConsumerModel(
             serviceMetadata.getServiceKey(), null, serviceDescriptor,
-            referenceConfig, serviceMetadata, methodConfigs
-        );
+            serviceMetadata, methodConfigs, referenceConfig.getInterfaceClassLoader());
         repository.registerConsumer(consumerModel);
     }
 }
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
index d4a2a279bd..cba896f039 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.qos.command.impl;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.qos.DemoService;
 import org.apache.dubbo.qos.DemoServiceImpl;
 import org.apache.dubbo.qos.command.CommandContext;
@@ -90,8 +91,7 @@ public class OfflineTest {
             DemoService.class.getName(),
             new DemoServiceImpl(),
             serviceDescriptor,
-            null,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         registerStatedURL = new ProviderModel.RegisterStatedURL(
             URL.valueOf("dubbo://127.0.0.1:20880/" + DemoService.class.getName()),
             URL.valueOf("test://127.0.0.1:2181/" + RegistryService.class.getName()),
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
index b66312587b..189b7987f2 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.qos.command.impl;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.qos.DemoService;
 import org.apache.dubbo.qos.DemoServiceImpl;
 import org.apache.dubbo.qos.command.CommandContext;
@@ -90,8 +91,7 @@ public class OnlineTest {
             DemoService.class.getName(),
             new DemoServiceImpl(),
             serviceDescriptor,
-            null,
-            serviceMetadata);
+            serviceMetadata, ClassUtils.getClassLoader(DemoService.class));
         registerStatedURL = new ProviderModel.RegisterStatedURL(
             URL.valueOf("dubbo://127.0.0.1:20880/" + DemoService.class.getName()),
             URL.valueOf("test://127.0.0.1:2181/" + RegistryService.class.getName()),
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/ServiceCheckUtilsTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/ServiceCheckUtilsTest.java
index ab1509e06d..432e02536f 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/ServiceCheckUtilsTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/util/ServiceCheckUtilsTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.qos.command.util;
 
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.qos.DemoService;
 import org.apache.dubbo.qos.DemoServiceImpl;
@@ -64,8 +65,7 @@ public class ServiceCheckUtilsTest {
             url.getServiceKey(),
             demoServiceImpl,
             serviceDescriptor,
-            null,
-            new ServiceMetadata());
+            new ServiceMetadata(), ClassUtils.getClassLoader(DemoService.class));
         repository.registerProvider(providerModel);
 
         String url1 = "service-discovery-registry://127.0.0.1:2181/org.apache.dubbo.registry.RegistryService?application=dubbo-demo-api-provider&dubbo=2.0.2&pid=66099&registry=zookeeper&timestamp=1654588337653";
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
index 0101aece5b..48fe0deea3 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java
@@ -46,6 +46,7 @@ import java.util.concurrent.ThreadLocalRandom;
 
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
+import static org.apache.dubbo.common.constants.CommonConstants.PROXY_CLASS_REF;
 import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_KEY;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URLS_PROPERTY_NAME;
@@ -126,16 +127,29 @@ public class MetadataUtils {
                 + instance + ", but no metadata service can build from it.");
         }
 
+        URL url = urls.get(0);
+
         // Simply rely on the first metadata url, as stated in MetadataServiceURLBuilder.
         ApplicationModel applicationModel = instance.getApplicationModel();
         ModuleModel internalModel = applicationModel.getInternalModule();
-        ConsumerModel consumerModel = applicationModel.getInternalModule().registerInternalConsumer(MetadataService.class, urls.get(0));
+        ConsumerModel consumerModel = applicationModel.getInternalModule().registerInternalConsumer(MetadataService.class, url);
 
         Protocol protocol = applicationModel.getExtensionLoader(Protocol.class).getAdaptiveExtension();
-        Invoker<MetadataService> invoker = protocol.refer(MetadataService.class, urls.get(0));
+
+        url.setServiceModel(consumerModel);
+
+        Invoker<MetadataService> invoker = protocol.refer(MetadataService.class, url);
 
         ProxyFactory proxyFactory = applicationModel.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
-        return new ProxyHolder(consumerModel, proxyFactory.getProxy(invoker), internalModel);
+
+        MetadataService metadataService = proxyFactory.getProxy(invoker);
+
+        consumerModel.getServiceMetadata().setTarget(metadataService);
+        consumerModel.getServiceMetadata().addAttribute(PROXY_CLASS_REF, metadataService);
+        consumerModel.setProxyObject(metadataService);
+        consumerModel.initMethodModels();
+
+        return new ProxyHolder(consumerModel, metadataService, internalModel);
     }
 
     public static MetadataInfo getRemoteMetadata(String revision, List<ServiceInstance> instances, MetadataReport metadataReport) {
@@ -150,7 +164,6 @@ public class MetadataUtils {
                 metadataInfo = MetadataUtils.getMetadata(revision, instance, metadataReport);
             } else {
                 // change the instance used to communicate to avoid all requests route to the same instance
-                MetadataService metadataServiceProxy = null;
                 ProxyHolder proxyHolder = null;
                 try {
                     proxyHolder = MetadataUtils.referProxy(instance);
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 55bb92f01e..974c73aaac 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
@@ -109,8 +109,8 @@ public abstract class AbstractProxyFactory implements ProxyFactory {
     private <T> ClassLoader getClassLoader(Invoker<T> invoker) {
         ServiceModel serviceModel = invoker.getUrl().getServiceModel();
         ClassLoader classLoader = null;
-        if (serviceModel != null && serviceModel.getConfig() != null) {
-            classLoader = serviceModel.getConfig().getInterfaceClassLoader();
+        if (serviceModel != null && serviceModel.getInterfaceClassLoader() != null) {
+            classLoader = serviceModel.getInterfaceClassLoader();
         }
         if (classLoader == null) {
             classLoader = ClassUtils.getClassLoader();
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
index 38acb87247..c950d135bc 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
@@ -158,7 +158,7 @@ public class CallbackServiceCodec {
                     ServiceDescriptor serviceDescriptor = moduleModel.getServiceRepository().registerService(clazz);
                     ServiceMetadata serviceMetadata = new ServiceMetadata(clazz.getName() + "." + instid, exportUrl.getGroup(), exportUrl.getVersion(), clazz);
                     String serviceKey = BaseServiceMetadata.buildServiceKey(exportUrl.getPath(), group, exportUrl.getVersion());
-                    ProviderModel providerModel = new ProviderModel(serviceKey, inst, serviceDescriptor, null, moduleModel, serviceMetadata);
+                    ProviderModel providerModel = new ProviderModel(serviceKey, inst, serviceDescriptor, moduleModel, serviceMetadata, ClassUtils.getClassLoader(clazz));
                     moduleModel.getServiceRepository().registerProvider(providerModel);
 
                     exportUrl = exportUrl.setScopeModel(moduleModel);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
index ff7dd83242..2505dafeb0 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc.protocol.dubbo;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.Exporter;
@@ -87,8 +88,8 @@ public class ArgumentCallbackTest {
                 + "&retries=0"
                 + "&" + CALLBACK_INSTANCES_LIMIT_KEY + "=" + callbacks)
             .setScopeModel(ApplicationModel.defaultModel().getDefaultModule())
-            .setServiceModel(new ConsumerModel(IDemoService.class.getName(), null, null, null,
-            ApplicationModel.defaultModel().getDefaultModule(), null, null));
+            .setServiceModel(new ConsumerModel(IDemoService.class.getName(), null, null,
+                ApplicationModel.defaultModel().getDefaultModule(), null, null, ClassUtils.getClassLoader(IDemoService.class)));
 
         //      uncomment is unblock invoking
 //        serviceURL = serviceURL.addParameter("yyy."+Constants.ASYNC_KEY,String.valueOf(true));
@@ -111,13 +112,13 @@ public class ArgumentCallbackTest {
         } catch (Exception e) {
         }
     }
-    
+
     @Test
     public void TestCallbackNormalWithBindPort() throws Exception {
         initOrResetUrl(1, 10000000);
-        consumerUrl = serviceURL.addParameter(Constants.BIND_PORT_KEY,"7653");
+        consumerUrl = serviceURL.addParameter(Constants.BIND_PORT_KEY, "7653");
         initOrResetService();
-       
+
         final AtomicInteger count = new AtomicInteger(0);
 
         demoProxy.xxx(new IDemoCallback() {
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
index d7a7391d87..2223311578 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.rpc.protocol.grpc;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.config.ReferenceConfigBase;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
@@ -108,7 +107,7 @@ public class GrpcProtocol extends AbstractProxyProtocol {
         final Method dubboStubMethod;
         try {
             dubboStubMethod = enclosingClass.getDeclaredMethod("getDubboStub", Channel.class, CallOptions.class,
-                    URL.class, ReferenceConfigBase.class);
+                    URL.class);
         } catch (NoSuchMethodException e) {
             throw new IllegalArgumentException("Does not find getDubboStub in " + enclosingClass.getName() + ", please use the customized protoc-gen-dubbo-java to update the generated classes.");
         }
@@ -118,12 +117,10 @@ public class GrpcProtocol extends AbstractProxyProtocol {
 
         // CallOptions
         try {
-            ReferenceConfigBase<?> referenceConfig = url.getServiceModel().getReferenceConfig();
             @SuppressWarnings("unchecked") final T stub = (T) dubboStubMethod.invoke(null,
                     channel,
                     GrpcOptionsUtils.buildCallOptions(url),
-                    url,
-                    referenceConfig
+                    url
             );
             final Invoker<T> target = proxyFactory.getInvoker(stub, type, url);
             GrpcInvoker<T> grpcInvoker = new GrpcInvoker<>(type, url, target, channel);
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
index af410b8ba3..1e63f66fc4 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
@@ -74,8 +74,8 @@ public class GrpcProtocolTest {
         serviceMetadata.setServiceKey(URL.buildKey(DubboGreeterGrpc.IGreeter.class.getName(), null, null));
 
         Map<String, AsyncMethodInfo> methodConfigs = new HashMap<>();
-        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), null, serviceDescriptor, mockReferenceConfig,
-            serviceMetadata, methodConfigs);
+        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), null, serviceDescriptor,
+            serviceMetadata, methodConfigs, mockReferenceConfig.getInterfaceClassLoader());
 
         ApplicationModel.defaultModel().getDefaultModule().getServiceRepository().registerConsumer(consumerModel);
 
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/support/DubboGreeterGrpc.java b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/support/DubboGreeterGrpc.java
index a30962fa66..72a30d1ef8 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/support/DubboGreeterGrpc.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/support/DubboGreeterGrpc.java
@@ -38,16 +38,13 @@ public final class DubboGreeterGrpc {
     public static class DubboGreeterStub implements IGreeter {
 
         protected URL url;
-        protected ReferenceConfigBase<?> referenceConfig;
 
         protected GreeterGrpc.GreeterBlockingStub blockingStub;
         protected GreeterGrpc.GreeterFutureStub futureStub;
         protected GreeterGrpc.GreeterStub stub;
 
-        public DubboGreeterStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url,
-                                ReferenceConfigBase<?> referenceConfig) {
+        public DubboGreeterStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
             this.url = url;
-            this.referenceConfig = referenceConfig;
 
             blockingStub = GreeterGrpc.newBlockingStub(channel).build(channel, callOptions);
             futureStub = GreeterGrpc.newFutureStub(channel).build(channel, callOptions);
@@ -82,9 +79,8 @@ public final class DubboGreeterGrpc {
 
     }
 
-    public static DubboGreeterStub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url,
-                                                ReferenceConfigBase<?> referenceConfig) {
-        return new DubboGreeterStub(channel, callOptions, url, referenceConfig);
+    public static DubboGreeterStub getDubboStub(io.grpc.Channel channel, io.grpc.CallOptions callOptions, URL url) {
+        return new DubboGreeterStub(channel, callOptions, url);
     }
 
     public interface IGreeter {
diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmClassLoaderTest.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmClassLoaderTest.java
index 04e5b3bdd6..c91f50590e 100644
--- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmClassLoaderTest.java
+++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmClassLoaderTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.protocol.injvm;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.compiler.support.CtClassBuilder;
 import org.apache.dubbo.common.compiler.support.JavassistCompiler;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
@@ -105,8 +106,8 @@ public class InjvmClassLoaderTest {
 
         // refer consumer
         ServiceDescriptor consumerServiceDescriptor = moduleModel.getServiceRepository().registerService(clazz2);
-        ConsumerModel consumerModel = new ConsumerModel(clazz2.getName(), null, consumerServiceDescriptor, null,
-            ApplicationModel.defaultModel().getDefaultModule(), null, null);
+        ConsumerModel consumerModel = new ConsumerModel(clazz2.getName(), null, consumerServiceDescriptor,
+            ApplicationModel.defaultModel().getDefaultModule(), null, null, ClassUtils.getClassLoader(clazz2));
         consumerModel.setClassLoader(classLoader3);
         URL consumerUrl = url.setScopeModel(moduleModel).setServiceModel(consumerModel);
 
diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmDeepCopyTest.java b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmDeepCopyTest.java
index b8ea63c9bd..80aea35a02 100644
--- a/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmDeepCopyTest.java
+++ b/dubbo-rpc/dubbo-rpc-injvm/src/test/java/org/apache/dubbo/rpc/protocol/injvm/InjvmDeepCopyTest.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc.protocol.injvm;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
@@ -67,8 +68,8 @@ public class InjvmDeepCopyTest {
 
         // refer consumer
         ServiceDescriptor consumerServiceDescriptor = moduleModel.getServiceRepository().registerService(DemoInterface.class);
-        ConsumerModel consumerModel = new ConsumerModel(DemoInterface.class.getName(), null, consumerServiceDescriptor, null,
-            ApplicationModel.defaultModel().getDefaultModule(), null, null);
+        ConsumerModel consumerModel = new ConsumerModel(DemoInterface.class.getName(), null, consumerServiceDescriptor,
+            ApplicationModel.defaultModel().getDefaultModule(), null, null, ClassUtils.getClassLoader(DemoInterface.class));
         URL consumerUrl = url.setScopeModel(moduleModel).setServiceModel(consumerModel);
 
         DemoInterface stub = proxyFactory.getProxy(protocol.refer(DemoInterface.class, consumerUrl));
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
index 8887ddcda4..3065ad0bde 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.protocol.tri;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.stream.StreamObserver;
+import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
@@ -62,8 +63,7 @@ public class TripleProtocolTest {
             providerUrl.getServiceKey(),
             serviceImpl,
             serviceDescriptor,
-            null,
-            new ServiceMetadata());
+            new ServiceMetadata(), ClassUtils.getClassLoader(IGreeter.class));
         serviceRepository.registerProvider(providerModel);
         providerUrl = providerUrl.setServiceModel(providerModel);