You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by ky...@apache.org on 2021/08/26 13:57:44 UTC

[dubbo] branch 3.0-multi-instances updated: Add ScopeModel and ScopeBeanFactory, fix extension initialization of XxxConfig

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

kylixs pushed a commit to branch 3.0-multi-instances
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.0-multi-instances by this push:
     new 2072b41  Add ScopeModel and ScopeBeanFactory, fix extension initialization of XxxConfig
2072b41 is described below

commit 2072b413a4137e2abe1f48374de97d335b3585e3
Author: gongdewei <ky...@qq.com>
AuthorDate: Thu Aug 26 21:57:21 2021 +0800

    Add ScopeModel and ScopeBeanFactory, fix extension initialization of XxxConfig
---
 .../org/apache/dubbo/rpc/cluster/StickyTest.java   |   2 -
 .../ScopeBeanException.java}                       |  14 +-
 .../ScopeBeanExtensionInjector.java}               |  30 +-
 .../common/beans/factory/ScopeBeanFactory.java     | 140 +++++++++
 .../beans/factory/ScopeBeanFactoryInitializer.java |  59 ++++
 .../dubbo/common/config/ConfigurationUtils.java    |  15 +
 .../configcenter/DynamicConfigurationFactory.java  |  16 -
 .../dubbo/common/extension/ExtensionAccessor.java  |  45 +++
 ...ectorAware.java => ExtensionAccessorAware.java} |   6 +-
 .../dubbo/common/extension/ExtensionDirector.java  |  21 +-
 .../dubbo/common/extension/ExtensionInjector.java  |   4 +-
 .../dubbo/common/extension/ExtensionLoader.java    |   6 +-
 .../inject/AdaptiveExtensionInjector.java          |  10 +-
 .../extension/inject/SpiExtensionInjector.java     |  10 +-
 .../manager/DefaultExecutorRepository.java         |  13 +-
 .../org/apache/dubbo/config/AbstractConfig.java    |  54 +++-
 .../dubbo/config/AbstractInterfaceConfig.java      |  40 +--
 .../org/apache/dubbo/config/ApplicationConfig.java |   3 +-
 .../java/org/apache/dubbo/config/MethodConfig.java |   3 +-
 .../apache/dubbo/config/ReferenceConfigBase.java   |   3 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |   6 +-
 .../org/apache/dubbo/config/ServiceConfigBase.java |  11 +-
 .../apache/dubbo/config/context/ConfigManager.java |  12 +-
 .../apache/dubbo/rpc/model/ApplicationModel.java   |  45 +--
 .../org/apache/dubbo/rpc/model/FrameworkModel.java |  29 +-
 .../org/apache/dubbo/rpc/model/ModuleModel.java    |  15 +-
 .../org/apache/dubbo/rpc/model/ScopeModel.java     |  59 ++++
 .../{ModelAware.java => ScopeModelAccessor.java}   |  15 +-
 .../{ModelAware.java => ScopeModelAware.java}      |   5 +-
 ...java => ScopeModelAwareExtensionProcessor.java} |  40 +--
 ...odelAware.java => ScopeModelPostProcessor.java} |  21 +-
 .../org/apache/dubbo/rpc/model/ScopeModelUtil.java |  50 ++++
 .../apache/dubbo/rpc/model/ServiceRepository.java  |  17 +-
 ...apache.dubbo.common.extension.ExtensionInjector |   1 +
 .../FileSystemDynamicConfigurationFactoryTest.java |   5 +-
 .../common/extension/ExtensionLoaderTest.java      |   5 -
 .../extension/director/impl/BaseTestService.java   |   4 +-
 .../org/apache/dubbo/config/ReferenceConfig.java   |  27 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |  34 ++-
 .../dubbo/config/bootstrap/DubboBootstrap.java     | 325 ++++++++++++++++-----
 .../bootstrap/DubboBootstrapMultiInstanceTest.java |  47 ++-
 .../dubbo/metadata/WritableMetadataService.java    |   3 +-
 .../metadata/report/MetadataReportInstance.java    |  24 +-
 .../apache/dubbo/monitor/dubbo/MetricsFilter.java  |  15 +-
 .../metadata/MetadataServiceNameMapping.java       |  21 +-
 .../registry/client/metadata/MetadataUtils.java    |  15 +-
 .../metadata/store/RemoteMetadataServiceImpl.java  |  13 +-
 47 files changed, 1000 insertions(+), 358 deletions(-)

diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
index f9f9311..eddd7f6 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster;
 
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.rpc.AppResponse;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
@@ -72,7 +71,6 @@ public class StickyTest {
 
         clusterinvoker = new StickyClusterInvoker<StickyTest>(dic);
 
-        ExtensionLoader.resetExtensionLoader(LoadBalance.class);
     }
 
     @Test
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
similarity index 74%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
index 5a68218..a6bb1b3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
@@ -14,13 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.beans;
 
-/**
- * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionDirector} instance.
- */
-public interface ExtensionDirectorAware {
+public class ScopeBeanException extends RuntimeException {
 
-    void setExtensionDirector(ExtensionDirector extensionDirector);
+    public ScopeBeanException(String message, Throwable cause) {
+        super(message, cause);
+    }
 
+    public ScopeBeanException(String message) {
+        super(message);
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java
similarity index 52%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java
index 0af3cbb..05dc985 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java
@@ -14,24 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.beans;
+
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.common.extension.ExtensionInjector;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 /**
- * An injector to provide resources for SPI extension.
+ * Inject scope bean to SPI extension instance
  */
-@SPI(scope = ExtensionScope.SELF)
-public interface ExtensionInjector extends ExtensionDirectorAware {
+public class ScopeBeanExtensionInjector implements ExtensionInjector, ScopeModelAware {
+    private ScopeModel scopeModel;
+    private ScopeBeanFactory beanFactory;
 
-    /**
-     * Get instance of specify type and name.
-     *
-     * @param type object type.
-     * @param name object name.
-     * @return object instance.
-     */
-    <T> T getInstance(Class<T> type, String name);
+    @Override
+    public void setScopeModel(ScopeModel scopeModel) {
+        this.scopeModel = scopeModel;
+        this.beanFactory = scopeModel.getBeanFactory();
+    }
 
     @Override
-    default void setExtensionDirector(ExtensionDirector extensionDirector) {
+    public <T> T getInstance(Class<T> type, String name) {
+        return beanFactory.getBean(name, type);
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
new file mode 100644
index 0000000..85f2d63
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
@@ -0,0 +1,140 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.beans.factory;
+
+import org.apache.dubbo.common.beans.ScopeBeanException;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionAccessorAware;
+import org.apache.dubbo.common.extension.ExtensionPostProcessor;
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+/**
+ * A bean factory for internal sharing.
+ */
+public class ScopeBeanFactory {
+
+    private final ScopeBeanFactory parent;
+    private ExtensionAccessor extensionAccessor;
+    private List<ExtensionPostProcessor> extensionPostProcessors;
+    private Map<Class, AtomicInteger> beanNameIdCounterMap = new ConcurrentHashMap<>();
+    private Map<Class, List<BeanInfo>> beanMap = new ConcurrentHashMap<>();
+
+    public ScopeBeanFactory(ScopeBeanFactory parent, ExtensionAccessor extensionAccessor) {
+        this.parent = parent;
+        this.extensionAccessor = extensionAccessor;
+        extensionPostProcessors = extensionAccessor.getExtensionDirector().getExtensionPostProcessors();
+    }
+
+    public <T> T registerBean(Class<T> bean) throws ScopeBeanException {
+        return this.registerBean(null, bean);
+    }
+
+    public <T> T registerBean(String name, Class<T> clazz) throws ScopeBeanException {
+        T instance = getBean(name, clazz);
+        if (instance != null) {
+            throw new ScopeBeanException("already exists bean with same name and type, name=" + name + ", type=" + clazz.getName());
+        }
+        try {
+            instance = clazz.newInstance();
+        } catch (Throwable e) {
+            throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName());
+        }
+        registerBean(name, instance);
+        return instance;
+    }
+
+    public void registerBean(Object bean) {
+        this.registerBean(null, bean);
+    }
+
+    public void registerBean(String name, Object bean) {
+        Class<?> beanClass = bean.getClass();
+        try {
+            if (bean instanceof ExtensionAccessorAware) {
+                ((ExtensionAccessorAware) bean).setExtensionAccessor(extensionAccessor);
+            }
+            for (ExtensionPostProcessor processor : extensionPostProcessors) {
+                processor.postProcessAfterInitialization(bean, name);
+            }
+        } catch (Exception e) {
+            throw new ScopeBeanException("register bean failed! name=" + name + ", type=" + beanClass.getName(), e);
+        }
+
+        if (name == null) {
+            name = beanClass.getName() + "#" + getNextId(beanClass);
+        }
+        List<BeanInfo> beanInfos = beanMap.computeIfAbsent(beanClass, key -> new ArrayList<>());
+        beanInfos.add(new BeanInfo(name, bean));
+    }
+
+    private int getNextId(Class<?> beanClass) {
+        return beanNameIdCounterMap.computeIfAbsent(beanClass, key -> new AtomicInteger()).incrementAndGet();
+    }
+
+    public <T> T getBean(Class<T> type) {
+        return this.getBean(null, type);
+    }
+
+    public <T> T getBean(String name, Class<T> type) {
+        T bean = getBeanInternal(name, type);
+        if (bean == null && parent != null) {
+            return parent.getBean(name, type);
+        }
+        return bean;
+    }
+
+    private <T> T getBeanInternal(String name, Class<T> type) {
+        List<BeanInfo> beanInfos = beanMap.get(type);
+        if (beanInfos == null || beanInfos.isEmpty()) {
+            return null;
+        }
+
+        for (BeanInfo beanInfo : beanInfos) {
+            if (name == null || StringUtils.isEquals(beanInfo.name, name)) {
+                return (T) beanInfo.instance;
+            }
+        }
+
+        // if bean name not matched and only single candidate
+        if (name != null) {
+            if (beanInfos.size() == 1) {
+                return (T) beanInfos.get(0);
+            } else if (beanInfos.size() > 1) {
+                List<String> candidateBeanNames = beanInfos.stream().map(beanInfo -> beanInfo.name).collect(Collectors.toList());
+                throw new ScopeBeanException("expected single matching bean but found " + beanInfos.size() + " candidates for type [" + type.getName() + "]: " + candidateBeanNames);
+            }
+        }
+        return null;
+    }
+
+    static class BeanInfo {
+        private String name;
+        private Object instance;
+
+        public BeanInfo(String name, Object instance) {
+            this.name = name;
+            this.instance = instance;
+        }
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java
new file mode 100644
index 0000000..33c9136
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java
@@ -0,0 +1,59 @@
+package org.apache.dubbo.common.beans.factory;
+
+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.ScopeModelPostProcessor;
+
+/**
+ * Initialize the bean factory for ScopeModel
+ */
+public abstract class ScopeBeanFactoryInitializer implements ScopeModelPostProcessor {
+
+    @Override
+    public void postProcessScopeModel(ScopeModel scopeModel) {
+        if (scopeModel instanceof ApplicationModel) {
+            ApplicationModel applicationModel = (ApplicationModel) scopeModel;
+            registerApplicationBeans(applicationModel, applicationModel.getBeanFactory());
+        } else if (scopeModel instanceof FrameworkModel) {
+            FrameworkModel frameworkModel = (FrameworkModel) scopeModel;
+            registerFrameworkBeans(frameworkModel, frameworkModel.getBeanFactory());
+        } else if (scopeModel instanceof ModuleModel) {
+            ModuleModel moduleModel = (ModuleModel) scopeModel;
+            registerModuleBeans(moduleModel, moduleModel.getBeanFactory());
+        }
+    }
+
+    /**
+     * Initialize beans for framework
+     *
+     * @param frameworkModel
+     * @param beanFactory
+     */
+    protected void registerFrameworkBeans(FrameworkModel frameworkModel, ScopeBeanFactory beanFactory) {
+
+    }
+
+    /**
+     * Initialize beans for application
+     *
+     * @param applicationModel
+     * @param beanFactory
+     */
+    protected void registerApplicationBeans(ApplicationModel applicationModel, ScopeBeanFactory beanFactory) {
+//        beanFactory.registerBean(MetadataReportInstance.class);
+//        beanFactory.registerBean(RemoteMetadataServiceImpl.class);
+    }
+
+    /**
+     * Initialize beans for module
+     *
+     * @param moduleModel
+     * @param beanFactory
+     */
+    protected void registerModuleBeans(ModuleModel moduleModel, ScopeBeanFactory beanFactory) {
+
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
index 94b9319..25db5df 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
@@ -16,6 +16,9 @@
  */
 package org.apache.dubbo.common.config;
 
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+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.StringUtils;
@@ -275,4 +278,16 @@ public class ConfigurationUtils {
         return ids;
     }
 
+    /**
+     * Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
+     * extension of {@link DynamicConfigurationFactory}
+     *
+     * @param name the name of extension of {@link DynamicConfigurationFactory}
+     * @return non-null
+     * @see 2.7.4
+     */
+    public static DynamicConfigurationFactory getDynamicConfigurationFactory(ExtensionAccessor extensionAccessor, String name) {
+        ExtensionLoader<DynamicConfigurationFactory> loader = extensionAccessor.getExtensionLoader(DynamicConfigurationFactory.class);
+        return loader.getOrDefaultExtension(name);
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
index 4b7118d..a6b6dbc 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
@@ -17,12 +17,9 @@
 package org.apache.dubbo.common.config.configcenter;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
-
 /**
  * The factory interface to create the instance of {@link DynamicConfiguration}
  */
@@ -31,17 +28,4 @@ public interface DynamicConfigurationFactory {
 
     DynamicConfiguration getDynamicConfiguration(URL url);
 
-    /**
-     * Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
-     * extension of {@link DynamicConfigurationFactory}
-     *
-     * @param name the name of extension of {@link DynamicConfigurationFactory}
-     * @return non-null
-     * @see 2.7.4
-     */
-    static DynamicConfigurationFactory getDynamicConfigurationFactory(String name) {
-        Class<DynamicConfigurationFactory> factoryClass = DynamicConfigurationFactory.class;
-        ExtensionLoader<DynamicConfigurationFactory> loader = getExtensionLoader(factoryClass);
-        return loader.getOrDefaultExtension(name);
-    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessor.java
new file mode 100644
index 0000000..be13080
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.extension;
+
+/**
+ * Uniform accessor for extension
+ */
+public interface ExtensionAccessor {
+
+    ExtensionDirector getExtensionDirector();
+
+    default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+        return this.getExtensionDirector().getExtensionLoader(type);
+    }
+
+    default <T> T getExtension(Class<T> type, String name) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getExtension(name) : null;
+    }
+
+    default <T> T getAdaptiveExtension(Class<T> type) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null;
+    }
+
+    default <T> T getDefaultExtension(Class<T> type) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
similarity index 85%
rename from dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
index 5a68218..e2215e5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirectorAware.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
@@ -17,10 +17,10 @@
 package org.apache.dubbo.common.extension;
 
 /**
- * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionDirector} instance.
+ * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionAccessor} instance.
  */
-public interface ExtensionDirectorAware {
+public interface ExtensionAccessorAware {
 
-    void setExtensionDirector(ExtensionDirector extensionDirector);
+    void setExtensionAccessor(ExtensionAccessor extensionAccessor);
 
 }
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 0e7768e..07d8cde 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
@@ -28,7 +28,7 @@ import java.util.concurrent.ConcurrentMap;
  * <p>ExtensionDirector supports multiple levels, and the child can inherit the parent's extension instances. </p>
  * <p>The way to find and create an extension instance is similar to Java classloader.</p>
  */
-public class ExtensionDirector {
+public class ExtensionDirector implements ExtensionAccessor {
 
     private final ConcurrentMap<Class<?>, ExtensionLoader<?>> extensionLoadersMap = new ConcurrentHashMap<>(64);
     private ExtensionDirector parent;
@@ -50,21 +50,12 @@ public class ExtensionDirector {
         return extensionPostProcessors;
     }
 
-    public <T> T getExtension(Class<T> type, String name) {
-        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
-        return extensionLoader != null ? extensionLoader.getExtension(name) : null;
-    }
-
-    public <T> T getAdaptiveExtension(Class<T> type) {
-        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
-        return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null;
-    }
-
-    public <T> T getDefaultExtension(Class<T> type) {
-        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
-        return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
+    @Override
+    public ExtensionDirector getExtensionDirector() {
+        return this;
     }
 
+    @Override
     public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
         if (type == null) {
             throw new IllegalArgumentException("Extension type == null");
@@ -130,7 +121,7 @@ public class ExtensionDirector {
         return type.isAnnotationPresent(SPI.class);
     }
 
-    protected ExtensionDirector getParent() {
+    public ExtensionDirector getParent() {
         return parent;
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
index 0af3cbb..4906805 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
@@ -20,7 +20,7 @@ package org.apache.dubbo.common.extension;
  * An injector to provide resources for SPI extension.
  */
 @SPI(scope = ExtensionScope.SELF)
-public interface ExtensionInjector extends ExtensionDirectorAware {
+public interface ExtensionInjector extends ExtensionAccessorAware {
 
     /**
      * Get instance of specify type and name.
@@ -32,6 +32,6 @@ public interface ExtensionInjector extends ExtensionDirectorAware {
     <T> T getInstance(Class<T> type, String name);
 
     @Override
-    default void setExtensionDirector(ExtensionDirector extensionDirector) {
+    default void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
     }
 }
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 a7ef06f..166e9c0 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
@@ -174,7 +174,7 @@ public class ExtensionLoader<T> {
      */
     @Deprecated
     public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
-        return ApplicationModel.defaultModel().getExtensionDirector().getExtensionLoader(type);
+        return ApplicationModel.defaultModel().getExtensionLoader(type);
     }
 
     // For testing purposes only
@@ -734,8 +734,8 @@ public class ExtensionLoader<T> {
     }
 
     private T postProcessAfterInitialization(T instance, String name) throws Exception {
-        if (instance instanceof ExtensionDirectorAware) {
-            ((ExtensionDirectorAware) instance).setExtensionDirector(extensionDirector);
+        if (instance instanceof ExtensionAccessorAware) {
+            ((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector);
         }
         if (extensionPostProcessors != null) {
             for (ExtensionPostProcessor processor : extensionPostProcessors) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/AdaptiveExtensionInjector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/AdaptiveExtensionInjector.java
index 3c78474..1ae03cf 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/AdaptiveExtensionInjector.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/AdaptiveExtensionInjector.java
@@ -18,7 +18,7 @@ package org.apache.dubbo.common.extension.inject;
 
 import org.apache.dubbo.common.context.Lifecycle;
 import org.apache.dubbo.common.extension.Adaptive;
-import org.apache.dubbo.common.extension.ExtensionDirector;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
 import org.apache.dubbo.common.extension.ExtensionInjector;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 
@@ -34,19 +34,19 @@ public class AdaptiveExtensionInjector implements ExtensionInjector, Lifecycle {
 
     private List<ExtensionInjector> injectors = Collections.emptyList();
 
-    private ExtensionDirector extensionDirector;
+    private ExtensionAccessor extensionAccessor;
 
     public AdaptiveExtensionInjector() {
     }
 
     @Override
-    public void setExtensionDirector(ExtensionDirector extensionDirector) {
-        this.extensionDirector = extensionDirector;
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
     }
 
     @Override
     public void initialize() throws IllegalStateException {
-        ExtensionLoader<ExtensionInjector> loader = extensionDirector.getExtensionLoader(ExtensionInjector.class);
+        ExtensionLoader<ExtensionInjector> loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
         List<ExtensionInjector> list = new ArrayList<ExtensionInjector>();
         for (String name : loader.getSupportedExtensions()) {
             list.add(loader.getExtension(name));
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java
index 1ee4d71..d45cc7b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java
@@ -16,7 +16,7 @@
  */
 package org.apache.dubbo.common.extension.inject;
 
-import org.apache.dubbo.common.extension.ExtensionDirector;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
 import org.apache.dubbo.common.extension.ExtensionInjector;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.SPI;
@@ -26,17 +26,17 @@ import org.apache.dubbo.common.extension.SPI;
  */
 public class SpiExtensionInjector implements ExtensionInjector {
 
-    private ExtensionDirector extensionDirector;
+    private ExtensionAccessor extensionAccessor;
 
     @Override
-    public void setExtensionDirector(ExtensionDirector extensionDirector) {
-        this.extensionDirector = extensionDirector;
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
     }
 
     @Override
     public <T> T getInstance(Class<T> type, String name) {
         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
-            ExtensionLoader<T> loader = extensionDirector.getExtensionLoader(type);
+            ExtensionLoader<T> loader = extensionAccessor.getExtensionLoader(type);
             if (loader == null) {
                 return null;
             }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
index 2776855..54334fd 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
@@ -17,7 +17,8 @@
 package org.apache.dubbo.common.threadpool.manager;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionAccessorAware;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory;
@@ -51,7 +52,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
 /**
  * Consider implementing {@code Licycle} to enable executors shutdown when the process stops.
  */
-public class DefaultExecutorRepository implements ExecutorRepository {
+public class DefaultExecutorRepository implements ExecutorRepository, ExtensionAccessorAware {
     private static final Logger logger = LoggerFactory.getLogger(DefaultExecutorRepository.class);
 
     private int DEFAULT_SCHEDULER_SIZE = Runtime.getRuntime().availableProcessors();
@@ -79,6 +80,7 @@ public class DefaultExecutorRepository implements ExecutorRepository {
     private static Ring<ExecutorService> executorServiceRing = new Ring<ExecutorService>();
 
     private static final Object LOCK = new Object();
+    private ExtensionAccessor extensionAccessor;
 
     public DefaultExecutorRepository() {
         for (int i = 0; i < DEFAULT_SCHEDULER_SIZE; i++) {
@@ -311,7 +313,7 @@ public class DefaultExecutorRepository implements ExecutorRepository {
     }
 
     private ExecutorService createExecutor(URL url) {
-        return (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
+        return (ExecutorService) extensionAccessor.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
     }
 
     @Override
@@ -362,4 +364,9 @@ public class DefaultExecutorRepository implements ExecutorRepository {
 //            executorService.shutdown();
 //        }
     }
+
+    @Override
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index af2150d..dedb0b0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.config.Environment;
 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.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ClassUtils;
@@ -28,8 +29,11 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.MethodUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.rpc.model.ScopeModel;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
 
 import java.beans.BeanInfo;
 import java.beans.IntrospectionException;
@@ -93,6 +97,13 @@ public abstract class AbstractConfig implements Serializable {
      */
     protected Boolean isDefault;
 
+    /**
+     * The scope model of this config instance.
+     * <p>
+     * <b>NOTE:</b> the model maybe changed during config processing,
+     * the extension spi instance needs to be reinitialized after changing the model!
+     */
+    protected ScopeModel scopeModel;
 
     public static String getTagName(Class<?> cls) {
         return tagNameCache.computeIfAbsent(cls, (key) -> {
@@ -302,6 +313,44 @@ public abstract class AbstractConfig implements Serializable {
         return result;
     }
 
+    public ApplicationModel getApplicationModel() {
+        if (scopeModel instanceof ApplicationModel) {
+            return (ApplicationModel) scopeModel;
+        } else if (scopeModel instanceof ModuleModel) {
+            return ((ModuleModel) scopeModel).getApplicationModel();
+        } else {
+            throw new IllegalStateException("scope model is invalid: " + scopeModel);
+        }
+    }
+
+    public ScopeModel getScopeModel() {
+        return scopeModel;
+    }
+
+    public void setScopeModel(ScopeModel scopeModel) {
+        this.scopeModel = scopeModel;
+        // REINITIALIZE SPI extension here
+        this.initExtensions();
+    }
+
+    /**
+     * Subclass should override this method to initialize its SPI extensions.
+     * <p>
+     * For example:
+     * <pre>
+     * this.protocol = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+     * </pre>
+     */
+    protected void initExtensions() {
+    }
+
+    protected <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+        if (scopeModel == null) {
+            throw new IllegalStateException("owner module is not initialized");
+        }
+        return scopeModel.getExtensionLoader(type);
+    }
+
     @Parameter(excluded = true, attribute = true)
     public String getId() {
         return id;
@@ -443,7 +492,7 @@ public abstract class AbstractConfig implements Serializable {
             // check and init before do refresh
             preProcessRefresh();
 
-            Environment environment = ApplicationModel.defaultModel().getEnvironment();
+            Environment environment = getApplicationModel().getEnvironment();
             List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
 
             // Search props starts with PREFIX in order
@@ -729,4 +778,7 @@ public abstract class AbstractConfig implements Serializable {
         return methods;
     }
 
+    protected ConfigManager getConfigManager() {
+        return getApplicationModel().getConfigManager();
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index e13b5e0..eb88a57 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.bytecode.Wrapper;
 import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.config.InmemoryConfiguration;
 import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.CollectionUtils;
@@ -27,7 +28,6 @@ import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
 
 import java.lang.reflect.Method;
@@ -225,7 +225,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
      * @return
      */
     protected String[] methods(Class<?> interfaceClass) {
-        boolean isNative = ApplicationModel.defaultModel().getEnvironment().getConfiguration().getBoolean(NATIVE, false);
+        boolean isNative = getEnvironment().getConfiguration().getBoolean(NATIVE, false);
         if (isNative) {
             return Arrays.stream(interfaceClass.getMethods()).map(Method::getName).toArray(String[]::new);
         } else {
@@ -233,6 +233,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         }
     }
 
+    protected Environment getEnvironment() {
+        return getApplicationModel().getEnvironment();
+    }
+
     @Override
     protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
         if (StringUtils.hasText(interfaceName)) {
@@ -278,7 +282,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             List<MethodConfig> methodConfigs = this.getMethods();
             if (methodConfigs != null && methodConfigs.size() > 0) {
                 // whether ignore invalid method config
-                Object ignoreInvalidMethodConfigVal = ApplicationModel.defaultModel().getEnvironment().getConfiguration()
+                Object ignoreInvalidMethodConfigVal = getEnvironment().getConfiguration()
                     .getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_INVALID_METHOD_CONFIG, "false");
                 boolean ignoreInvalidMethodConfig = Boolean.parseBoolean(ignoreInvalidMethodConfigVal.toString());
 
@@ -388,7 +392,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         computeValidRegistryIds();
         if (StringUtils.isEmpty(registryIds)) {
             if (CollectionUtils.isEmpty(registries)) {
-                List<RegistryConfig> registryConfigs = ApplicationModel.defaultModel().getConfigManager().getDefaultRegistries();
+                List<RegistryConfig> registryConfigs = getConfigManager().getDefaultRegistries();
                 registryConfigs = new ArrayList<>(registryConfigs);
                 setRegistries(registryConfigs);
             }
@@ -397,7 +401,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             List<RegistryConfig> tmpRegistries = new ArrayList<>();
             Arrays.stream(ids).forEach(id -> {
                 if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
-                    Optional<RegistryConfig> globalRegistry = ApplicationModel.defaultModel().getConfigManager().getRegistry(id);
+                    Optional<RegistryConfig> globalRegistry = getConfigManager().getRegistry(id);
                     if (globalRegistry.isPresent()) {
                         tmpRegistries.add(globalRegistry.get());
                     } else {
@@ -561,14 +565,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         if (application != null) {
             return application;
         }
-        return ApplicationModel.defaultModel().getConfigManager().getApplicationOrElseThrow();
+        return getConfigManager().getApplicationOrElseThrow();
     }
 
     @Deprecated
     public void setApplication(ApplicationConfig application) {
         this.application = application;
         if (application != null) {
-            ApplicationModel.defaultModel().getConfigManager().setApplication(application);
+            getConfigManager().setApplication(application);
         }
     }
 
@@ -576,14 +580,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         if (module != null) {
             return module;
         }
-        return ApplicationModel.defaultModel().getConfigManager().getModule().orElse(null);
+        return getConfigManager().getModule().orElse(null);
     }
 
     @Deprecated
     public void setModule(ModuleConfig module) {
         this.module = module;
         if (module != null) {
-            ApplicationModel.defaultModel().getConfigManager().setModule(module);
+            getConfigManager().setModule(module);
         }
     }
 
@@ -637,7 +641,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             return monitor;
         }
         // FIXME: instead of return null, we should set default monitor when getMonitor() return null in ConfigManager
-        return ApplicationModel.defaultModel().getConfigManager().getMonitor().orElse(null);
+        return getConfigManager().getMonitor().orElse(null);
     }
 
     @Deprecated
@@ -649,7 +653,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     public void setMonitor(MonitorConfig monitor) {
         this.monitor = monitor;
         if (monitor != null) {
-            ApplicationModel.defaultModel().getConfigManager().setMonitor(monitor);
+            getConfigManager().setMonitor(monitor);
         }
     }
 
@@ -666,7 +670,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         if (configCenter != null) {
             return configCenter;
         }
-        Collection<ConfigCenterConfig> configCenterConfigs = ApplicationModel.defaultModel().getConfigManager().getConfigCenters();
+        Collection<ConfigCenterConfig> configCenterConfigs = getConfigManager().getConfigCenters();
         if (CollectionUtils.isNotEmpty(configCenterConfigs)) {
             return configCenterConfigs.iterator().next();
         }
@@ -677,7 +681,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     public void setConfigCenter(ConfigCenterConfig configCenter) {
         this.configCenter = configCenter;
         if (configCenter != null) {
-            ApplicationModel.defaultModel().getConfigManager().addConfigCenter(configCenter);
+            getConfigManager().addConfigCenter(configCenter);
         }
     }
 
@@ -718,7 +722,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         if (metadataReportConfig != null) {
             return metadataReportConfig;
         }
-        Collection<MetadataReportConfig> metadataReportConfigs = ApplicationModel.defaultModel().getConfigManager().getMetadataConfigs();
+        Collection<MetadataReportConfig> metadataReportConfigs = getConfigManager().getMetadataConfigs();
         if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
             return metadataReportConfigs.iterator().next();
         }
@@ -729,7 +733,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     public void setMetadataReportConfig(MetadataReportConfig metadataReportConfig) {
         this.metadataReportConfig = metadataReportConfig;
         if (metadataReportConfig != null) {
-            ApplicationModel.defaultModel().getConfigManager().addMetadataReport(metadataReportConfig);
+            getConfigManager().addMetadataReport(metadataReportConfig);
         }
     }
 
@@ -738,14 +742,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         if (metrics != null) {
             return metrics;
         }
-        return ApplicationModel.defaultModel().getConfigManager().getMetrics().orElse(null);
+        return getConfigManager().getMetrics().orElse(null);
     }
 
     @Deprecated
     public void setMetrics(MetricsConfig metrics) {
         this.metrics = metrics;
         if (metrics != null) {
-            ApplicationModel.defaultModel().getConfigManager().setMetrics(metrics);
+            getConfigManager().setMetrics(metrics);
         }
     }
 
@@ -767,7 +771,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     }
 
     public SslConfig getSslConfig() {
-        return ApplicationModel.defaultModel().getConfigManager().getSsl().orElse(null);
+        return getConfigManager().getSsl().orElse(null);
     }
     
     protected void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 2a2758a..1b0176a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.compiler.support.AdaptiveCompiler;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.infra.InfraAdapter;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -551,7 +550,7 @@ public class ApplicationConfig extends AbstractConfig {
             parameters = new HashMap<>();
         }
 
-        Set<InfraAdapter> adapters = ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
+        Set<InfraAdapter> adapters = this.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
         if (CollectionUtils.isNotEmpty(adapters)) {
             Map<String, String> inputParameters = new HashMap<>();
             inputParameters.put(APPLICATION_KEY, getName());
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java
index 7d6b44f..6b03ee6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MethodConfig.java
@@ -24,7 +24,6 @@ import org.apache.dubbo.common.utils.ReflectUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.AsyncMethodInfo;
 
 import java.util.ArrayList;
@@ -231,7 +230,7 @@ public class MethodConfig extends AbstractMethodConfig {
     private void refreshArgument(ArgumentConfig argument, InmemoryConfiguration subPropsConfiguration) {
         if (argument.getIndex() != null && argument.getIndex() >= 0) {
             String prefix = argument.getIndex() + ".";
-            Environment environment = ApplicationModel.defaultModel().getEnvironment();
+            Environment environment = getApplicationModel().getEnvironment();
             java.lang.reflect.Method[] methods = argument.getClass().getMethods();
             for (java.lang.reflect.Method method : methods) {
                 if (MethodUtils.isSetter(method)) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
index 65840a6..09abf83 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
@@ -22,7 +22,6 @@ import org.apache.dubbo.common.utils.RegexProperties;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -115,7 +114,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
     protected void preProcessRefresh() {
         super.preProcessRefresh();
         if (consumer == null) {
-            consumer = ApplicationModel.defaultModel().getConfigManager()
+            consumer = getConfigManager()
                     .getDefaultConsumer()
                     .orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized"));
         }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java
index 9ed3df1..f007b54 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -327,7 +327,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setTransporter(String transporter) {
-        /*if(transporter != null && transporter.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(transporter)){
+        /*if(transporter != null && transporter.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(transporter)){
             throw new IllegalStateException("No such transporter type : " + transporter);
         }*/
         this.transporter = transporter;
@@ -338,7 +338,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setServer(String server) {
-        /*if(server != null && server.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(server)){
+        /*if(server != null && server.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(server)){
             throw new IllegalStateException("No such server type : " + server);
         }*/
         this.server = server;
@@ -349,7 +349,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setClient(String client) {
-        /*if(client != null && client.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(client)){
+        /*if(client != null && client.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(client)){
             throw new IllegalStateException("No such client type : " + client);
         }*/
         this.client = client;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
index ef403de..8e99615 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -199,7 +198,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
         super.preProcessRefresh();
         convertProviderIdToProvider();
         if (provider == null) {
-            provider = ApplicationModel.defaultModel().getConfigManager()
+            provider = getConfigManager()
                     .getDefaultProvider()
                     .orElseThrow(() -> new IllegalArgumentException("Default provider is not initialized"));
         }
@@ -247,7 +246,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
 
     protected void convertProviderIdToProvider() {
         if (provider == null && StringUtils.hasText(providerIds)) {
-            provider = ApplicationModel.defaultModel().getConfigManager().getProvider(providerIds)
+            provider = getConfigManager().getProvider(providerIds)
                     .orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds));
         }
     }
@@ -255,7 +254,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
     protected void convertProtocolIdsToProtocols() {
         if (StringUtils.isEmpty(protocolIds)) {
             if (CollectionUtils.isEmpty(protocols)) {
-                List<ProtocolConfig> protocolConfigs = ApplicationModel.defaultModel().getConfigManager().getDefaultProtocols();
+                List<ProtocolConfig> protocolConfigs = getConfigManager().getDefaultProtocols();
                 if (protocolConfigs.isEmpty()) {
                     throw new IllegalStateException("The default protocol has not been initialized.");
                 }
@@ -266,7 +265,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
             Set<String> idsSet = new LinkedHashSet<>(Arrays.asList(idsArray));
             List<ProtocolConfig> tmpProtocols = new ArrayList<>();
             for (String id : idsSet) {
-                Optional<ProtocolConfig> globalProtocol = ApplicationModel.defaultModel().getConfigManager().getProtocol(id);
+                Optional<ProtocolConfig> globalProtocol = getConfigManager().getProtocol(id);
                 if (globalProtocol.isPresent()) {
                     tmpProtocols.add(globalProtocol.get());
                 } else {
@@ -336,7 +335,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
     }
 
     public void setProvider(ProviderConfig provider) {
-        ApplicationModel.defaultModel().getConfigManager().addProvider(provider);
+        getConfigManager().addProvider(provider);
         this.provider = provider;
     }
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index b9ea862..215753b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -44,6 +44,7 @@ import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfigBase;
 import org.apache.dubbo.config.SslConfig;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -66,7 +67,7 @@ import static org.apache.dubbo.config.AbstractConfig.getTagName;
  * A lock-free config manager (through ConcurrentHashMap), for fast read operation.
  * The Write operation lock with sub configs map of config type, for safely check and add new config.
  */
-public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
+public class ConfigManager extends LifecycleAdapter implements FrameworkExt, ScopeModelAware {
 
     private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
 
@@ -105,12 +106,19 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
         }
     }
 
+    private ApplicationModel applicationModel;
+
     public ConfigManager() {
     }
 
     @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
+
+    @Override
     public void initialize() throws IllegalStateException {
-        CompositeConfiguration configuration = ApplicationModel.defaultModel().getEnvironment().getConfiguration();
+        CompositeConfiguration configuration = applicationModel.getEnvironment().getConfiguration();
         String configModeStr = (String) configuration.getProperty(DUBBO_CONFIG_MODE);
         try {
             if (StringUtils.hasText(configModeStr)) {
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 4954ea0..0ccfff4 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
@@ -27,9 +27,10 @@ import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.context.ConfigManager;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.List;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -47,25 +48,24 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * <p>
  */
 
-public class ApplicationModel {
+public class ApplicationModel extends ScopeModel {
     protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
     public static final String NAME = "application";
     private static volatile ApplicationModel defaultInstance;
 
-    private Collection<ModuleModel> moduleModels = Collections.synchronizedSet(new LinkedHashSet<>());
+    private volatile List<ModuleModel> moduleModels = Collections.synchronizedList(new ArrayList<>());
     private AtomicBoolean initFlag = new AtomicBoolean(false);
     private Environment environment;
     private ConfigManager configManager;
     private ServiceRepository serviceRepository;
 
     private FrameworkModel frameworkModel;
-    private ExtensionDirector extensionDirector;
 
     public ApplicationModel(FrameworkModel frameworkModel) {
+        super(frameworkModel, new ExtensionDirector(frameworkModel.getExtensionDirector(), ExtensionScope.APPLICATION));
         this.frameworkModel = frameworkModel;
-        extensionDirector = new ExtensionDirector(frameworkModel.getExtensionDirector(), ExtensionScope.APPLICATION);
-        extensionDirector.addExtensionPostProcessor(new ModelAwarePostProcessor(this));
         frameworkModel.addApplication(this);
+        postProcessAfterCreated();
     }
 
     public static ApplicationModel defaultModel() {
@@ -81,7 +81,7 @@ public class ApplicationModel {
 
     public void init() {
         if (initFlag.compareAndSet(false, true)) {
-            ExtensionLoader<ApplicationInitListener> extensionLoader = ExtensionLoader.getExtensionLoader(ApplicationInitListener.class);
+            ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
             Set<String> listenerNames = extensionLoader.getSupportedExtensions();
             for (String listenerName : listenerNames) {
                 extensionLoader.getExtension(listenerName).init();
@@ -97,14 +97,6 @@ public class ApplicationModel {
         return frameworkModel;
     }
 
-    public ExtensionDirector getExtensionDirector() {
-        return extensionDirector;
-    }
-
-    public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
-        return extensionDirector.getExtensionLoader(type);
-    }
-
     public Collection<ConsumerModel> allConsumerModels() {
         return getServiceRepository().getReferredServices();
     }
@@ -122,7 +114,7 @@ public class ApplicationModel {
     }
 
     public void initFrameworkExts() {
-        Set<FrameworkExt> exts = extensionDirector.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
+        Set<FrameworkExt> exts = this.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
         for (FrameworkExt ext : exts) {
             ext.initialize();
         }
@@ -130,7 +122,7 @@ public class ApplicationModel {
 
     public Environment getEnvironment() {
         if (environment == null) {
-            environment = (Environment) extensionDirector.getExtensionLoader(FrameworkExt.class)
+            environment = (Environment) this.getExtensionLoader(FrameworkExt.class)
                 .getExtension(Environment.NAME);
         }
         return environment;
@@ -138,7 +130,7 @@ public class ApplicationModel {
 
     public ConfigManager getConfigManager() {
         if (configManager == null) {
-            configManager = (ConfigManager) extensionDirector.getExtensionLoader(FrameworkExt.class)
+            configManager = (ConfigManager) this.getExtensionLoader(FrameworkExt.class)
                 .getExtension(ConfigManager.NAME);
         }
         return configManager;
@@ -146,14 +138,14 @@ public class ApplicationModel {
 
     public ServiceRepository getServiceRepository() {
         if (serviceRepository == null) {
-            serviceRepository = (ServiceRepository) extensionDirector.getExtensionLoader(FrameworkExt.class)
+            serviceRepository = (ServiceRepository) this.getExtensionLoader(FrameworkExt.class)
                 .getExtension(ServiceRepository.NAME);
         }
         return serviceRepository;
     }
 
     public ExecutorRepository getExecutorRepository() {
-        return extensionDirector.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+        return this.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
     }
 
     public ApplicationConfig getApplicationConfig() {
@@ -165,17 +157,26 @@ public class ApplicationModel {
     }
 
     public void addModule(ModuleModel model) {
-        this.moduleModels.add(model);
+        if (!this.moduleModels.contains(model)) {
+            this.moduleModels.add(model);
+        }
     }
 
     public void removeModule(ModuleModel model) {
         this.moduleModels.remove(model);
     }
 
-    public Collection<ModuleModel> getModuleModels() {
+    public List<ModuleModel> getModuleModels() {
         return moduleModels;
     }
 
+    public synchronized ModuleModel getDefaultModule() {
+        if (moduleModels.isEmpty()) {
+            this.addModule(new ModuleModel(this));
+        }
+        return moduleModels.get(0);
+    }
+
     // only for unit test
     @Deprecated
     public static void reset() {
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 18cc148..438c465 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
@@ -17,31 +17,28 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.extension.ExtensionDirector;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 
-import java.util.Collection;
+import java.util.ArrayList;
 import java.util.Collections;
-import java.util.LinkedHashSet;
+import java.util.List;
 
 /**
  * Model of dubbo framework, it can be shared with multiple applications.
  */
-public class FrameworkModel {
+public class FrameworkModel extends ScopeModel {
 
     protected static final Logger LOGGER = LoggerFactory.getLogger(FrameworkModel.class);
 
     private volatile static FrameworkModel defaultInstance;
 
-    private final ExtensionDirector extensionDirector;
-
-    private Collection<ApplicationModel> applicationModels = Collections.synchronizedSet(new LinkedHashSet<>());
+    private List<ApplicationModel> applicationModels = Collections.synchronizedList(new ArrayList<>());
 
     public FrameworkModel() {
-        extensionDirector = new ExtensionDirector(null, ExtensionScope.FRAMEWORK);
-        extensionDirector.addExtensionPostProcessor(new ModelAwarePostProcessor(this));
+        super(null, new ExtensionDirector(null, ExtensionScope.FRAMEWORK));
+        postProcessAfterCreated();
     }
 
     public static FrameworkModel defaultModel() {
@@ -55,23 +52,17 @@ public class FrameworkModel {
         return defaultInstance;
     }
 
-    public ExtensionDirector getExtensionDirector() {
-        return extensionDirector;
-    }
-
-    public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
-        return extensionDirector.getExtensionLoader(type);
-    }
-
     public void addApplication(ApplicationModel model) {
-        this.applicationModels.add(model);
+        if (!this.applicationModels.contains(model)) {
+            this.applicationModels.add(model);
+        }
     }
 
     public void removeApplication(ApplicationModel model) {
         this.applicationModels.remove(model);
     }
 
-    public Collection<ApplicationModel> getApplicationModels() {
+    public List<ApplicationModel> getApplicationModels() {
         return applicationModels;
     }
 }
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 e2e8345..0ddb8b9 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
@@ -17,33 +17,24 @@
 package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.extension.ExtensionDirector;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.ExtensionScope;
 
 /**
  * Model of a service module
  */
-public class ModuleModel {
+public class ModuleModel extends ScopeModel {
 
     private final ApplicationModel applicationModel;
-    private final ExtensionDirector extensionDirector;
 
     public ModuleModel(ApplicationModel applicationModel) {
+        super(applicationModel, new ExtensionDirector(applicationModel.getExtensionDirector(), ExtensionScope.MODULE));
         this.applicationModel = applicationModel;
-        extensionDirector = new ExtensionDirector(applicationModel.getExtensionDirector(), ExtensionScope.MODULE);
-        extensionDirector.addExtensionPostProcessor(new ModelAwarePostProcessor(this));
         applicationModel.addModule(this);
+        postProcessAfterCreated();
     }
 
     public ApplicationModel getApplicationModel() {
         return applicationModel;
     }
 
-    public ExtensionDirector getExtensionDirector() {
-        return extensionDirector;
-    }
-
-    public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
-        return extensionDirector.getExtensionLoader(type);
-    }
 }
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
new file mode 100644
index 0000000..5d96f11
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.model;
+
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionDirector;
+
+import java.util.Set;
+
+public abstract class ScopeModel implements ExtensionAccessor {
+
+    private final ScopeModel parent;
+
+    private final ExtensionDirector extensionDirector;
+
+    private final ScopeBeanFactory beanFactory;
+
+    public ScopeModel(ScopeModel parent, ExtensionDirector extensionDirector) {
+        this.parent = parent;
+        this.extensionDirector = extensionDirector;
+        this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
+        this.beanFactory = new ScopeBeanFactory(parent!=null?parent.getBeanFactory():null, extensionDirector);
+    }
+
+    public ExtensionDirector getExtensionDirector() {
+        return extensionDirector;
+    }
+
+    public ScopeBeanFactory getBeanFactory() {
+        return beanFactory;
+    }
+
+    public ScopeModel getParent() {
+        return parent;
+    }
+
+    protected void postProcessAfterCreated() {
+        Set<ScopeModelPostProcessor> scopeModelPostProcessors = getExtensionLoader(ScopeModelPostProcessor.class)
+            .getSupportedExtensionInstances();
+        for (ScopeModelPostProcessor processor : scopeModelPostProcessors) {
+            processor.postProcessScopeModel(this);
+        }
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java
similarity index 63%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java
index dafa769..35aefa7 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java
@@ -17,17 +17,22 @@
 package org.apache.dubbo.rpc.model;
 
 /**
- * Interface to inject FrameworkModel/ApplicationModel/ModuleModel for SPI extension.
+ * An accessor for scope module, it can be use in interface default methods to get scope model.
  */
-public interface ModelAware {
+public interface ScopeModelAccessor {
 
-    default void setFrameworkModel(FrameworkModel frameworkModel) {
+    ScopeModel getScopeModel();
+
+    default FrameworkModel getFrameworkModel() {
+        return ScopeModelUtil.getFrameworkModel(getScopeModel());
     }
 
-    default void setApplicationModel(ApplicationModel applicationModel) {
+    default ApplicationModel getApplicationModel() {
+        return ScopeModelUtil.getApplicationModel(getScopeModel());
     }
 
-    default void setModuleModel(ModuleModel moduleModel) {
+    default ModuleModel getModuleModel() {
+        return ScopeModelUtil.getModuleModel(getScopeModel());
     }
 
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java
similarity index 92%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java
index dafa769..1fdc422 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java
@@ -19,7 +19,10 @@ package org.apache.dubbo.rpc.model;
 /**
  * Interface to inject FrameworkModel/ApplicationModel/ModuleModel for SPI extension.
  */
-public interface ModelAware {
+public interface ScopeModelAware {
+
+    default void setScopeModel(ScopeModel scopeModel) {
+    }
 
     default void setFrameworkModel(FrameworkModel frameworkModel) {
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAwarePostProcessor.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java
similarity index 66%
rename from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAwarePostProcessor.java
rename to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java
index 2e93318..4c47c22 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAwarePostProcessor.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java
@@ -18,40 +18,44 @@ package org.apache.dubbo.rpc.model;
 
 import org.apache.dubbo.common.extension.ExtensionPostProcessor;
 
-public class ModelAwarePostProcessor implements ExtensionPostProcessor {
-    private Object model;
+public class ScopeModelAwareExtensionProcessor implements ExtensionPostProcessor {
+    private ScopeModel scopeModel;
     private FrameworkModel frameworkModel;
     private ApplicationModel applicationModel;
     private ModuleModel moduleModel;
+    private volatile boolean inited;
 
-    public ModelAwarePostProcessor(Object model) {
-        this.model = model;
-        if (model instanceof FrameworkModel) {
-            frameworkModel = (FrameworkModel) model;
-        } else if (model instanceof ApplicationModel) {
-            applicationModel = (ApplicationModel) model;
-            frameworkModel = applicationModel.getFrameworkModel();
-        } else if (model instanceof ModuleModel) {
-            moduleModel = (ModuleModel) model;
-            applicationModel = moduleModel.getApplicationModel();
-            frameworkModel = applicationModel.getFrameworkModel();
+    public ScopeModelAwareExtensionProcessor(ScopeModel scopeModel) {
+        this.scopeModel = scopeModel;
+    }
+
+    private void init() {
+        if (inited) {
+            return;
         }
+        frameworkModel = ScopeModelUtil.getFrameworkModel(scopeModel);
+        applicationModel = ScopeModelUtil.getApplicationModel(scopeModel);
+        moduleModel = ScopeModelUtil.getModuleModel(scopeModel);
+        inited = true;
     }
 
     @Override
     public Object postProcessAfterInitialization(Object instance, String name) throws Exception {
-        if (instance instanceof ModelAware) {
-            ModelAware modelAware = (ModelAware) instance;
-            if (this.applicationModel != null) {
-                modelAware.setApplicationModel(this.applicationModel);
-            }
+        init();
+        if (instance instanceof ScopeModelAware) {
+            ScopeModelAware modelAware = (ScopeModelAware) instance;
+            modelAware.setScopeModel(scopeModel);
             if (this.moduleModel != null) {
                 modelAware.setModuleModel(this.moduleModel);
             }
+            if (this.applicationModel != null) {
+                modelAware.setApplicationModel(this.applicationModel);
+            }
             if (this.frameworkModel != null) {
                 modelAware.setFrameworkModel(this.frameworkModel);
             }
         }
         return instance;
     }
+
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
similarity index 66%
rename from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
rename to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
index dafa769..5a78a3f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelAware.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
@@ -16,18 +16,19 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
+import org.apache.dubbo.common.extension.SPI;
+
 /**
- * Interface to inject FrameworkModel/ApplicationModel/ModuleModel for SPI extension.
+ * A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel)
  */
-public interface ModelAware {
-
-    default void setFrameworkModel(FrameworkModel frameworkModel) {
-    }
-
-    default void setApplicationModel(ApplicationModel applicationModel) {
-    }
+@SPI(scope = ExtensionScope.FRAMEWORK)
+public interface ScopeModelPostProcessor {
 
-    default void setModuleModel(ModuleModel moduleModel) {
-    }
+    /**
+     * Post-process after a scope model is created.
+     * @param scopeModel
+     */
+    void postProcessScopeModel(ScopeModel scopeModel);
 
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java
new file mode 100644
index 0000000..2544012
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.model;
+
+public class ScopeModelUtil {
+
+    public static ApplicationModel getApplicationModel(ScopeModel scopeModel) {
+        if (scopeModel instanceof ApplicationModel) {
+            return (ApplicationModel) scopeModel;
+        } else if (scopeModel instanceof ModuleModel) {
+            ModuleModel moduleModel = (ModuleModel) scopeModel;
+            return moduleModel.getApplicationModel();
+        }
+        return null;
+    }
+
+    public static ModuleModel getModuleModel(ScopeModel scopeModel) {
+        if (scopeModel instanceof ModuleModel) {
+            return (ModuleModel) scopeModel;
+        }
+        return null;
+    }
+
+    public static FrameworkModel getFrameworkModel(ScopeModel scopeModel) {
+        if (scopeModel instanceof ApplicationModel) {
+            return ((ApplicationModel) scopeModel).getFrameworkModel();
+        } else if (scopeModel instanceof ModuleModel) {
+            ModuleModel moduleModel = (ModuleModel) scopeModel;
+            return moduleModel.getApplicationModel().getFrameworkModel();
+        } else if (scopeModel instanceof FrameworkModel) {
+            return (FrameworkModel) scopeModel;
+        }
+        return null;
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceRepository.java
index 7567dcd..a004d5a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceRepository.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceRepository.java
@@ -19,7 +19,8 @@ package org.apache.dubbo.rpc.model;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.context.FrameworkExt;
 import org.apache.dubbo.common.context.LifecycleAdapter;
-import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionAccessorAware;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConcurrentHashSet;
 import org.apache.dubbo.common.utils.StringUtils;
@@ -37,7 +38,7 @@ import java.util.concurrent.ConcurrentMap;
 import static org.apache.dubbo.common.BaseServiceMetadata.interfaceFromServiceKey;
 import static org.apache.dubbo.common.BaseServiceMetadata.versionFromServiceKey;
 
-public class ServiceRepository extends LifecycleAdapter implements FrameworkExt {
+public class ServiceRepository extends LifecycleAdapter implements FrameworkExt, ExtensionAccessorAware {
 
     public static final String NAME = "repository";
 
@@ -55,10 +56,15 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
 
     // useful to find a url quickly with serviceInterfaceName:version
     private ConcurrentMap<String, Set<URL>> providerUrlsWithoutGroup = new ConcurrentHashMap<>();
+    private ExtensionAccessor extensionAccessor;
 
     public ServiceRepository() {
+    }
+
+    @Override
+    public void initialize() throws IllegalStateException {
         Set<BuiltinServiceDetector> builtinServices
-            = ExtensionLoader.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
+            = extensionAccessor.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
         if (CollectionUtils.isNotEmpty(builtinServices)) {
             for (BuiltinServiceDetector service : builtinServices) {
                 registerService(service.getService());
@@ -213,4 +219,9 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
         providers.clear();
         providersWithoutGroup.clear();
     }
+
+    @Override
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
 }
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
index d524580..a6ef1e3 100644
--- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
@@ -1,2 +1,3 @@
 adaptive=org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector
 spi=org.apache.dubbo.common.extension.inject.SpiExtensionInjector
+scopeBean=org.apache.dubbo.common.beans.ScopeBeanExtensionInjector
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java
index 9e8991d..7af1663 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java
@@ -16,8 +16,9 @@
  */
 package org.apache.dubbo.common.config.configcenter.file;
 
-import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.config.ConfigurationUtils;
 
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -31,6 +32,6 @@ public class FileSystemDynamicConfigurationFactoryTest {
 
     @Test
     public void testGetFactory() {
-        assertEquals(FileSystemDynamicConfigurationFactory.class, DynamicConfigurationFactory.getDynamicConfigurationFactory("file").getClass());
+        assertEquals(FileSystemDynamicConfigurationFactory.class, ConfigurationUtils.getDynamicConfigurationFactory(ApplicationModel.defaultModel(), "file").getClass());
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java
index b9b80b2..1e474eb 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java
@@ -271,7 +271,6 @@ public class ExtensionLoaderTest {
 
         assertThat(ext, instanceOf(AddExt1_ManualAdd1.class));
         assertEquals("Manual1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd1.class));
-        ExtensionLoader.resetExtensionLoader(AddExt1.class);
     }
 
     @Test
@@ -282,7 +281,6 @@ public class ExtensionLoaderTest {
 
         assertThat(ext, instanceOf(Ext9Empty.class));
         assertEquals("ext9", getExtensionLoader(Ext9Empty.class).getExtensionName(Ext9EmptyImpl.class));
-        ExtensionLoader.resetExtensionLoader(Ext9Empty.class);
     }
 
     @Test
@@ -304,7 +302,6 @@ public class ExtensionLoaderTest {
 
         AddExt2 adaptive = loader.getAdaptiveExtension();
         assertTrue(adaptive instanceof AddExt2_ManualAdaptive);
-        ExtensionLoader.resetExtensionLoader(AddExt2.class);
     }
 
     @Test
@@ -343,7 +340,6 @@ public class ExtensionLoaderTest {
             assertThat(ext, instanceOf(AddExt1_ManualAdd2.class));
             assertEquals("impl1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd2.class));
         }
-        ExtensionLoader.resetExtensionLoader(AddExt1.class);
     }
 
     @Test
@@ -357,7 +353,6 @@ public class ExtensionLoaderTest {
 
         adaptive = loader.getAdaptiveExtension();
         assertTrue(adaptive instanceof AddExt3_ManualAdaptive);
-        ExtensionLoader.resetExtensionLoader(AddExt3.class);
     }
 
     @Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/BaseTestService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/BaseTestService.java
index c3399b8..e3171a4 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/BaseTestService.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/BaseTestService.java
@@ -18,10 +18,10 @@ package org.apache.dubbo.common.extension.director.impl;
 
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
-import org.apache.dubbo.rpc.model.ModelAware;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 import org.apache.dubbo.rpc.model.ModuleModel;
 
-public class BaseTestService implements ModelAware {
+public class BaseTestService implements ScopeModelAware {
     private FrameworkModel frameworkModel;
     private ApplicationModel applicationModel;
     private ModuleModel moduleModel;
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 3c2dfe2..d06574c 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
@@ -40,7 +40,6 @@ import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
 import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
 import org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
 import org.apache.dubbo.rpc.model.ServiceRepository;
 import org.apache.dubbo.rpc.model.AsyncMethodInfo;
@@ -104,13 +103,13 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
      * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
      * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
      */
-    private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+    private Protocol protocolSPI;
 
     /**
      * A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
      * its default implementation
      */
-    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    private ProxyFactory proxyFactory;
 
     /**
      * The interface proxy reference
@@ -149,6 +148,14 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         super(reference);
     }
 
+    @Override
+    protected void initExtensions() {
+        super.initExtensions();
+
+        protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+        proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    }
+
     /**
      * Get a string presenting the service names that the Dubbo interface subscribed.
      * If it is a multiple-values, the content will be a comma-delimited String.
@@ -248,7 +255,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         Map<String, String> referenceParameters = appendConfig();
 
 
-        ServiceRepository repository = ApplicationModel.defaultModel().getServiceRepository();
+        ServiceRepository repository = getApplicationModel().getServiceRepository();
         ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass);
         repository.registerConsumer(
             serviceMetadata.getServiceKey(),
@@ -386,7 +393,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         MetadataUtils.publishServiceDefinition(consumerUrl);
 
         // create service proxy
-        return (T) PROXY_FACTORY.getProxy(invoker, ProtocolUtils.isGeneric(generic));
+        return (T) proxyFactory.getProxy(invoker, ProtocolUtils.isGeneric(generic));
     }
 
     /**
@@ -396,7 +403,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
      */
     private void createInvokerForLocal(Map<String, String> referenceParameters) {
         URL url = new ServiceConfigURL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(referenceParameters);
-        invoker = REF_PROTOCOL.refer(interfaceClass, url);
+        invoker = protocolSPI.refer(interfaceClass, url);
         if (logger.isInfoEnabled()) {
             logger.info("Using in jvm service " + interfaceClass.getName());
         }
@@ -454,14 +461,14 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void createInvokerForRemote() {
         if (urls.size() == 1) {
-            invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
+            invoker = protocolSPI.refer(interfaceClass, urls.get(0));
         } else {
             List<Invoker<?>> invokers = new ArrayList<>();
             URL registryUrl = null;
             for (URL url : urls) {
                 // For multi-registry scenarios, it is not checked whether each referInvoker is available.
                 // Because this invoker may become available later.
-                invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
+                invokers.add(protocolSPI.refer(interfaceClass, url));
 
                 if (UrlUtils.isRegistry(url)) {
                     // use last registry url
@@ -516,7 +523,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         completeCompoundConfigs();
 
         // init some null configuration.
-        List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
+        List<ConfigInitializer> configInitializers = this.getExtensionLoader(ConfigInitializer.class)
             .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
         configInitializers.forEach(e -> e.initReferConfig(this));
 
@@ -592,7 +599,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
     }
 
     private void postProcessConfig() {
-        List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
+        List<ConfigPostProcessor> configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class)
             .getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
         configPostProcessors.forEach(component -> component.postProcessReferConfig(this));
     }
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 575633a..f94d0aa 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
@@ -36,13 +36,13 @@ import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.config.utils.ConfigValidationUtils;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.ServiceNameMapping;
+import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.client.metadata.MetadataUtils;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
 import org.apache.dubbo.rpc.model.ServiceRepository;
 import org.apache.dubbo.rpc.service.GenericService;
@@ -116,13 +116,13 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
      */
     private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
 
-    private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+    private Protocol protocolSPI;
 
     /**
      * A {@link ProxyFactory} implementation that will generate a exported service proxy,the JavassistProxyFactory is its
      * default implementation
      */
-    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    private ProxyFactory proxyFactory;
 
     /**
      * Whether the provider has been exported
@@ -144,6 +144,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
 
     private List<ServiceListener> serviceListeners = new ArrayList<>();
+    private WritableMetadataService localMetadataService;
 
     public ServiceConfig() {
     }
@@ -152,6 +153,13 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         super(service);
     }
 
+    @Override
+    protected void initExtensions() {
+        super.initExtensions();
+        protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+        proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+        localMetadataService = this.getScopeModel().getDefaultExtension(WritableMetadataService.class);
+    }
 
     @Override
     @Parameter(excluded = true, attribute = false)
@@ -197,7 +205,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             this.bootstrap.service(this);
 
             // load ServiceListeners from extension
-            ExtensionLoader<ServiceListener> extensionLoader = ExtensionLoader.getExtensionLoader(ServiceListener.class);
+            ExtensionLoader<ServiceListener> extensionLoader = this.getExtensionLoader(ServiceListener.class);
             this.serviceListeners.addAll(extensionLoader.getSupportedExtensionInstances());
 
             this.checkAndUpdateSubConfigs();
@@ -259,7 +267,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         checkProtocol();
 
         // init some null configuration.
-        List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
+        List<ConfigInitializer> configInitializers = this.getExtensionLoader(ConfigInitializer.class)
                 .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
         configInitializers.forEach(e -> e.initServiceConfig(this));
 
@@ -345,7 +353,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void doExportUrls() {
-        ServiceRepository repository = ApplicationModel.defaultModel().getServiceRepository();
+        ServiceRepository repository = getApplicationModel().getServiceRepository();
         ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass());
         repository.registerProvider(
                 getUniqueServiceName(),
@@ -522,9 +530,9 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         URL url = new ServiceConfigURL(name, null, null, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), params);
 
         // You can customize Configurator to append extra parameters
-        if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
+        if (this.getExtensionLoader(ConfiguratorFactory.class)
                 .hasExtension(url.getProtocol())) {
-            url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
+            url = this.getExtensionLoader(ConfiguratorFactory.class)
                     .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
         }
 
@@ -589,7 +597,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         } else {
 
             if (MetadataService.class.getName().equals(url.getServiceInterface())) {
-                MetadataUtils.saveMetadataURL(url);
+                localMetadataService.setMetadataServiceURL(url);
             }
 
             if (logger.isInfoEnabled()) {
@@ -605,11 +613,11 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void doExportUrl(URL url, boolean withMetaData) {
-        Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
+        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
         if (withMetaData) {
             invoker = new DelegateProviderMetaDataInvoker(invoker, this);
         }
-        Exporter<?> exporter = PROTOCOL.export(invoker);
+        Exporter<?> exporter = protocolSPI.export(invoker);
         exporters.add(exporter);
     }
 
@@ -739,7 +747,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             if (provider != null && (portToBind == null || portToBind == 0)) {
                 portToBind = provider.getPort();
             }
-            final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
+            final int defaultPort = this.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
             if (portToBind == null || portToBind == 0) {
                 portToBind = defaultPort;
             }
@@ -804,7 +812,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     }
 
     private void postProcessConfig() {
-        List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
+        List<ConfigPostProcessor> configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class)
                 .getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
         configPostProcessors.forEach(component -> component.postProcessServiceConfig(this));
     }
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 30bd5f3..0aaa3c3 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
@@ -17,12 +17,14 @@
 package org.apache.dubbo.config.bootstrap;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
 import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
 import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
 import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.extension.ExtensionDirector;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
 import org.apache.dubbo.common.logger.Logger;
@@ -68,7 +70,6 @@ import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.metadata.MetadataUtils;
 import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
 import org.apache.dubbo.registry.client.metadata.store.InMemoryWritableMetadataService;
 import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl;
@@ -76,6 +77,7 @@ import org.apache.dubbo.registry.support.AbstractRegistryFactory;
 import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
 
 import java.io.IOException;
 import java.util.ArrayList;
@@ -102,12 +104,10 @@ import static java.lang.String.format;
 import static java.util.Collections.singletonList;
 import static java.util.concurrent.Executors.newSingleThreadExecutor;
 import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
-import static org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory.getDynamicConfigurationFactory;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
 import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
 import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
 import static org.apache.dubbo.common.function.ThrowableAction.execute;
 import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
 import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
@@ -161,7 +161,7 @@ public class DubboBootstrap {
 
     private final ExecutorService executorService = newSingleThreadExecutor();
 
-    private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+    private ExecutorRepository executorRepository;
 
     private final ApplicationModel applicationModel;
 
@@ -200,6 +200,7 @@ public class DubboBootstrap {
     private boolean asyncReferFinish = true;
 
     private static boolean ignoreConfigState;
+    private Module currentModule;
 
     /**
      * See {@link ApplicationModel} and {@link ExtensionLoader} for why DubboBootstrap is designed to be singleton.
@@ -262,8 +263,21 @@ public class DubboBootstrap {
         configManager = applicationModel.getConfigManager();
         environment = applicationModel.getEnvironment();
 
+        executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
         DubboShutdownHook.getDubboShutdownHook().register();
         ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy);
+
+        initInternalBeans();
+    }
+
+    /**
+     * TODO init beans module-self
+     */
+    private void initInternalBeans() {
+        ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
+
+        beanFactory.registerBean(MetadataReportInstance.class);
+        beanFactory.registerBean(RemoteMetadataServiceImpl.class);
     }
 
     public ApplicationModel getApplicationModel() {
@@ -274,6 +288,14 @@ public class DubboBootstrap {
         return configManager;
     }
 
+    public ExtensionDirector getExtensionDirector() {
+        return applicationModel.getExtensionDirector();
+    }
+
+    public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+        return applicationModel.getExtensionLoader(type);
+    }
+
     public void unRegisterShutdownHook() {
         DubboShutdownHook.getDubboShutdownHook().unregister();
     }
@@ -339,6 +361,7 @@ public class DubboBootstrap {
      * @return current {@link DubboBootstrap} instance
      */
     public DubboBootstrap application(ApplicationConfig applicationConfig) {
+        applicationConfig.setScopeModel(applicationModel);
         configManager.setApplication(applicationConfig);
         return this;
     }
@@ -376,6 +399,7 @@ public class DubboBootstrap {
      * @return current {@link DubboBootstrap} instance
      */
     public DubboBootstrap registry(RegistryConfig registryConfig) {
+        registryConfig.setScopeModel(applicationModel);
         configManager.addRegistry(registryConfig);
         return this;
     }
@@ -414,70 +438,71 @@ public class DubboBootstrap {
         if (CollectionUtils.isEmpty(protocolConfigs)) {
             return this;
         }
-        configManager.addProtocols(protocolConfigs);
+        for (ProtocolConfig protocolConfig : protocolConfigs) {
+            protocolConfig.setScopeModel(applicationModel);
+            configManager.addProtocol(protocolConfig);
+        }
         return this;
     }
 
+    private Module getCurrentModule() {
+        if (currentModule == null) {
+            currentModule = new Module(applicationModel.getDefaultModule());
+        }
+        return currentModule;
+    }
+
     // {@link ServiceConfig} correlative methods
     public <S> DubboBootstrap service(Consumer<ServiceBuilder<S>> consumerBuilder) {
-        return service(DEFAULT_SERVICE_ID, consumerBuilder);
+        getCurrentModule().service(consumerBuilder);
+        return this;
     }
 
     public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
-        ServiceBuilder builder = createServiceBuilder(id);
-        consumerBuilder.accept(builder);
-        return service(builder.build());
+        getCurrentModule().service(id, consumerBuilder);
+        return this;
     }
 
     public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
-        serviceConfig.setBootstrap(this);
-        configManager.addService(serviceConfig);
+        getCurrentModule().service(serviceConfig);
         return this;
     }
 
     public DubboBootstrap services(List<ServiceConfig> serviceConfigs) {
-        if (CollectionUtils.isEmpty(serviceConfigs)) {
-            return this;
-        }
-        serviceConfigs.forEach(configManager::addService);
+        getCurrentModule().services(serviceConfigs);
         return this;
     }
 
     // {@link Reference} correlative methods
     public <S> DubboBootstrap reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
-        return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+        getCurrentModule().reference(consumerBuilder);
+        return this;
     }
 
     public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
-        ReferenceBuilder builder = createReferenceBuilder(id);
-        consumerBuilder.accept(builder);
-        return reference(builder.build());
+        getCurrentModule().reference(id, consumerBuilder);
+        return this;
     }
 
     public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
-        referenceConfig.setBootstrap(this);
-        configManager.addReference(referenceConfig);
+        getCurrentModule().reference(referenceConfig);
         return this;
     }
 
     public DubboBootstrap references(List<ReferenceConfig> referenceConfigs) {
-        if (CollectionUtils.isEmpty(referenceConfigs)) {
-            return this;
-        }
-
-        referenceConfigs.forEach(configManager::addReference);
+        getCurrentModule().references(referenceConfigs);
         return this;
     }
 
     // {@link ProviderConfig} correlative methods
     public DubboBootstrap provider(Consumer<ProviderBuilder> builderConsumer) {
-        return provider(DEFAULT_PROVIDER_ID, builderConsumer);
+        getCurrentModule().provider(builderConsumer);
+        return this;
     }
 
     public DubboBootstrap provider(String id, Consumer<ProviderBuilder> builderConsumer) {
-        ProviderBuilder builder = createProviderBuilder(id);
-        builderConsumer.accept(builder);
-        return provider(builder.build());
+        getCurrentModule().provider(id, builderConsumer);
+        return this;
     }
 
     public DubboBootstrap provider(ProviderConfig providerConfig) {
@@ -485,67 +510,70 @@ public class DubboBootstrap {
     }
 
     public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
-        if (CollectionUtils.isEmpty(providerConfigs)) {
-            return this;
-        }
-
-        providerConfigs.forEach(configManager::addProvider);
+        getCurrentModule().providers(providerConfigs);
         return this;
     }
 
     // {@link ConsumerConfig} correlative methods
     public DubboBootstrap consumer(Consumer<ConsumerBuilder> builderConsumer) {
-        return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+        getCurrentModule().consumer(builderConsumer);
+        return this;
     }
 
     public DubboBootstrap consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
-        ConsumerBuilder builder = createConsumerBuilder(id);
-        builderConsumer.accept(builder);
-        return consumer(builder.build());
+        getCurrentModule().consumer(id, builderConsumer);
+        return this;
     }
 
     public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
-        return consumers(singletonList(consumerConfig));
+        getCurrentModule().consumer(consumerConfig);
+        return this;
     }
 
     public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
-        if (CollectionUtils.isEmpty(consumerConfigs)) {
-            return this;
-        }
-
-        consumerConfigs.forEach(configManager::addConsumer);
+        getCurrentModule().consumers(consumerConfigs);
         return this;
     }
+    // module configs end
 
     // {@link ConfigCenterConfig} correlative methods
     public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
-        return configCenters(singletonList(configCenterConfig));
+        configCenterConfig.setScopeModel(applicationModel);
+        configManager.addConfigCenter(configCenterConfig);
+        return this;
     }
 
     public DubboBootstrap configCenters(List<ConfigCenterConfig> configCenterConfigs) {
         if (CollectionUtils.isEmpty(configCenterConfigs)) {
             return this;
         }
-        configManager.addConfigCenters(configCenterConfigs);
+        for (ConfigCenterConfig configCenterConfig : configCenterConfigs) {
+            this.configCenter(configCenterConfig);
+        }
         return this;
     }
 
     public DubboBootstrap monitor(MonitorConfig monitor) {
+        monitor.setScopeModel(applicationModel);
         configManager.setMonitor(monitor);
         return this;
     }
 
     public DubboBootstrap metrics(MetricsConfig metrics) {
+        metrics.setScopeModel(applicationModel);
         configManager.setMetrics(metrics);
         return this;
     }
 
     public DubboBootstrap module(ModuleConfig module) {
+        //TODO module config?
+        module.setScopeModel(applicationModel);
         configManager.setModule(module);
         return this;
     }
 
     public DubboBootstrap ssl(SslConfig sslConfig) {
+        sslConfig.setScopeModel(applicationModel);
         configManager.setSsl(sslConfig);
         return this;
     }
@@ -633,7 +661,7 @@ public class DubboBootstrap {
     private <T extends AbstractConfig> void checkDefaultAndValidateConfigs(Class<T> configType) {
         try {
             if (shouldAddDefaultConfig(configType)) {
-                T config = configType.newInstance();
+                T config = createConfig(configType);
                 config.refresh();
                 if (!isNeedValidation(config) || config.isValid()) {
                     configManager.addConfig(config);
@@ -735,6 +763,7 @@ public class DubboBootstrap {
         Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
         if (CollectionUtils.isEmpty(configCenters)) {
             ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
+            configCenterConfig.setScopeModel(applicationModel);
             configCenterConfig.refresh();
             ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
             if (configCenterConfig.isValid()) {
@@ -780,13 +809,14 @@ public class DubboBootstrap {
             return;
         }
 
+        MetadataReportInstance metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
         for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
             ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
             if (!metadataReportConfig.isValid()) {
                 logger.info("Ignore invalid metadata-report config: " + metadataReportConfig);
                 continue;
             }
-            MetadataReportInstance.init(metadataReportConfig);
+            metadataReportInstance.init(metadataReportConfig);
         }
     }
 
@@ -837,6 +867,7 @@ public class DubboBootstrap {
         String id = "config-center-" + protocol + "-" + url.getHost() + "-" + port;
         ConfigCenterConfig cc = new ConfigCenterConfig();
         cc.setId(id);
+        cc.setScopeModel(applicationModel);
         if (cc.getParameters() == null) {
             cc.setParameters(new HashMap<>());
         }
@@ -946,6 +977,7 @@ public class DubboBootstrap {
         String id = "metadata-center-" + protocol + "-" + url.getHost() + "-" + url.getPort();
         MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
         metadataReportConfig.setId(id);
+        metadataReportConfig.setScopeModel(applicationModel);
         if (metadataReportConfig.getParameters() == null) {
             metadataReportConfig.setParameters(new HashMap<>());
         }
@@ -1026,7 +1058,7 @@ public class DubboBootstrap {
             if (!configManager.getConfig(cls, id).isPresent()) {
                 T config = null;
                 try {
-                    config = cls.newInstance();
+                    config = createConfig(cls);
                     config.setId(id);
                 } catch (Exception e) {
                     throw new IllegalStateException("create config instance failed, id: " + id + ", type:" + cls.getSimpleName());
@@ -1062,7 +1094,7 @@ public class DubboBootstrap {
             if (ConfigurationUtils.hasSubProperties(configurationMaps, AbstractConfig.getTypePrefix(cls))) {
                 T config = null;
                 try {
-                    config = cls.newInstance();
+                    config = createConfig(cls);
                     config.refresh();
                 } catch (Exception e) {
                     throw new IllegalStateException("create default config instance failed, type:" + cls.getSimpleName());
@@ -1074,6 +1106,17 @@ public class DubboBootstrap {
 
     }
 
+    private <T extends AbstractConfig> T createConfig(Class<T> cls) throws InstantiationException, IllegalAccessException {
+        T config = cls.newInstance();
+        if (config instanceof ProviderConfig || config instanceof ConsumerConfig || config instanceof ReferenceConfigBase
+            || config instanceof ServiceConfigBase) {
+            config.setScopeModel(getCurrentModule().moduleModel);
+        } else {
+            config.setScopeModel(applicationModel);
+        }
+        return config;
+    }
+
     /**
      * Search props and extract config ids of specify type.
      * <pre>
@@ -1110,7 +1153,7 @@ public class DubboBootstrap {
      */
     public synchronized DubboBootstrap start() {
         // avoid re-entry start method multiple times in same thread
-        if (isCurrentlyInStart){
+        if (isCurrentlyInStart) {
             return this;
         }
 
@@ -1375,7 +1418,8 @@ public class DubboBootstrap {
      */
     private DynamicConfiguration getDynamicConfiguration(URL connectionURL) {
         String protocol = connectionURL.getProtocol();
-        DynamicConfigurationFactory factory = getDynamicConfigurationFactory(protocol);
+
+        DynamicConfigurationFactory factory = ConfigurationUtils.getDynamicConfigurationFactory(applicationModel, protocol);
         return factory.getDynamicConfiguration(connectionURL);
     }
 
@@ -1388,9 +1432,9 @@ public class DubboBootstrap {
 
     private void unexportMetadataService() {
         if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
-            try{
+            try {
                 metadataServiceExporter.unexport();
-            }catch (Exception ignored){
+            } catch (Exception ignored) {
                 // ignored
             }
         }
@@ -1432,10 +1476,10 @@ public class DubboBootstrap {
 
     private void unexportServices() {
         exportedServices.forEach(sc -> {
-            try{
+            try {
                 configManager.removeConfig(sc);
                 sc.unexport();
-            }catch (Exception ignored){
+            } catch (Exception ignored) {
                 // ignored
             }
         });
@@ -1482,7 +1526,7 @@ public class DubboBootstrap {
     }
 
     private void unreferServices() {
-        try{
+        try {
             if (cache == null) {
                 cache = ReferenceConfigCache.getCache();
             }
@@ -1494,7 +1538,7 @@ public class DubboBootstrap {
             });
             asyncReferringFutures.clear();
             cache.destroyAll();
-        }catch (Exception ignored){
+        } catch (Exception ignored) {
         }
     }
 
@@ -1513,7 +1557,7 @@ public class DubboBootstrap {
             registered = false;
             logger.error("Register instance error", e);
         }
-        if(registered){
+        if (registered) {
             // scheduled task for updating Metadata and ServiceInstance
             executorRepository.nextScheduledExecutor().scheduleAtFixedRate(() -> {
                 InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension();
@@ -1553,16 +1597,16 @@ public class DubboBootstrap {
         if (logger.isInfoEnabled()) {
             logger.info("Start publishing metadata to remote center, this only makes sense for applications enabled remote metadata center.");
         }
-        RemoteMetadataServiceImpl remoteMetadataService = MetadataUtils.getRemoteMetadataService();
+        RemoteMetadataServiceImpl remoteMetadataService = applicationModel.getBeanFactory().getBean(RemoteMetadataServiceImpl.class);
         remoteMetadataService.publishMetadata(serviceInstance.getServiceName());
     }
 
     private void unregisterServiceInstance() {
         if (serviceInstance != null) {
             getServiceDiscoveries().forEach(serviceDiscovery -> {
-                try{
+                try {
                     serviceDiscovery.unregister(serviceInstance);
-                }catch (Exception ignored){
+                } catch (Exception ignored) {
                     // ignored
                 }
             });
@@ -1606,10 +1650,10 @@ public class DubboBootstrap {
 
                 destroyDynamicConfigurations();
                 ShutdownHookCallbacks.INSTANCE.clear();
-            }catch (Throwable ignored){
+            } catch (Throwable ignored) {
                 // ignored
-                logger.warn(ignored.getMessage(),ignored);
-            }finally {
+                logger.warn(ignored.getMessage(), ignored);
+            } finally {
                 initialized.set(false);
                 startup.set(false);
                 destroyLock.unlock();
@@ -1640,7 +1684,7 @@ public class DubboBootstrap {
     }
 
     private void destroyExecutorRepository() {
-        ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
+        getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
     }
 
     private void destroyRegistries() {
@@ -1651,7 +1695,7 @@ public class DubboBootstrap {
      * Destroy all the protocols.
      */
     private void destroyProtocols() {
-        ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
+        ExtensionLoader<Protocol> loader = getExtensionLoader(Protocol.class);
         for (String protocolName : loader.getLoadedExtensions()) {
             try {
                 Protocol protocol = loader.getLoadedExtension(protocolName);
@@ -1666,10 +1710,10 @@ public class DubboBootstrap {
 
     private void destroyServiceDiscoveries() {
         getServiceDiscoveries().forEach(serviceDiscovery -> {
-            try{
+            try {
                 execute(serviceDiscovery::destroy);
-            }catch (Throwable ignored){
-                logger.warn(ignored.getMessage(),ignored);
+            } catch (Throwable ignored) {
+                logger.warn(ignored.getMessage(), ignored);
             }
         });
         if (logger.isDebugEnabled()) {
@@ -1680,13 +1724,12 @@ public class DubboBootstrap {
     private void destroyMetadataReports() {
         AbstractMetadataReportFactory.destroy();
         MetadataReportInstance.reset();
-        ExtensionLoader.resetExtensionLoader(MetadataReportFactory.class);
     }
 
     private void destroyDynamicConfigurations() {
         // DynamicConfiguration may be cached somewhere, and maybe used during destroy
         // destroy them may cause some troubles, so just clear instances cache
-        ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
+        // ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
     }
 
     private void clear() {
@@ -1719,11 +1762,11 @@ public class DubboBootstrap {
     private void shutdown() {
         if (!executorService.isShutdown()) {
             // Shutdown executorService
-            try{
+            try {
                 executorService.shutdown();
-            }catch (Throwable ignored){
+            } catch (Throwable ignored) {
                 // ignored
-                logger.warn(ignored.getMessage(),ignored);
+                logger.warn(ignored.getMessage(), ignored);
             }
         }
     }
@@ -1749,4 +1792,134 @@ public class DubboBootstrap {
     public BootstrapTakeoverMode getTakeoverMode() {
         return takeoverMode;
     }
+
+    public Module addModule(ModuleModel moduleModel) {
+        applicationModel.addModule(moduleModel);
+        currentModule = new Module(moduleModel);
+        return currentModule;
+    }
+
+    public DubboBootstrap endModule() {
+        currentModule = new Module(applicationModel.getDefaultModule());
+        return this;
+    }
+
+    public class Module {
+        private ModuleModel moduleModel;
+        private DubboBootstrap bootstrap;
+
+        public Module(ModuleModel moduleModel) {
+            this.moduleModel = moduleModel;
+            this.bootstrap = DubboBootstrap.this;
+        }
+
+        public DubboBootstrap endModule() {
+            return this.bootstrap.endModule();
+        }
+
+        // {@link ServiceConfig} correlative methods
+        public <S> Module service(Consumer<ServiceBuilder<S>> consumerBuilder) {
+            return service(DEFAULT_SERVICE_ID, consumerBuilder);
+        }
+
+        public <S> Module service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
+            ServiceBuilder builder = createServiceBuilder(id);
+            consumerBuilder.accept(builder);
+            return service(builder.build());
+        }
+
+        public Module service(ServiceConfig<?> serviceConfig) {
+            serviceConfig.setBootstrap(this.bootstrap);
+            serviceConfig.setScopeModel(moduleModel);
+            configManager.addService(serviceConfig);
+            return this;
+        }
+
+        public Module services(List<ServiceConfig> serviceConfigs) {
+            if (CollectionUtils.isEmpty(serviceConfigs)) {
+                return this;
+            }
+            serviceConfigs.forEach(configManager::addService);
+            return this;
+        }
+
+        // {@link Reference} correlative methods
+        public <S> Module reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
+            return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+        }
+
+        public <S> Module reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
+            ReferenceBuilder builder = createReferenceBuilder(id);
+            consumerBuilder.accept(builder);
+            return reference(builder.build());
+        }
+
+        public Module reference(ReferenceConfig<?> referenceConfig) {
+            referenceConfig.setBootstrap(this.bootstrap);
+            referenceConfig.setScopeModel(moduleModel);
+            configManager.addReference(referenceConfig);
+            return this;
+        }
+
+        public Module references(List<ReferenceConfig> referenceConfigs) {
+            if (CollectionUtils.isEmpty(referenceConfigs)) {
+                return this;
+            }
+
+            referenceConfigs.forEach(configManager::addReference);
+            return this;
+        }
+
+        // {@link ProviderConfig} correlative methods
+        public Module provider(Consumer<ProviderBuilder> builderConsumer) {
+            return provider(DEFAULT_PROVIDER_ID, builderConsumer);
+        }
+
+        public Module provider(String id, Consumer<ProviderBuilder> builderConsumer) {
+            ProviderBuilder builder = createProviderBuilder(id);
+            builderConsumer.accept(builder);
+            return provider(builder.build());
+        }
+
+        public Module provider(ProviderConfig providerConfig) {
+            return providers(singletonList(providerConfig));
+        }
+
+        public Module providers(List<ProviderConfig> providerConfigs) {
+            if (CollectionUtils.isEmpty(providerConfigs)) {
+                return this;
+            }
+            for (ProviderConfig providerConfig : providerConfigs) {
+                providerConfig.setScopeModel(moduleModel);
+                configManager.addProvider(providerConfig);
+            }
+            return this;
+        }
+
+        // {@link ConsumerConfig} correlative methods
+        public Module consumer(Consumer<ConsumerBuilder> builderConsumer) {
+            return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+        }
+
+        public Module consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
+            ConsumerBuilder builder = createConsumerBuilder(id);
+            builderConsumer.accept(builder);
+            return consumer(builder.build());
+        }
+
+        public Module consumer(ConsumerConfig consumerConfig) {
+            return consumers(singletonList(consumerConfig));
+        }
+
+        public Module consumers(List<ConsumerConfig> consumerConfigs) {
+            if (CollectionUtils.isEmpty(consumerConfigs)) {
+                return this;
+            }
+            for (ConsumerConfig consumerConfig : consumerConfigs) {
+                consumerConfig.setScopeModel(moduleModel);
+                configManager.addConsumer(consumerConfig);
+            }
+            return this;
+        }
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
index 858fb75..711aa01 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
@@ -16,6 +16,12 @@
  */
 package org.apache.dubbo.config.bootstrap;
 
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.junit.jupiter.api.Assertions;
@@ -34,18 +40,37 @@ public class DubboBootstrapMultiInstanceTest {
         Assertions.assertNotSame(applicationModel1.getFrameworkModel(), applicationModel2.getFrameworkModel());
         Assertions.assertNotSame(dubboBootstrap1.getConfigManager(), dubboBootstrap2.getConfigManager());
 
-//        dubboBootstrap1.application("app1")
-//            .registry(registry1)
-//            .configCenter(configCenter1)
-//            .metadataReport(metadataReport1)
-//            .protocol(protocol1)
-//            .provider(provider1)
-//            .consumer(consumer1)
-//            .monitor(monitor1)
-//            .metrics(metrics1)
-//            .ssl(sslConfig1);
-//
+        // bootstrap1: provider app
+        RegistryConfig registry1 = new RegistryConfig();
+        registry1.setAddress("zookeeper://localhost:2181");
 
+        ProtocolConfig protocol1 = new ProtocolConfig();
+        protocol1.setName("dubbo");
+        protocol1.setPort(2001);
+
+        ServiceConfig<DemoService> serviceConfig = new ServiceConfig<>();
+        serviceConfig.setInterface(DemoService.class);
+        serviceConfig.setRef(new DemoServiceImpl());
+
+        dubboBootstrap1.application("provider-app")
+            .registry(registry1)
+            .protocol(protocol1)
+            .service(serviceConfig)
+            .start();
+
+
+        // bootstrap2: consumer app
+        ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
+        referenceConfig.setInterface(DemoService.class);
+
+        dubboBootstrap2.application("consumer-app")
+            .registry(new RegistryConfig("zookeeper://localhost:2181"))
+            .reference(referenceConfig)
+            .start();
+
+        DemoService demoServiceRefer = dubboBootstrap2.getCache().get(DemoService.class);
+        String result = demoServiceRefer.sayName("dubbo");
+        System.out.println("result: " + result);
     }
 
     @Test
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index fcd888f..e692658 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
@@ -32,7 +33,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
  *
  * @since 2.7.5
  */
-@SPI("default")
+@SPI(value = "default", scope = ExtensionScope.APPLICATION)
 public interface WritableMetadataService extends MetadataService {
     /**
      * Gets the current Dubbo Service name
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
index 8c6576f..9bc3cb0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
@@ -36,15 +36,17 @@ import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT
  */
 public class MetadataReportInstance {
 
-    private static AtomicBoolean init = new AtomicBoolean(false);
+    private AtomicBoolean init = new AtomicBoolean(false);
 
-    private static final Map<String, MetadataReport> metadataReports = new HashMap<>();
+    private final Map<String, MetadataReport> metadataReports = new HashMap<>();
 
-    public static void init(MetadataReportConfig config) {
+    public void init(MetadataReportConfig config) {
         if (init.get()) {
             return;
         }
-        MetadataReportFactory metadataReportFactory = ExtensionLoader.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension();
+        ApplicationModel applicationModel = config.getApplicationModel();
+
+        MetadataReportFactory metadataReportFactory = applicationModel.getExtensionLoader(MetadataReportFactory.class).getAdaptiveExtension();
         URL url = config.toUrl();
         if (METADATA_REPORT_KEY.equals(url.getProtocol())) {
             String protocol = url.getParameter(METADATA_REPORT_KEY, DEFAULT_DIRECTORY);
@@ -53,22 +55,22 @@ public class MetadataReportInstance {
                     .removeParameter(METADATA_REPORT_KEY)
                     .build();
         }
-        url = url.addParameterIfAbsent(APPLICATION_KEY, ApplicationModel.defaultModel().getApplicationConfig().getName());
+        url = url.addParameterIfAbsent(APPLICATION_KEY, applicationModel.getApplicationConfig().getName());
         String relatedRegistryId = config.getRegistry() == null ? DEFAULT_KEY : config.getRegistry();
-//        RegistryConfig registryConfig = ApplicationModel.defaultModel().getConfigManager().getRegistry(relatedRegistryId)
+//        RegistryConfig registryConfig = applicationModel.getConfigManager().getRegistry(relatedRegistryId)
 //                .orElseThrow(() -> new IllegalStateException("Registry id " + relatedRegistryId + " does not exist."));
         metadataReports.put(relatedRegistryId, metadataReportFactory.getMetadataReport(url));
         init.set(true);
     }
 
-    public static Map<String, MetadataReport> getMetadataReports(boolean checked) {
+    public Map<String, MetadataReport> getMetadataReports(boolean checked) {
         if (checked) {
             checkInit();
         }
         return metadataReports;
     }
 
-    public static MetadataReport getMetadataReport(String registryKey) {
+    public MetadataReport getMetadataReport(String registryKey) {
         checkInit();
         MetadataReport metadataReport = metadataReports.get(registryKey);
         if (metadataReport == null) {
@@ -78,14 +80,14 @@ public class MetadataReportInstance {
     }
 
 
-    private static void checkInit() {
+    private void checkInit() {
         if (!init.get()) {
             throw new IllegalStateException("the metadata report was not inited.");
         }
     }
 
     public static void reset() {
-        metadataReports.clear();
-        init.set(false);
+//        metadataReports.clear();
+//        init.set(false);
     }
 }
diff --git a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
index 4015339..d46462e 100644
--- a/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
+++ b/dubbo-monitor/dubbo-monitor-default/src/main/java/org/apache/dubbo/monitor/dubbo/MetricsFilter.java
@@ -17,7 +17,8 @@
 package org.apache.dubbo.monitor.dubbo;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionAccessorAware;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.store.DataStore;
@@ -67,12 +68,13 @@ import static org.apache.dubbo.monitor.Constants.DUBBO_PROVIDER_METHOD;
 import static org.apache.dubbo.monitor.Constants.METHOD;
 import static org.apache.dubbo.monitor.Constants.SERVICE;
 
-public class MetricsFilter implements Filter {
+public class MetricsFilter implements Filter, ExtensionAccessorAware {
 
     private static final Logger logger = LoggerFactory.getLogger(MetricsFilter.class);
     protected static volatile AtomicBoolean exported = new AtomicBoolean(false);
     private Integer port;
     private String protocolName;
+    private ExtensionAccessor extensionAccessor;
 
     @Override
     public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
@@ -80,7 +82,7 @@ public class MetricsFilter implements Filter {
             this.protocolName = invoker.getUrl().getParameter(METRICS_PROTOCOL) == null ?
                     DEFAULT_PROTOCOL : invoker.getUrl().getParameter(METRICS_PROTOCOL);
 
-            Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(protocolName);
+            Protocol protocol = extensionAccessor.getExtensionLoader(Protocol.class).getExtension(protocolName);
 
             this.port = invoker.getUrl().getParameter(METRICS_PORT) == null ?
                     protocol.getDefaultPort() : Integer.valueOf(invoker.getUrl().getParameter(METRICS_PORT));
@@ -176,7 +178,7 @@ public class MetricsFilter implements Filter {
     }
 
     private List<MetricObject> getThreadPoolMessage() {
-        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
+        DataStore dataStore = extensionAccessor.getExtensionLoader(DataStore.class).getDefaultExtension();
         Map<String, Object> executors = dataStore.get(EXECUTOR_SERVICE_COMPONENT_KEY);
 
         List<MetricObject> threadPoolMtricList = new ArrayList<>();
@@ -257,4 +259,9 @@ public class MetricsFilter implements Filter {
 
         return metricsInvoker;
     }
+
+    @Override
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java
index bfe2cc4..dd69e02 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java
@@ -29,6 +29,7 @@ import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.registry.client.RegistryClusterIdentifier;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -38,18 +39,20 @@ import java.util.Set;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
 
-public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
+public class MetadataServiceNameMapping extends AbstractServiceNameMapping implements ScopeModelAware {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     private static final List<String> IGNORED_SERVICE_INTERFACES = Collections.singletonList(MetadataService.class.getName());
 
     private static final int CAS_RETRY_TIMES = 6;
+    private MetadataReportInstance metadataReportInstance;
+    private ApplicationModel applicationModel;
 
     @Override
     public void map(URL url) {
         execute(() -> {
-            if (CollectionUtils.isEmpty(ApplicationModel.defaultModel().getConfigManager().getMetadataConfigs())) {
+            if (CollectionUtils.isEmpty(applicationModel.getConfigManager().getMetadataConfigs())) {
                 return;
             }
             String serviceInterface = url.getServiceInterface();
@@ -57,9 +60,9 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
                 return;
             }
             String registryCluster = getRegistryCluster(url);
-            MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
+            MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
 
-            String appName = ApplicationModel.defaultModel().getName();
+            String appName = applicationModel.getName();
             if (metadataReport.registerServiceAppMapping(serviceInterface, appName, url)) {
                 // MetadataReport support directly register service-app mapping
                 return;
@@ -89,7 +92,7 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
         execute(() -> {
             String serviceInterface = url.getServiceInterface();
             String registryCluster = getRegistryCluster(url);
-            MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
+            MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
             Set<String> apps = metadataReport.getServiceAppMapping(serviceInterface, url);
             serviceNames.addAll(apps);
         });
@@ -102,13 +105,19 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
         execute(() -> {
             String serviceInterface = url.getServiceInterface();
             String registryCluster = getRegistryCluster(url);
-            MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
+            MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
             Set<String> apps = metadataReport.getServiceAppMapping(serviceInterface, mappingListener, url);
             serviceNames.addAll(apps);
         });
         return serviceNames;
     }
 
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
+    }
+
     protected String getRegistryCluster(URL url) {
         String registryCluster = RegistryClusterIdentifier.getExtension(url).providerKey(url);
         if (registryCluster == null) {
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 e6f6d68..9200289 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
@@ -55,20 +55,11 @@ public class MetadataUtils {
 
     public static RemoteMetadataServiceImpl remoteMetadataService;
 
-    public static WritableMetadataService localMetadataService;
-
-    public static WritableMetadataService getLocalMetadataService() {
-        if (localMetadataService == null) {
-            localMetadataService = WritableMetadataService.getDefaultExtension();
-        }
-        return localMetadataService;
-    }
-
     public static RemoteMetadataServiceImpl getRemoteMetadataService() {
         if (remoteMetadataService == null) {
             synchronized (REMOTE_LOCK) {
                 if (remoteMetadataService == null) {
-                    remoteMetadataService = new RemoteMetadataServiceImpl(getLocalMetadataService());
+                    remoteMetadataService = new RemoteMetadataServiceImpl();
                 }
             }
         }
@@ -144,8 +135,4 @@ public class MetadataUtils {
         return proxyFactory.getProxy(invoker);
     }
 
-    public static void saveMetadataURL(URL url) {
-        // store in local
-        getLocalMetadataService().setMetadataServiceURL(url);
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
index 4b926fa..fb6233b 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/RemoteMetadataServiceImpl.java
@@ -31,6 +31,8 @@ import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -44,16 +46,19 @@ import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
 import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
 import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
 
-public class RemoteMetadataServiceImpl {
+public class RemoteMetadataServiceImpl implements ScopeModelAware {
     protected final Logger logger = LoggerFactory.getLogger(getClass());
     private WritableMetadataService localMetadataService;
+    private MetadataReportInstance metadataReportInstance;
 
-    public RemoteMetadataServiceImpl(WritableMetadataService writableMetadataService) {
-        this.localMetadataService = writableMetadataService;
+    @Override
+    public void setScopeModel(ScopeModel scopeModel) {
+        metadataReportInstance = scopeModel.getBeanFactory().getBean(MetadataReportInstance.class);
+        localMetadataService = scopeModel.getDefaultExtension(WritableMetadataService.class);
     }
 
     public Map<String, MetadataReport> getMetadataReports() {
-        return MetadataReportInstance.getMetadataReports(false);
+        return metadataReportInstance.getMetadataReports(false);
     }
 
     public void publishMetadata(String serviceName) {