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

[dubbo] branch 3.0 updated: Add ClassLoader Binding for ScopeModel (#8766)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 2bd54ae  Add ClassLoader Binding for ScopeModel (#8766)
2bd54ae is described below

commit 2bd54ae05492cc1a0ac8e6fcb3485cecc0c471e7
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Sat Sep 11 23:40:09 2021 +0800

    Add ClassLoader Binding for ScopeModel (#8766)
    
    * Add ClassLoader Binding for ScopeModel
    
    * Fix UT
    
    * Fix UT
    
    * Fix UT
    
    * Fix API
    
    * Fix UT
    
    * remove ExtensionLoader reload
    
    * Fix cl
    
    * Fix cl
    
    * Fix NPE
    
    * Fix override method
---
 .../apache/dubbo/common/config/Environment.java    |   7 +-
 .../common/config/PropertiesConfiguration.java     |  35 +++++-
 .../dubbo/common/extension/ExtensionDirector.java  |  12 +-
 .../dubbo/common/extension/ExtensionLoader.java    |  39 ++++---
 .../org/apache/dubbo/common/utils/ConfigUtils.java | 125 ++++++++-------------
 .../org/apache/dubbo/common/utils/PojoUtils.java   |   3 +-
 .../apache/dubbo/rpc/model/ApplicationModel.java   |  26 ++++-
 .../org/apache/dubbo/rpc/model/FrameworkModel.java |   9 +-
 .../org/apache/dubbo/rpc/model/ModuleModel.java    |  23 ++--
 .../org/apache/dubbo/rpc/model/ScopeModel.java     |  42 ++++++-
 .../common/extension/ExtensionDirectorTest.java    |   7 +-
 .../apache/dubbo/common/utils/ConfigUtilsTest.java |  60 ++++------
 .../dubbo/config/bootstrap/DubboBootstrap.java     |   8 +-
 .../dubbo/config/utils/ConfigValidationUtils.java  |   8 +-
 .../apache/dubbo/config/AbstractConfigTest.java    |   4 +-
 .../dubbo/config/ConfigCenterConfigTest.java       |  20 ++--
 .../apache/dubbo/config/ConsumerConfigTest.java    |  13 +--
 .../apache/dubbo/config/ReferenceConfigTest.java   |   9 +-
 .../dubbo/config/bootstrap/DubboBootstrapTest.java |   6 +-
 .../main/java/org/apache/dubbo/container/Main.java |   3 +-
 .../dubbo/container/spring/SpringContainer.java    |   3 +-
 .../dubbo/registry/client/InstanceAddressURL.java  |  12 ++
 .../client/OverrideInstanceAddressURL.java         |  45 ++++++++
 .../remoting/transport/netty4/NettyClient.java     |   6 +-
 .../apache/dubbo/rpc/protocol/AbstractInvoker.java |   8 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |   3 +-
 26 files changed, 320 insertions(+), 216 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
index 06d33cb..c54624d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
@@ -95,7 +95,7 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
                 path = CommonConstants.DEFAULT_DUBBO_MIGRATION_FILE;
             }
         }
-        this.localMigrationRule = ConfigUtils.loadMigrationRule(path);
+        this.localMigrationRule = ConfigUtils.loadMigrationRule(applicationModel.getClassLoaders(), path);
     }
 
     @Deprecated
@@ -313,4 +313,9 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
         return localMigrationRule;
     }
 
+    public void refreshClassLoaders() {
+        propertiesConfiguration.refresh();
+        loadMigrationRule();
+    }
+
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/PropertiesConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/PropertiesConfiguration.java
index efc6bb2..5e9b881 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/PropertiesConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/PropertiesConfiguration.java
@@ -31,7 +31,17 @@ import java.util.Set;
  */
 public class PropertiesConfiguration implements Configuration {
 
+    private Properties properties;
+    private final ApplicationModel applicationModel;
+
     public PropertiesConfiguration(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        refresh();
+    }
+
+    public void refresh() {
+        //load the default properties
+        properties = ConfigUtils.getProperties(applicationModel.getClassLoaders());
 
         ExtensionLoader<OrderedPropertiesProvider> propertiesProviderExtensionLoader = applicationModel.getExtensionLoader(OrderedPropertiesProvider.class);
         Set<String> propertiesProviderNames = propertiesProviderExtensionLoader.getSupportedExtensions();
@@ -48,23 +58,38 @@ public class PropertiesConfiguration implements Configuration {
             return b.priority() - a.priority();
         });
 
-        //load the default properties
-        Properties properties = ConfigUtils.getProperties();
 
         //override the properties.
         for (OrderedPropertiesProvider orderedPropertiesProvider :
-                orderedPropertiesProviders) {
+            orderedPropertiesProviders) {
             properties.putAll(orderedPropertiesProvider.initProperties());
         }
+    }
 
+    @Override
+    public String getProperty(String key) {
+        return properties.getProperty(key);
     }
 
     @Override
     public Object getInternalProperty(String key) {
-        return ConfigUtils.getProperty(key);
+        return properties.getProperty(key);
+    }
+
+    public void setProperty(String key, String value) {
+        properties.setProperty(key, value);
+    }
+
+    public String remove(String key) {
+        return (String) properties.remove(key);
+    }
+
+    @Deprecated
+    public void setProperties(Properties properties) {
+        this.properties = properties;
     }
 
     public Map<String, String> getProperties() {
-        return (Map) ConfigUtils.getProperties();
+        return (Map) properties;
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java
index 07d8cde..d65228a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.common.extension;
 
+import org.apache.dubbo.rpc.model.ScopeModel;
+
 import java.util.ArrayList;
 import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
@@ -34,10 +36,12 @@ public class ExtensionDirector implements ExtensionAccessor {
     private ExtensionDirector parent;
     private final ExtensionScope scope;
     private List<ExtensionPostProcessor> extensionPostProcessors = new ArrayList<>();
+    private ScopeModel scopeModel;
 
-    public ExtensionDirector(ExtensionDirector parent, ExtensionScope scope) {
+    public ExtensionDirector(ExtensionDirector parent, ExtensionScope scope, ScopeModel scopeModel) {
         this.parent = parent;
         this.scope = scope;
+        this.scopeModel = scopeModel;
     }
 
     public void addExtensionPostProcessor(ExtensionPostProcessor processor) {
@@ -107,7 +111,7 @@ public class ExtensionDirector implements ExtensionAccessor {
 
     private <T> ExtensionLoader<T> createExtensionLoader0(Class<T> type) {
         ExtensionLoader<T> loader;
-        extensionLoadersMap.putIfAbsent(type, new ExtensionLoader<T>(type, this));
+        extensionLoadersMap.putIfAbsent(type, new ExtensionLoader<T>(type, this, scopeModel));
         loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
         return loader;
     }
@@ -124,4 +128,8 @@ public class ExtensionDirector implements ExtensionAccessor {
     public ExtensionDirector getParent() {
         return parent;
     }
+
+    public void removeAllCachedLoader() {
+        // extensionLoadersMap.clear();
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
index c77ea58..760cfb3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java
@@ -37,6 +37,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.model.ModuleModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
 import org.apache.dubbo.rpc.model.ScopeModelAccessor;
 
 import java.io.BufferedReader;
@@ -130,6 +131,7 @@ public class ExtensionLoader<T> {
     private InstantiationStrategy instantiationStrategy;
     private Environment environment;
     private ActivateComparator activateComparator;
+    private ScopeModel scopeModel;
 
     public static void setLoadingStrategies(LoadingStrategy... strategies) {
         if (ArrayUtils.isNotEmpty(strategies)) {
@@ -161,7 +163,7 @@ public class ExtensionLoader<T> {
         return asList(strategies);
     }
 
-    ExtensionLoader(Class<?> type, ExtensionDirector extensionDirector) {
+    ExtensionLoader(Class<?> type, ExtensionDirector extensionDirector, ScopeModel scopeModel) {
         this.type = type;
         this.extensionDirector = extensionDirector;
         this.extensionPostProcessors = extensionDirector.getExtensionPostProcessors();
@@ -169,6 +171,7 @@ public class ExtensionLoader<T> {
         this.injector = (type == ExtensionInjector.class ? null : extensionDirector.getExtensionLoader(ExtensionInjector.class)
             .getAdaptiveExtension());
         this.activateComparator = new ActivateComparator(extensionDirector);
+        this.scopeModel = scopeModel;
     }
 
     private void initInstantiationStrategy() {
@@ -917,29 +920,28 @@ public class ExtensionLoader<T> {
                                boolean extensionLoaderClassLoaderFirst, boolean overridden, String... excludedPackages) {
         String fileName = dir + type;
         try {
-            Enumeration<java.net.URL> urls = null;
-            ClassLoader classLoader = findClassLoader();
+
+            Enumeration<java.net.URL> urls;
 
             // try to load from ExtensionLoader's ClassLoader first
             if (extensionLoaderClassLoaderFirst) {
                 ClassLoader extensionLoaderClassLoader = ExtensionLoader.class.getClassLoader();
                 if (ClassLoader.getSystemClassLoader() != extensionLoaderClassLoader) {
                     urls = extensionLoaderClassLoader.getResources(fileName);
+                    loadFromClass(extensionClasses, overridden, urls, extensionLoaderClassLoader, excludedPackages);
                 }
             }
 
-            if (urls == null || !urls.hasMoreElements()) {
-                if (classLoader != null) {
-                    urls = classLoader.getResources(fileName);
-                } else {
-                    urls = ClassLoader.getSystemResources(fileName);
-                }
-            }
+            // load from scope model
+            Set<ClassLoader> classLoaders = scopeModel.getClassLoaders();
 
-            if (urls != null) {
-                while (urls.hasMoreElements()) {
-                    java.net.URL resourceURL = urls.nextElement();
-                    loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
+            if (CollectionUtils.isEmpty(classLoaders)) {
+                urls = ClassLoader.getSystemResources(fileName);
+                loadFromClass(extensionClasses, overridden, urls, null, excludedPackages);
+            } else {
+                for (ClassLoader classLoader : classLoaders) {
+                    urls = classLoader.getResources(fileName);
+                    loadFromClass(extensionClasses, overridden, urls, classLoader, excludedPackages);
                 }
             }
         } catch (Throwable t) {
@@ -948,6 +950,15 @@ public class ExtensionLoader<T> {
         }
     }
 
+    private void loadFromClass(Map<String, Class<?>> extensionClasses, boolean overridden, Enumeration<java.net.URL> urls, ClassLoader classLoader, String[] excludedPackages) {
+        if (urls != null) {
+            while (urls.hasMoreElements()) {
+                java.net.URL resourceURL = urls.nextElement();
+                loadResource(extensionClasses, classLoader, resourceURL, overridden, excludedPackages);
+            }
+        }
+    }
+
     private void loadResource(Map<String, Class<?>> extensionClasses, ClassLoader classLoader,
                               java.net.URL resourceURL, boolean overridden, String... excludedPackages) {
         try {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
index 5a55ce2..17d1b84 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ConfigUtils.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.common.utils;
 import org.apache.dubbo.common.config.Configuration;
 import org.apache.dubbo.common.config.InmemoryConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.ExtensionDirector;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 
@@ -34,9 +34,11 @@ import java.lang.management.RuntimeMXBean;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Enumeration;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -48,8 +50,7 @@ public class ConfigUtils {
 
     private static final Logger logger = LoggerFactory.getLogger(ConfigUtils.class);
     private static Pattern VARIABLE_PATTERN = Pattern.compile(
-            "\\$\\s*\\{?\\s*([\\._0-9a-zA-Z]+)\\s*\\}?");
-    private static volatile Properties PROPERTIES;
+        "\\$\\s*\\{?\\s*([\\._0-9a-zA-Z]+)\\s*\\}?");
     private static int PID = -1;
 
     private ConfigUtils() {
@@ -61,15 +62,15 @@ public class ConfigUtils {
 
     public static boolean isEmpty(String value) {
         return StringUtils.isEmpty(value)
-                || "false".equalsIgnoreCase(value)
-                || "0".equalsIgnoreCase(value)
-                || "null".equalsIgnoreCase(value)
-                || "N/A".equalsIgnoreCase(value);
+            || "false".equalsIgnoreCase(value)
+            || "0".equalsIgnoreCase(value)
+            || "null".equalsIgnoreCase(value)
+            || "N/A".equalsIgnoreCase(value);
     }
 
     public static boolean isDefault(String value) {
         return "true".equalsIgnoreCase(value)
-                || "default".equalsIgnoreCase(value);
+            || "default".equalsIgnoreCase(value);
     }
 
     /**
@@ -85,11 +86,11 @@ public class ConfigUtils {
      * @param def  Default extension list
      * @return result extension list
      */
-    public static List<String> mergeValues(Class<?> type, String cfg, List<String> def) {
+    public static List<String> mergeValues(ExtensionDirector extensionDirector, Class<?> type, String cfg, List<String> def) {
         List<String> defaults = new ArrayList<String>();
         if (def != null) {
             for (String name : def) {
-                if (ExtensionLoader.getExtensionLoader(type).hasExtension(name)) {
+                if (extensionDirector.getExtensionLoader(type).hasExtension(name)) {
                     defaults.add(name);
                 }
             }
@@ -159,60 +160,18 @@ public class ConfigUtils {
     /**
      * Get dubbo properties.
      * It is not recommended to use this method to modify dubbo properties.
+     *
      * @return
      */
-    public static Properties getProperties() {
-        //TODO remove global instance PROPERTIES from ConfigUtils
-        if (PROPERTIES == null) {
-            synchronized (ConfigUtils.class) {
-                if (PROPERTIES == null) {
-                    String path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
-                    if (path == null || path.length() == 0) {
-                        path = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY);
-                        if (path == null || path.length() == 0) {
-                            path = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
-                        }
-                    }
-                    PROPERTIES = ConfigUtils.loadProperties(path, false, true);
-                }
+    public static Properties getProperties(Set<ClassLoader> classLoaders) {
+        String path = System.getProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
+        if (path == null || path.length() == 0) {
+            path = System.getenv(CommonConstants.DUBBO_PROPERTIES_KEY);
+            if (path == null || path.length() == 0) {
+                path = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
             }
         }
-        return PROPERTIES;
-    }
-
-    /**
-     * This method should be called before Dubbo starting.
-     * It is not recommended to use this method to modify dubbo properties.
-     */
-    public static void setProperties(Properties properties) {
-        PROPERTIES = properties;
-    }
-
-    /**
-     * This method should be called before Dubbo starting.
-     * It is not recommended to use this method to modify dubbo properties.
-     */
-    public static void addProperties(Properties properties) {
-        if (properties != null) {
-            getProperties().putAll(properties);
-        }
-    }
-
-    public static String getProperty(String key) {
-        return getProperty(key, null);
-    }
-
-    @SuppressWarnings({"unchecked", "rawtypes"})
-    public static String getProperty(String key, String defaultValue) {
-        String value = System.getProperty(key);
-        if (value != null && value.length() > 0) {
-            return value;
-        }
-        return getProperty(getProperties(), key, defaultValue);
-    }
-
-    public static String getProperty(Properties properties, String key, String defaultValue) {
-        return replaceProperty(properties.getProperty(key, defaultValue), (Map) properties);
+        return ConfigUtils.loadProperties(classLoaders, path, false, true);
     }
 
     /**
@@ -229,12 +188,12 @@ public class ConfigUtils {
         return value;
     }
 
-    public static Properties loadProperties(String fileName) {
-        return loadProperties(fileName, false, false);
+    public static Properties loadProperties(Set<ClassLoader> classLoaders, String fileName) {
+        return loadProperties(classLoaders, fileName, false, false);
     }
 
-    public static Properties loadProperties(String fileName, boolean allowMultiFile) {
-        return loadProperties(fileName, allowMultiFile, false);
+    public static Properties loadProperties(Set<ClassLoader> classLoaders, String fileName, boolean allowMultiFile) {
+        return loadProperties(classLoaders, fileName, allowMultiFile, false);
     }
 
     /**
@@ -249,7 +208,7 @@ public class ConfigUtils {
      * </ul>
      * @throws IllegalStateException not allow multi-file, but multi-file exist on class path.
      */
-    public static Properties loadProperties(String fileName, boolean allowMultiFile, boolean optional) {
+    public static Properties loadProperties(Set<ClassLoader> classLoaders, String fileName, boolean allowMultiFile, boolean optional) {
         Properties properties = new Properties();
         // add scene judgement in windows environment Fix 2557
         if (checkFileNameExist(fileName)) {
@@ -266,18 +225,23 @@ public class ConfigUtils {
             return properties;
         }
 
-        List<java.net.URL> list = new ArrayList<java.net.URL>();
+        Set<java.net.URL> set = new HashSet<java.net.URL>();
         try {
             Enumeration<java.net.URL> urls = ClassUtils.getClassLoader().getResources(fileName);
-            list = new ArrayList<java.net.URL>();
             while (urls.hasMoreElements()) {
-                list.add(urls.nextElement());
+                set.add(urls.nextElement());
+            }
+            for (ClassLoader classLoader : classLoaders) {
+                urls = classLoader.getResources(fileName);
+                while (urls.hasMoreElements()) {
+                    set.add(urls.nextElement());
+                }
             }
         } catch (Throwable t) {
             logger.warn("Fail to load " + fileName + " file: " + t.getMessage(), t);
         }
 
-        if (list.isEmpty()) {
+        if (set.isEmpty()) {
             if (!optional) {
                 logger.warn("No " + fileName + " found on the class path.");
             }
@@ -285,9 +249,9 @@ public class ConfigUtils {
         }
 
         if (!allowMultiFile) {
-            if (list.size() > 1) {
+            if (set.size() > 1) {
                 String errMsg = String.format("only 1 %s file is expected, but %d dubbo.properties files found on class path: %s",
-                        fileName, list.size(), list.toString());
+                    fileName, set.size(), set.toString());
                 logger.warn(errMsg);
             }
 
@@ -300,9 +264,9 @@ public class ConfigUtils {
             return properties;
         }
 
-        logger.info("load " + fileName + " properties file from " + list);
+        logger.info("load " + fileName + " properties file from " + set);
 
-        for (java.net.URL url : list) {
+        for (java.net.URL url : set) {
             try {
                 Properties p = new Properties();
                 InputStream input = url.openStream();
@@ -325,23 +289,28 @@ public class ConfigUtils {
         return properties;
     }
 
-    public static String loadMigrationRule(String fileName) {
+    public static String loadMigrationRule(Set<ClassLoader> classLoaders, String fileName) {
         String rawRule = "";
         if (checkFileNameExist(fileName)) {
             try {
                 try (FileInputStream input = new FileInputStream(fileName)) {
-                    rawRule = readString(input);
+                    return readString(input);
                 }
             } catch (Throwable e) {
                 logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);
             }
-            return rawRule;
         }
 
         try {
             InputStream is = ClassUtils.getClassLoader().getResourceAsStream(fileName);
             if (is != null) {
-                rawRule = readString(is);
+                return readString(is);
+            }
+            for (ClassLoader classLoader : classLoaders) {
+                is = classLoader.getResourceAsStream(fileName);
+                if (is != null) {
+                    return readString(is);
+                }
             }
         } catch (Throwable e) {
             logger.warn("Failed to load " + fileName + " file from " + fileName + "(ignore this file): " + e.getMessage(), e);
@@ -352,7 +321,7 @@ public class ConfigUtils {
     private static String readString(InputStream is) {
         StringBuilder stringBuilder = new StringBuilder();
         char[] buffer = new char[10];
-        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))){
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
             int n;
             while ((n = reader.read(buffer)) != -1) {
                 if (n < 10) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
index 889ada1..cd30737 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.common.utils;
 
+import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -73,7 +74,7 @@ public class PojoUtils {
     private static final Logger logger = LoggerFactory.getLogger(PojoUtils.class);
     private static final ConcurrentMap<String, Method> NAME_METHODS_CACHE = new ConcurrentHashMap<String, Method>();
     private static final ConcurrentMap<Class<?>, ConcurrentMap<String, Field>> CLASS_FIELD_CACHE = new ConcurrentHashMap<Class<?>, ConcurrentMap<String, Field>>();
-    private static final boolean GENERIC_WITH_CLZ = Boolean.parseBoolean(ConfigUtils.getProperty(CommonConstants.GENERIC_WITH_CLZ_KEY, "true"));
+    private static final boolean GENERIC_WITH_CLZ = Boolean.parseBoolean(ConfigurationUtils.getProperty(CommonConstants.GENERIC_WITH_CLZ_KEY, "true"));
     private static final List<Class<?>> CLASS_CAN_BE_STRING = Arrays.asList(Byte.class, Short.class, Integer.class,
         Long.class, Float.class, Double.class, Boolean.class, Character.class);
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index 9ec18fb..a08d39b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@ -31,6 +31,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * {@link ExtensionLoader}, {@code DubboBootstrap} and this class are at present designed to be
@@ -48,15 +49,16 @@ import java.util.Set;
 
 public class ApplicationModel extends ScopeModel {
     protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
-    public static final String NAME = "application";
+    private static final AtomicLong index = new AtomicLong(0);
+    public static final String NAME = "ApplicationModel";
     private static volatile ApplicationModel defaultInstance;
 
-    private volatile List<ModuleModel> moduleModels = Collections.synchronizedList(new ArrayList<>());
+    private final List<ModuleModel> moduleModels = Collections.synchronizedList(new ArrayList<>());
     private Environment environment;
     private ConfigManager configManager;
     private ServiceRepository serviceRepository;
 
-    private FrameworkModel frameworkModel;
+    private final FrameworkModel frameworkModel;
 
     private ModuleModel internalModule;
 
@@ -153,12 +155,13 @@ public class ApplicationModel extends ScopeModel {
         this.frameworkModel = frameworkModel;
         frameworkModel.addApplication(this);
         initialize();
+        this.modelName = NAME + "-" + index.getAndIncrement();
     }
 
     @Override
     protected void initialize() {
         super.initialize();
-        internalModule = new ModuleModel(this);
+        internalModule = new ModuleModel(this.modelName + "-internal", this);
         this.serviceRepository = new ServiceRepository(this);
 
         ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
@@ -299,7 +302,18 @@ public class ApplicationModel extends ScopeModel {
     }
 
     @Override
-    public String toString() {
-        return "ApplicationModel";
+    public void addClassLoader(ClassLoader classLoader) {
+        super.addClassLoader(classLoader);
+        if (environment != null) {
+            environment.refreshClassLoaders();
+        }
+    }
+
+    @Override
+    public void removeClassLoader(ClassLoader classLoader) {
+        super.removeClassLoader(classLoader);
+        if (environment != null) {
+            environment.refreshClassLoaders();
+        }
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
index 1948298..a23386e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
@@ -25,6 +25,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Model of dubbo framework, it can be shared with multiple applications.
@@ -33,6 +34,8 @@ public class FrameworkModel extends ScopeModel {
 
     protected static final Logger LOGGER = LoggerFactory.getLogger(FrameworkModel.class);
 
+    private static final AtomicLong index = new AtomicLong(0);
+    public static final String NAME = "FrameworkModel";
     private volatile static FrameworkModel defaultInstance;
 
     private static List<FrameworkModel> allInstances = Collections.synchronizedList(new ArrayList<>());
@@ -45,6 +48,7 @@ public class FrameworkModel extends ScopeModel {
     public FrameworkModel() {
         super(null, ExtensionScope.FRAMEWORK);
         initialize();
+        this.modelName = NAME + "-" + index.getAndIncrement();
     }
 
     @Override
@@ -120,9 +124,4 @@ public class FrameworkModel extends ScopeModel {
     public FrameworkServiceRepository getServiceRepository() {
         return serviceRepository;
     }
-
-    @Override
-    public String toString() {
-        return "FrameworkModel";
-    }
 }
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 5067589..494a987 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
@@ -23,6 +23,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.atomic.AtomicLong;
 
 /**
  * Model of a service module
@@ -30,15 +31,22 @@ import java.util.Set;
 public class ModuleModel extends ScopeModel {
     private static final Logger logger = LoggerFactory.getLogger(ModuleModel.class);
 
-    private String id;
+    private static final AtomicLong index = new AtomicLong(0);
+    public static final String NAME = "ModuleModel";
+
     private final ApplicationModel applicationModel;
     private ModuleServiceRepository serviceRepository;
 
     public ModuleModel(ApplicationModel applicationModel) {
+        this(NAME + "-" + index.getAndIncrement(), applicationModel);
+    }
+
+    public ModuleModel(String name, ApplicationModel applicationModel) {
         super(applicationModel, ExtensionScope.MODULE);
         this.applicationModel = applicationModel;
         applicationModel.addModule(this);
         initialize();
+        this.modelName = name;
     }
 
     @Override
@@ -101,17 +109,4 @@ public class ModuleModel extends ScopeModel {
     public ModuleServiceRepository getServiceRepository() {
         return serviceRepository;
     }
-
-    public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
-    }
-
-    @Override
-    public String toString() {
-        return "ModuleModel";
-    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
index 6cef351..aec14b7 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
@@ -20,7 +20,9 @@ import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.common.extension.ExtensionAccessor;
 import org.apache.dubbo.common.extension.ExtensionDirector;
 import org.apache.dubbo.common.extension.ExtensionScope;
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
 
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
@@ -29,6 +31,9 @@ import java.util.concurrent.ConcurrentHashMap;
 
 public abstract class ScopeModel implements ExtensionAccessor {
 
+    protected String modelName;
+    private Set<ClassLoader> classLoaders;
+
     private final ScopeModel parent;
     private final ExtensionScope scope;
 
@@ -54,11 +59,18 @@ public abstract class ScopeModel implements ExtensionAccessor {
      * </ol>
      */
     protected void initialize() {
-        this.extensionDirector = new ExtensionDirector(parent != null ? parent.getExtensionDirector() : null, scope);
+        this.extensionDirector = new ExtensionDirector(parent != null ? parent.getExtensionDirector() : null, scope, this);
         this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
         this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector);
         this.destroyListeners = new LinkedList<>();
         this.attribute = new ConcurrentHashMap<>();
+        this.classLoaders = new ConcurrentHashSet<>();
+
+        // Add Framework's ClassLoader by default
+        ClassLoader dubboClassLoader = ScopeModel.class.getClassLoader();
+        if (dubboClassLoader != null) {
+            this.addClassLoader(dubboClassLoader);
+        }
     }
 
     public void destroy() {
@@ -94,4 +106,32 @@ public abstract class ScopeModel implements ExtensionAccessor {
             processor.postProcessScopeModel(this);
         }
     }
+
+    public String getModelName() {
+        return modelName;
+    }
+
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public void addClassLoader(ClassLoader classLoader) {
+        this.classLoaders.add(classLoader);
+        if (parent != null) {
+            parent.addClassLoader(classLoader);
+        }
+        extensionDirector.removeAllCachedLoader();
+    }
+
+    public void removeClassLoader(ClassLoader classLoader) {
+        this.classLoaders.remove(classLoader);
+        if (parent != null) {
+            parent.removeClassLoader(classLoader);
+        }
+        extensionDirector.removeAllCachedLoader();
+    }
+
+    public Set<ClassLoader> getClassLoaders() {
+        return Collections.unmodifiableSet(classLoaders);
+    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
index 5a40936..0a68d06 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.common.extension.director.impl.TestModuleService;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.model.ModuleModel;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -48,9 +49,9 @@ public class ExtensionDirectorTest {
         // 2. Child ExtensionDirector can get extension instance from parent
         // 3. Parent ExtensionDirector can't get extension instance from child
 
-        ExtensionDirector fwExtensionDirector = new ExtensionDirector(null, ExtensionScope.FRAMEWORK);
-        ExtensionDirector appExtensionDirector = new ExtensionDirector(fwExtensionDirector, ExtensionScope.APPLICATION);
-        ExtensionDirector moduleExtensionDirector = new ExtensionDirector(appExtensionDirector, ExtensionScope.MODULE);
+        ExtensionDirector fwExtensionDirector = new ExtensionDirector(null, ExtensionScope.FRAMEWORK, FrameworkModel.defaultModel());
+        ExtensionDirector appExtensionDirector = new ExtensionDirector(fwExtensionDirector, ExtensionScope.APPLICATION, ApplicationModel.defaultModel());
+        ExtensionDirector moduleExtensionDirector = new ExtensionDirector(appExtensionDirector, ExtensionScope.MODULE, ApplicationModel.defaultModel().getDefaultModule());
 
         // test module extension loader
         FooFrameworkService testFwSrvFromModule = moduleExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
index 149ad6c..76f6977 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.config.CompositeConfiguration;
 import org.apache.dubbo.common.config.InmemoryConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.threadpool.ThreadPool;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
@@ -40,14 +41,15 @@ import static org.hamcrest.Matchers.is;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 public class ConfigUtilsTest {
+    private Properties properties;
+    
     @BeforeEach
     public void setUp() throws Exception {
-        ConfigUtils.setProperties(null);
+        properties = ConfigUtils.getProperties(Collections.emptySet());
     }
 
     @AfterEach
     public void tearDown() throws Exception {
-        ConfigUtils.setProperties(null);
     }
 
     @Test
@@ -78,27 +80,27 @@ public class ConfigUtilsTest {
 
     @Test
     public void testMergeValues() {
-        List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "aaa,bbb,default.custom",
+        List<String> merged = ConfigUtils.mergeValues(ApplicationModel.defaultModel().getExtensionDirector(), ThreadPool.class, "aaa,bbb,default.custom",
                 asList("fixed", "default.limited", "cached"));
         assertEquals(asList("fixed", "cached", "aaa", "bbb", "default.custom"), merged);
     }
 
     @Test
     public void testMergeValuesAddDefault() {
-        List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "aaa,bbb,default,zzz",
+        List<String> merged = ConfigUtils.mergeValues(ApplicationModel.defaultModel().getExtensionDirector(), ThreadPool.class, "aaa,bbb,default,zzz",
                 asList("fixed", "default.limited", "cached"));
         assertEquals(asList("aaa", "bbb", "fixed", "cached", "zzz"), merged);
     }
 
     @Test
     public void testMergeValuesDeleteDefault() {
-        List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "-default", asList("fixed", "default.limited", "cached"));
+        List<String> merged = ConfigUtils.mergeValues(ApplicationModel.defaultModel().getExtensionDirector(), ThreadPool.class, "-default", asList("fixed", "default.limited", "cached"));
         assertEquals(Collections.emptyList(), merged);
     }
 
     @Test
     public void testMergeValuesDeleteDefault_2() {
-        List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "-default,aaa", asList("fixed", "default.limited", "cached"));
+        List<String> merged = ConfigUtils.mergeValues(ApplicationModel.defaultModel().getExtensionDirector(), ThreadPool.class, "-default,aaa", asList("fixed", "default.limited", "cached"));
         assertEquals(asList("aaa"), merged);
     }
 
@@ -107,7 +109,7 @@ public class ConfigUtilsTest {
      */
     @Test
     public void testMergeValuesDelete() {
-        List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "-fixed,aaa", asList("fixed", "default.limited", "cached"));
+        List<String> merged = ConfigUtils.mergeValues(ApplicationModel.defaultModel().getExtensionDirector(), ThreadPool.class, "-fixed,aaa", asList("fixed", "default.limited", "cached"));
         assertEquals(asList("cached", "aaa"), merged);
     }
 
@@ -145,7 +147,7 @@ public class ConfigUtilsTest {
     public void testGetProperties1() throws Exception {
         try {
             System.setProperty(CommonConstants.DUBBO_PROPERTIES_KEY, "properties.load");
-            Properties p = ConfigUtils.getProperties();
+            Properties p = ConfigUtils.getProperties(Collections.emptySet());
             assertThat((String) p.get("a"), equalTo("12"));
             assertThat((String) p.get("b"), equalTo("34"));
             assertThat((String) p.get("c"), equalTo("56"));
@@ -157,46 +159,28 @@ public class ConfigUtilsTest {
     @Test
     public void testGetProperties2() throws Exception {
         System.clearProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
-        Properties p = ConfigUtils.getProperties();
+        Properties p = ConfigUtils.getProperties(Collections.emptySet());
         assertThat((String) p.get("dubbo"), equalTo("properties"));
     }
 
     @Test
-    public void testAddProperties() throws Exception {
-        Properties p = new Properties();
-        p.put("key1", "value1");
-        ConfigUtils.addProperties(p);
-        assertThat((String) ConfigUtils.getProperties().get("key1"), equalTo("value1"));
-    }
-
-    @Test
     public void testLoadPropertiesNoFile() throws Exception {
-        Properties p = ConfigUtils.loadProperties("notExisted", true);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "notExisted", true);
         Properties expected = new Properties();
         assertEquals(expected, p);
 
-        p = ConfigUtils.loadProperties("notExisted", false);
+        p = ConfigUtils.loadProperties(Collections.emptySet(), "notExisted", false);
         assertEquals(expected, p);
     }
 
     @Test
     public void testGetProperty() throws Exception {
-        assertThat(ConfigUtils.getProperty("dubbo"), equalTo("properties"));
+        assertThat(properties.getProperty("dubbo"), equalTo("properties"));
     }
 
     @Test
     public void testGetPropertyDefaultValue() throws Exception {
-        assertThat(ConfigUtils.getProperty("not-exist", "default"), equalTo("default"));
-    }
-
-    @Test
-    public void testGetPropertyFromSystem() throws Exception {
-        try {
-            System.setProperty("dubbo", "system");
-            assertThat(ConfigUtils.getProperty("dubbo"), equalTo("system"));
-        } finally {
-            System.clearProperty("dubbo");
-        }
+        assertThat(properties.getProperty("not-exist", "default"), equalTo("default"));
     }
 
     @Test
@@ -211,13 +195,13 @@ public class ConfigUtilsTest {
 
     @Test
     public void testLoadProperties() throws Exception {
-        Properties p = ConfigUtils.loadProperties("dubbo.properties");
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "dubbo.properties");
         assertThat((String)p.get("dubbo"), equalTo("properties"));
     }
 
     @Test
     public void testLoadPropertiesOneFile() throws Exception {
-        Properties p = ConfigUtils.loadProperties("properties.load", false);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "properties.load", false);
 
         Properties expected = new Properties();
         expected.put("a", "12");
@@ -229,7 +213,7 @@ public class ConfigUtilsTest {
 
     @Test
     public void testLoadPropertiesOneFileAllowMulti() throws Exception {
-        Properties p = ConfigUtils.loadProperties("properties.load", true);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "properties.load", true);
 
         Properties expected = new Properties();
         expected.put("a", "12");
@@ -241,7 +225,7 @@ public class ConfigUtilsTest {
 
     @Test
     public void testLoadPropertiesOneFileNotRootPath() throws Exception {
-        Properties p = ConfigUtils.loadProperties("META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool", false);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool", false);
 
         Properties expected = new Properties();
         expected.put("fixed", "org.apache.dubbo.common.threadpool.support.fixed.FixedThreadPool");
@@ -257,7 +241,7 @@ public class ConfigUtilsTest {
     @Test
     public void testLoadPropertiesMultiFileNotRootPathException() throws Exception {
         try {
-            ConfigUtils.loadProperties("META-INF/services/org.apache.dubbo.common.status.StatusChecker", false);
+            ConfigUtils.loadProperties(Collections.emptySet(), "META-INF/services/org.apache.dubbo.common.status.StatusChecker", false);
             Assertions.fail();
         } catch (IllegalStateException expected) {
             assertThat(expected.getMessage(), containsString("only 1 META-INF/services/org.apache.dubbo.common.status.StatusChecker file is expected, but 2 dubbo.properties files found on class path:"));
@@ -267,7 +251,7 @@ public class ConfigUtilsTest {
     @Test
     public void testLoadPropertiesMultiFileNotRootPath() throws Exception {
 
-        Properties p = ConfigUtils.loadProperties("META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker", true);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker", true);
 
         Properties expected = new Properties();
         expected.put("memory", "org.apache.dubbo.common.status.support.MemoryStatusChecker");
@@ -284,7 +268,7 @@ public class ConfigUtilsTest {
 
     @Test
     public void testPropertiesWithStructedValue() throws Exception {
-        Properties p = ConfigUtils.loadProperties("parameters.properties", false);
+        Properties p = ConfigUtils.loadProperties(Collections.emptySet(), "parameters.properties", false);
 
         Properties expected = new Properties();
         expected.put("dubbo.parameters", "[{a:b},{c_.d: r*}]");
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index 5c71923..97e8abb 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -31,7 +31,6 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
 import org.apache.dubbo.common.utils.ArrayUtils;
 import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.AbstractConfig;
 import org.apache.dubbo.config.ApplicationConfig;
@@ -247,7 +246,6 @@ public final class DubboBootstrap {
      */
     @Deprecated
     public static void reset(boolean destroy) {
-        ConfigUtils.setProperties(null);
         DubboBootstrap.ignoreConfigState = true;
         if (destroy) {
             if (instance != null) {
@@ -1061,8 +1059,8 @@ public final class DubboBootstrap {
                 try {
                     // add default name config (same as id), e.g. dubbo.protocols.rest.port=1234
                     key = DUBBO + "." + AbstractConfig.getPluralTagName(cls) + "." + id + ".name";
-                    if (ConfigUtils.getProperties().getProperty(key) == null) {
-                        ConfigUtils.getProperties().setProperty(key, id);
+                    if (applicationModel.getApplicationEnvironment().getPropertiesConfiguration().getProperty(key) == null) {
+                        applicationModel.getApplicationEnvironment().getPropertiesConfiguration().setProperty(key, id);
                         addDefaultNameConfig = true;
                     }
 
@@ -1073,7 +1071,7 @@ public final class DubboBootstrap {
                     throw new IllegalStateException("load config failed, id: " + id + ", type:" + cls.getSimpleName());
                 } finally {
                     if (addDefaultNameConfig && key != null) {
-                        ConfigUtils.getProperties().remove(key);
+                        applicationModel.getApplicationEnvironment().getPropertiesConfiguration().remove(key);
                     }
                 }
             }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
index b361957..298750e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.utils;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.config.PropertiesConfiguration;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.serialize.Serialization;
@@ -63,6 +64,7 @@ import org.apache.dubbo.rpc.cluster.LoadBalance;
 import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 import org.apache.dubbo.rpc.support.MockInvoker;
 
 import java.net.InetAddress;
@@ -464,11 +466,13 @@ public class ConfigValidationUtils {
         }
 
         // backward compatibility
-        String wait = ConfigUtils.getProperty(SHUTDOWN_WAIT_KEY);
+        ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(config.getScopeModel());
+        PropertiesConfiguration configuration = applicationModel.getApplicationEnvironment().getPropertiesConfiguration();
+        String wait = configuration.getProperty(SHUTDOWN_WAIT_KEY);
         if (wait != null && wait.trim().length() > 0) {
             System.setProperty(SHUTDOWN_WAIT_KEY, wait.trim());
         } else {
-            wait = ConfigUtils.getProperty(SHUTDOWN_WAIT_SECONDS_KEY);
+            wait = configuration.getProperty(SHUTDOWN_WAIT_SECONDS_KEY);
             if (wait != null && wait.trim().length() > 0) {
                 System.setProperty(SHUTDOWN_WAIT_SECONDS_KEY, wait.trim());
             }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index 32864f2..7f03914 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -16,7 +16,6 @@
  */
 package org.apache.dubbo.config;
 
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.api.Greeting;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
@@ -390,7 +389,7 @@ public class AbstractConfigTest {
 
             Properties properties = new Properties();
             properties.load(this.getClass().getResourceAsStream("/dubbo.properties"));
-            ConfigUtils.setProperties(properties);
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperties(properties);
 
             overrideConfig.refresh();
 
@@ -400,7 +399,6 @@ public class AbstractConfigTest {
             //Assertions.assertEquals("properties", overrideConfig.getUseKeyAsProperty());
         } finally {
             ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
-            ConfigUtils.setProperties(null);
         }
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
index 427a265..92a7282 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
@@ -18,7 +18,6 @@
 package org.apache.dubbo.config;
 
 
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -30,7 +29,6 @@ import org.junit.jupiter.api.Test;
 
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 
@@ -164,11 +162,10 @@ public class ConfigCenterConfigTest {
     @Test
     public void testOverrideConfigByDubboProps() {
 
+        ApplicationModel.defaultModel().getDefaultModule();
         // Config instance has id, dubbo props has no id
-        Map props = new HashMap();
-        props.put("dubbo.config-center.check", "false");
-        props.put("dubbo.config-center.timeout", "1234");
-        ConfigUtils.getProperties().putAll(props);
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.config-center.check", "false");
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.config-center.timeout", "1234");
 
         try {
             // Config instance has id
@@ -186,7 +183,7 @@ public class ConfigCenterConfigTest {
             Assertions.assertEquals(3000L, configCenter.getTimeout());
             Assertions.assertEquals(false, configCenter.isCheck());
         } finally {
-            props.keySet().forEach(ConfigUtils.getProperties()::remove);
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().refresh();
         }
     }
 
@@ -221,11 +218,10 @@ public class ConfigCenterConfigTest {
     @Test
     public void testOverrideConfigByDubboPropsWithId() {
 
+        ApplicationModel.defaultModel().getDefaultModule();
         // Config instance has id, dubbo props has id
-        Map props = new HashMap();
-        props.put("dubbo.config-centers.configcenterA.check", "false");
-        props.put("dubbo.config-centers.configcenterA.timeout", "1234");
-        ConfigUtils.getProperties().putAll(props);
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.config-centers.configcenterA.check", "false");
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.config-centers.configcenterA.timeout", "1234");
 
         try {
             // Config instance has id
@@ -244,7 +240,7 @@ public class ConfigCenterConfigTest {
             Assertions.assertEquals(3000L, configCenter.getTimeout());
             Assertions.assertEquals(false, configCenter.isCheck());
         } finally {
-            props.keySet().forEach(ConfigUtils.getProperties()::remove);
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().refresh();
         }
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
index 313fa71..2e06f0d 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
@@ -17,7 +17,6 @@
 
 package org.apache.dubbo.config;
 
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -28,7 +27,6 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
@@ -195,11 +193,10 @@ public class ConsumerConfigTest {
 
     @Test
     public void testOverrideConfigByDubboProps() {
-        Map props = new HashMap();
-        props.put("dubbo.consumers.consumerA.check", "false");
-        props.put("dubbo.consumers.consumerA.group", "demo");
-        props.put("dubbo.consumers.consumerA.threads", "10");
-        ConfigUtils.getProperties().putAll(props);
+        ApplicationModel.defaultModel().getDefaultModule();
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.consumers.consumerA.check", "false");
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.consumers.consumerA.group", "demo");
+        ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().setProperty("dubbo.consumers.consumerA.threads", "10");
 
         try {
             ConsumerConfig consumerConfig = new ConsumerConfig();
@@ -219,7 +216,7 @@ public class ConsumerConfigTest {
             Assertions.assertEquals("groupA", consumerConfig.getGroup());
             Assertions.assertEquals(10, consumerConfig.getThreads());
         } finally {
-            props.keySet().forEach(ConfigUtils.getProperties()::remove);
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().refresh();
         }
     }
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index e29f75a..34129dd 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -826,8 +826,8 @@ public class ReferenceConfigTest {
 
         String basePath = DemoService.class.getProtectionDomain().getCodeSource().getLocation().getFile();
         basePath = java.net.URLDecoder.decode(basePath, "UTF-8");
-        TestClassLoader classLoader1 = new TestClassLoader(basePath);
-        TestClassLoader classLoader2 = new TestClassLoader(basePath);
+        TestClassLoader classLoader1 = new TestClassLoader(Thread.currentThread().getContextClassLoader(), basePath);
+        TestClassLoader classLoader2 = new TestClassLoader(Thread.currentThread().getContextClassLoader(), basePath);
 
         Class<?> class1 = classLoader1.loadClass(DemoService.class.getName(), false);
         Class<?> class2 = classLoader2.loadClass(DemoService.class.getName(), false);
@@ -962,7 +962,8 @@ public class ReferenceConfigTest {
     private static class TestClassLoader extends ClassLoader {
         private String basePath;
 
-        public TestClassLoader(String basePath) {
+        public TestClassLoader(ClassLoader parent, String basePath) {
+            super(parent);
             this.basePath = basePath;
         }
 
@@ -983,7 +984,7 @@ public class ReferenceConfigTest {
                 return loadedClass;
             } else {
                 try {
-                    if (name.startsWith("org.apache.dubbo.config")) {
+                    if (name.equals("org.apache.dubbo.config.api.DemoService") || name.equals("org.apache.dubbo.config.api.DemoService$InnerClass")) {
                         Class<?> aClass = this.findClass(name);
                         if (resolve) {
                             this.resolveClass(aClass);
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
index 7ee63af..0abaa22 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.config.bootstrap;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.url.component.ServiceConfigURL;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.config.AbstractInterfaceConfig;
 import org.apache.dubbo.config.ApplicationConfig;
@@ -123,21 +122,20 @@ public class DubboBootstrapTest {
     @Test
     public void compatibleApplicationShutdown() {
         try {
-            ConfigUtils.setProperties(null);
             System.clearProperty(SHUTDOWN_WAIT_KEY);
             System.clearProperty(SHUTDOWN_WAIT_SECONDS_KEY);
 
             writeDubboProperties(SHUTDOWN_WAIT_KEY, "100");
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().refresh();
             ConfigValidationUtils.validateApplicationConfig(new ApplicationConfig("demo"));
             Assertions.assertEquals("100", System.getProperty(SHUTDOWN_WAIT_KEY));
 
             System.clearProperty(SHUTDOWN_WAIT_KEY);
-            ConfigUtils.setProperties(null);
             writeDubboProperties(SHUTDOWN_WAIT_SECONDS_KEY, "1000");
+            ApplicationModel.defaultModel().getApplicationEnvironment().getPropertiesConfiguration().refresh();
             ConfigValidationUtils.validateApplicationConfig(new ApplicationConfig("demo"));
             Assertions.assertEquals("1000", System.getProperty(SHUTDOWN_WAIT_SECONDS_KEY));
         } finally {
-            ConfigUtils.setProperties(null);
             System.clearProperty("dubbo.application.name");
             System.clearProperty(SHUTDOWN_WAIT_KEY);
             System.clearProperty(SHUTDOWN_WAIT_SECONDS_KEY);
diff --git a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java
index c0f1c9b..b43d340 100644
--- a/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java
+++ b/dubbo-container/dubbo-container-api/src/main/java/org/apache/dubbo/container/Main.java
@@ -20,7 +20,6 @@ import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ArrayUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
 
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -54,7 +53,7 @@ public class Main {
     public static void main(String[] args) {
         try {
             if (ArrayUtils.isEmpty(args)) {
-                String config = ConfigUtils.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName());
+                String config = System.getProperty(CONTAINER_KEY, LOADER.getDefaultExtensionName());
                 args = COMMA_SPLIT_PATTERN.split(config);
             }
 
diff --git a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java
index 390a57a..e3c0040 100644
--- a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java
+++ b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.container.spring;
 
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.container.Container;
 
@@ -42,7 +41,7 @@ public class SpringContainer implements Container {
 
     @Override
     public void start() {
-        String configPath = ConfigUtils.getProperty(SPRING_CONFIG);
+        String configPath = System.getProperty(SPRING_CONFIG);
         if (StringUtils.isEmpty(configPath)) {
             configPath = DEFAULT_SPRING_CONFIG;
         }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
index 94e96f8..c48bbbc 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
@@ -23,6 +23,8 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
 import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.model.ScopeModel;
 import org.apache.dubbo.rpc.model.ServiceModel;
 
@@ -497,6 +499,16 @@ public class InstanceAddressURL extends URL {
     }
 
     @Override
+    public FrameworkModel getOrDefaultFrameworkModel() {
+        return instance.getOrDefaultApplicationModel().getFrameworkModel();
+    }
+
+    @Override
+    public ApplicationModel getOrDefaultApplicationModel() {
+        return instance.getOrDefaultApplicationModel();
+    }
+
+    @Override
     public ServiceModel getServiceModel() {
         return RpcContext.getServiceContext().getConsumerUrl().getServiceModel();
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/OverrideInstanceAddressURL.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/OverrideInstanceAddressURL.java
index cc228d2..25e4e8c 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/OverrideInstanceAddressURL.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/OverrideInstanceAddressURL.java
@@ -21,10 +21,15 @@ import org.apache.dubbo.common.url.component.URLAddress;
 import org.apache.dubbo.common.url.component.URLParam;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
 public class OverrideInstanceAddressURL extends InstanceAddressURL {
@@ -265,6 +270,46 @@ public class OverrideInstanceAddressURL extends InstanceAddressURL {
     }
 
     @Override
+    public String getRemoteApplication() {
+        return originUrl.getRemoteApplication();
+    }
+
+    @Override
+    public String getSide() {
+        return originUrl.getSide();
+    }
+
+    @Override
+    public ScopeModel getScopeModel() {
+        return originUrl.getScopeModel();
+    }
+
+    @Override
+    public FrameworkModel getOrDefaultFrameworkModel() {
+        return originUrl.getOrDefaultFrameworkModel();
+    }
+
+    @Override
+    public ApplicationModel getOrDefaultApplicationModel() {
+        return originUrl.getOrDefaultApplicationModel();
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return originUrl.getServiceModel();
+    }
+
+    @Override
+    public Set<String> getProviderFirstParams() {
+        return originUrl.getProviderFirstParams();
+    }
+
+    @Override
+    public void setProviderFirstParams(Set<String> providerFirstParams) {
+        originUrl.setProviderFirstParams(providerFirstParams);
+    }
+
+    @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (o == null || getClass() != o.getClass()) return false;
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java
index 3d5ff1b..d44c428 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyClient.java
@@ -18,9 +18,9 @@ package org.apache.dubbo.remoting.transport.netty4;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.remoting.ChannelHandler;
 import org.apache.dubbo.remoting.Constants;
@@ -118,9 +118,9 @@ public class NettyClient extends AbstractClient {
                         .addLast("client-idle-handler", new IdleStateHandler(heartbeatInterval, 0, 0, MILLISECONDS))
                         .addLast("handler", nettyClientHandler);
 
-                String socksProxyHost = ConfigUtils.getProperty(SOCKS_PROXY_HOST);
+                String socksProxyHost = ConfigurationUtils.getProperty(getUrl().getOrDefaultApplicationModel(), SOCKS_PROXY_HOST);
                 if(socksProxyHost != null) {
-                    int socksProxyPort = Integer.parseInt(ConfigUtils.getProperty(SOCKS_PROXY_PORT, DEFAULT_SOCKS_PROXY_PORT));
+                    int socksProxyPort = Integer.parseInt(ConfigurationUtils.getProperty(getUrl().getOrDefaultApplicationModel(), SOCKS_PROXY_PORT, DEFAULT_SOCKS_PROXY_PORT));
                     Socks5ProxyHandler socks5ProxyHandler = new Socks5ProxyHandler(new InetSocketAddress(socksProxyHost, socksProxyPort));
                     ch.pipeline().addFirst(socks5ProxyHandler);
                 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
index 282e1bc..13ff94b 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java
@@ -51,6 +51,7 @@ import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
 
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
 import static org.apache.dubbo.remoting.Constants.DEFAULT_REMOTING_SERIALIZATION;
 import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
 import static org.apache.dubbo.rpc.Constants.SERIALIZATION_ID_KEY;
@@ -269,7 +270,12 @@ public abstract class AbstractInvoker<T> implements Invoker<T> {
              * must call {@link java.util.concurrent.CompletableFuture#get(long, TimeUnit)} because
              * {@link java.util.concurrent.CompletableFuture#get()} was proved to have serious performance drop.
              */
-            asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
+            Object timeout = invocation.get(TIMEOUT_KEY);
+            if (timeout instanceof Integer) {
+                asyncResult.get((Integer) timeout, TimeUnit.MILLISECONDS);
+            } else {
+                asyncResult.get(Integer.MAX_VALUE, TimeUnit.MILLISECONDS);
+            }
         } catch (InterruptedException e) {
             throw new RpcException("Interrupted unexpectedly while waiting for remote result to return! method: " +
                     invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 2c4a8a1..bb449b1 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -24,7 +24,6 @@ import org.apache.dubbo.common.serialize.support.SerializableClassRegistry;
 import org.apache.dubbo.common.serialize.support.SerializationOptimizer;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.remoting.Channel;
@@ -435,7 +434,7 @@ public class DubboProtocol extends AbstractProtocol {
              * The xml configuration should have a higher priority than properties.
              */
             String shareConnectionsStr = url.getParameter(SHARE_CONNECTIONS_KEY, (String) null);
-            connections = Integer.parseInt(StringUtils.isBlank(shareConnectionsStr) ? ConfigUtils.getProperty(SHARE_CONNECTIONS_KEY,
+            connections = Integer.parseInt(StringUtils.isBlank(shareConnectionsStr) ? ConfigurationUtils.getProperty(url.getOrDefaultApplicationModel(), SHARE_CONNECTIONS_KEY,
                     DEFAULT_SHARE_CONNECTIONS) : shareConnectionsStr);
             shareClients = getSharedClient(url, connections);
         }