diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/DefaultFilterChainBuilder.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/DefaultFilterChainBuilder.java index e2e26d2a00..478ad661f2 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/DefaultFilterChainBuilder.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/DefaultFilterChainBuilder.java @@ -16,11 +16,12 @@ */ package org.apache.dubbo.rpc.cluster.filter; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.cluster.ClusterInvoker; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.List; @@ -33,7 +34,8 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder { @Override public Invoker buildInvokerChain(final Invoker originalInvoker, String key, String group) { Invoker last = originalInvoker; - List filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(originalInvoker.getUrl(), key, group); + URL url = originalInvoker.getUrl(); + List filters = ScopeModelUtil.getExtensionLoader(Filter.class, url.getScopeModel()).getActivateExtension(url, key, group); if (!filters.isEmpty()) { for (int i = filters.size() - 1; i >= 0; i--) { @@ -52,7 +54,8 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder { @Override public ClusterInvoker buildClusterInvokerChain(final ClusterInvoker originalInvoker, String key, String group) { ClusterInvoker last = originalInvoker; - List filters = ExtensionLoader.getExtensionLoader(ClusterFilter.class).getActivateExtension(originalInvoker.getUrl(), key, group); + URL url = originalInvoker.getUrl(); + List filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, url.getScopeModel()).getActivateExtension(url, key, group); if (!filters.isEmpty()) { for (int i = filters.size() - 1; i >= 0; i--) { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/FilterChainBuilder.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/FilterChainBuilder.java index 949a66c5c4..7edab0899a 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/FilterChainBuilder.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/FilterChainBuilder.java @@ -28,7 +28,9 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.cluster.ClusterInvoker; import org.apache.dubbo.rpc.cluster.Directory; -@SPI("default") +import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION; + +@SPI(value = "default", scope = APPLICATION) public interface FilterChainBuilder { /** * build consumer/provider filter chain diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/ProtocolFilterWrapper.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/ProtocolFilterWrapper.java index 389b173ba6..efbc4540cc 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/ProtocolFilterWrapper.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/ProtocolFilterWrapper.java @@ -19,13 +19,13 @@ package org.apache.dubbo.rpc.cluster.filter; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.rpc.Exporter; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Protocol; import org.apache.dubbo.rpc.ProtocolServer; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.List; @@ -39,8 +39,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.SERVICE_FILTER_K public class ProtocolFilterWrapper implements Protocol { private final Protocol protocol; - private static final FilterChainBuilder builder - = ExtensionLoader.getExtensionLoader(FilterChainBuilder.class).getDefaultExtension(); public ProtocolFilterWrapper(Protocol protocol) { if (protocol == null) { @@ -59,14 +57,20 @@ public class ProtocolFilterWrapper implements Protocol { if (UrlUtils.isRegistry(invoker.getUrl())) { return protocol.export(invoker); } + FilterChainBuilder builder = getFilterChainBuilder(invoker.getUrl()); return protocol.export(builder.buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER)); } + private FilterChainBuilder getFilterChainBuilder(URL url) { + return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel()).getDefaultExtension(); + } + @Override public Invoker refer(Class type, URL url) throws RpcException { if (UrlUtils.isRegistry(url)) { return protocol.refer(type, url); } + FilterChainBuilder builder = getFilterChainBuilder(url); return builder.buildInvokerChain(protocol.refer(type, url), REFERENCE_FILTER_KEY, CommonConstants.CONSUMER); } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/DefaultGovernanceRuleRepositoryImpl.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/DefaultGovernanceRuleRepositoryImpl.java index dfebf27a47..61f8aeb577 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/DefaultGovernanceRuleRepositoryImpl.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/DefaultGovernanceRuleRepositoryImpl.java @@ -19,8 +19,11 @@ package org.apache.dubbo.rpc.cluster.governance; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; -public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository { +public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository, ScopeModelAware { + + private ApplicationModel applicationModel; @Override public void addListener(String key, String group, ConfigurationListener listener) { @@ -47,8 +50,13 @@ public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleReposi return null; } + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } + private DynamicConfiguration getDynamicConfiguration() { - return ApplicationModel.getEnvironment().getDynamicConfiguration().orElse(null); + return ApplicationModel.ofNullable(applicationModel).getApplicationEnvironment().getDynamicConfiguration().orElse(null); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/GovernanceRuleRepository.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/GovernanceRuleRepository.java index aaa604f2ff..d375c8b08c 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/GovernanceRuleRepository.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/governance/GovernanceRuleRepository.java @@ -19,7 +19,9 @@ package org.apache.dubbo.rpc.cluster.governance; import org.apache.dubbo.common.config.configcenter.ConfigurationListener; import org.apache.dubbo.common.extension.SPI; -@SPI("default") +import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION; + +@SPI(value = "default", scope = APPLICATION) public interface GovernanceRuleRepository { String DEFAULT_GROUP = "dubbo"; diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalance.java index 9c0967b977..7f0625a333 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalance.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalance.java @@ -23,6 +23,7 @@ import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcStatus; import org.apache.dubbo.rpc.cluster.Constants; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.List; import java.util.concurrent.ConcurrentHashMap; @@ -41,11 +42,11 @@ import java.util.concurrent.atomic.AtomicBoolean; * if there are multiple invokers and the weights are not the same, then random according to the total weight; * if there are multiple invokers and the same weight, then randomly called. */ -public class ShortestResponseLoadBalance extends AbstractLoadBalance { +public class ShortestResponseLoadBalance extends AbstractLoadBalance implements ScopeModelAware { public static final String NAME = "shortestresponse"; - private static final int SLIDE_PERIOD = ApplicationModel.getEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000); + private int SLIDE_PERIOD = 30_000; private ConcurrentMap methodMap = new ConcurrentHashMap<>(); @@ -53,6 +54,11 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance { private volatile long lastUpdateTime = System.currentTimeMillis(); + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + SLIDE_PERIOD = applicationModel.getApplicationEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000); + } + protected static class SlideWindowData { private final static ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor((new NamedThreadFactory("Dubbo-slidePeriod-reset"))); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java index b07fede897..c64d780b5d 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManager.java @@ -42,7 +42,7 @@ public final class MeshRuleManager { MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener(app); String appRuleDataId = app + MESH_RULE_DATA_ID_SUFFIX; - DynamicConfiguration configuration = ApplicationModel.getEnvironment().getDynamicConfiguration() + DynamicConfiguration configuration = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration() .orElse(null); Set envListenerFactories = ExtensionLoader.getExtensionLoader(MeshEnvListenerFactory.class).getSupportedExtensionInstances(); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java index 4ede912f2d..d2a6ea3d80 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java @@ -48,7 +48,7 @@ public abstract class AbstractCluster implements Cluster { // AbstractClusterInvoker last = clusterInvoker; AbstractClusterInvoker last = buildInterceptorInvoker(new ClusterFilterInvoker<>(clusterInvoker)); - if (Boolean.parseBoolean(ConfigurationUtils.getProperty(CLUSTER_INTERCEPTOR_COMPATIBLE_KEY, "false"))) { + if (Boolean.parseBoolean(ConfigurationUtils.getProperty(clusterInvoker.getDirectory().getConsumerUrl().getScopeModel(), CLUSTER_INTERCEPTOR_COMPATIBLE_KEY, "false"))) { return build27xCompatibleClusterInterceptors(clusterInvoker, last); } return last; 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 f9f9311448..eddd7f6145 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(dic); - ExtensionLoader.resetExtensionLoader(LoadBalance.class); } @Test diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java index 392393744d..75ad1ccc62 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/directory/MockDirInvocation.java @@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.directory; import org.apache.dubbo.rpc.AttachmentsAdapter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.model.ServiceModel; import java.util.HashMap; import java.util.Map; @@ -129,6 +130,16 @@ public class MockDirInvocation implements Invocation { return null; } + @Override + public void setServiceModel(ServiceModel serviceModel) { + + } + + @Override + public ServiceModel getServiceModel() { + return null; + } + @Override public Map getAttributes() { return null; diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalanceTest.java index 345c370c1f..aebaf00067 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalanceTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/ShortestResponseLoadBalanceTest.java @@ -19,6 +19,8 @@ package org.apache.dubbo.rpc.cluster.loadbalance; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcStatus; +import org.apache.dubbo.rpc.model.ApplicationModel; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; @@ -42,6 +44,7 @@ public class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest { int loop = 10000; ShortestResponseLoadBalance lb = new ShortestResponseLoadBalance(); + lb.setApplicationModel(ApplicationModel.defaultModel()); for (int i = 0; i < loop; i++) { Invoker selected = lb.select(weightInvokersSR, null, weightTestInvocation); @@ -74,6 +77,7 @@ public class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest { //active -> 0 RpcStatus.endCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName(), 5000L, true); ShortestResponseLoadBalance lb = new ShortestResponseLoadBalance(); + lb.setApplicationModel(ApplicationModel.defaultModel()); //reset slideWindow Field lastUpdateTimeField = ReflectUtils.forName(ShortestResponseLoadBalance.class.getName()).getDeclaredField("lastUpdateTime"); diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java index 214a65b4e4..74be2fd766 100644 --- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java +++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/mesh/route/MeshRuleManagerTest.java @@ -20,6 +20,7 @@ package org.apache.dubbo.rpc.cluster.router.mesh.route; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup; import org.apache.dubbo.rpc.model.ApplicationModel; + import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; @@ -38,11 +39,11 @@ public class MeshRuleManagerTest { @Test public void subscribeAppRule() { - Optional before = ApplicationModel.getEnvironment().getDynamicConfiguration(); + Optional before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration(); try { DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class); - ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration); MeshRuleManager.subscribeAppRule("test"); @@ -53,7 +54,7 @@ public class MeshRuleManagerTest { assertEquals("test.MESHAPPRULE", result); } finally { - ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null)); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null)); } @@ -61,11 +62,11 @@ public class MeshRuleManagerTest { @Test public void register() { - Optional before = ApplicationModel.getEnvironment().getDynamicConfiguration(); + Optional before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration(); try { DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class); - ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration); when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n" + @@ -109,17 +110,17 @@ public class MeshRuleManagerTest { assertEquals(1, result.getVirtualServiceRuleList().size()); assertEquals(0, result.getDestinationRuleList().size()); } finally { - ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null)); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null)); } } @Test public void unregister() { - Optional before = ApplicationModel.getEnvironment().getDynamicConfiguration(); + Optional before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration(); try { DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class); - ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration); when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" + "kind: VirtualService\n" + @@ -154,7 +155,7 @@ public class MeshRuleManagerTest { MeshRuleManager.unregister(meshRuleRouter); } finally { - ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null)); + ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null)); } } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java index 65ec40104d..dd40e7649d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java @@ -18,6 +18,7 @@ package org.apache.dubbo.common; import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.config.InmemoryConfiguration; +import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.constants.RemotingConstants; import org.apache.dubbo.common.url.component.PathURLAddress; import org.apache.dubbo.common.url.component.ServiceConfigURL; @@ -29,6 +30,8 @@ import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.LRUCache; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ServiceModel; import java.io.Serializable; import java.io.UnsupportedEncodingException; @@ -122,15 +125,22 @@ class URL implements Serializable { private transient String serviceKey; private transient String protocolServiceKey; + protected final Map attributes; protected URL() { this.urlAddress = null; this.urlParam = null; + this.attributes = new HashMap<>(); } public URL(URLAddress urlAddress, URLParam urlParam) { + this(urlAddress, urlParam, null); + } + + public URL(URLAddress urlAddress, URLParam urlParam, Map attributes) { this.urlAddress = urlAddress; this.urlParam = urlParam; + this.attributes = (attributes != null ? attributes : new HashMap<>()); } public URL(String protocol, String host, int port) { @@ -179,6 +189,7 @@ class URL implements Serializable { this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); this.urlParam = URLParam.parse(parameters); + this.attributes = new HashMap<>(); } protected URL(String protocol, @@ -196,6 +207,7 @@ class URL implements Serializable { this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port); this.urlParam = URLParam.parse(parameters); + this.attributes = new HashMap<>(); } public static URL cacheableValueOf(String url) { @@ -218,6 +230,10 @@ class URL implements Serializable { return valueOf(url, false); } + public static URL valueOf(String url, ScopeModel scopeModel) { + return valueOf(url).setScopeModel(scopeModel); + } + /** * parse normal or encoded url string into strutted URL: * - dubbo://host:port/path?param=value @@ -271,8 +287,8 @@ class URL implements Serializable { } } } - return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map) null) - : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap); + return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map) null, url.getAttributes()) + : new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap, url.getAttributes()); } public static String encode(String value) { @@ -532,6 +548,22 @@ class URL implements Serializable { return result; } + public URL setScopeModel(ScopeModel scopeModel) { + return putAttribute(CommonConstants.SCOPE_MODEL, scopeModel); + } + + public ScopeModel getScopeModel() { + return (ScopeModel) getAttribute(CommonConstants.SCOPE_MODEL); + } + + public URL setServiceModel(ServiceModel serviceModel) { + return putAttribute(CommonConstants.SERVICE_MODEL, serviceModel); + } + + public ServiceModel getServiceModel() { + return (ServiceModel) getAttribute(CommonConstants.SERVICE_MODEL); + } + protected Map getNumbers() { // concurrent initialization is tolerant if (numbers == null) { @@ -1449,7 +1481,7 @@ class URL implements Serializable { } protected T newURL(URLAddress urlAddress, URLParam urlParam) { - return (T) new ServiceConfigURL(urlAddress, urlParam, null); + return (T) new ServiceConfigURL(urlAddress, urlParam, attributes); } /* methods introduced for CompositeURL, CompositeURL must override to make the implementations meaningful */ @@ -1517,27 +1549,30 @@ class URL implements Serializable { /* Service Config URL, START*/ public Map getAttributes() { - return new HashMap<>(); + return attributes; } public URL addAttributes(Map attributes) { + attributes.putAll(attributes); return this; } public Object getAttribute(String key) { - return null; + return attributes.get(key); } public URL putAttribute(String key, Object obj) { + attributes.put(key, obj); return this; } public URL removeAttribute(String key) { + attributes.remove(key); return this; } public boolean hasAttribute(String key) { - return true; + return attributes.containsKey(key); } /* Service Config URL, END*/ diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java index 83a2dab86a..21e114f81d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URLBuilder.java @@ -19,12 +19,15 @@ package org.apache.dubbo.common; import org.apache.dubbo.common.url.component.ServiceConfigURL; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.model.ScopeModel; import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import static org.apache.dubbo.common.constants.CommonConstants.SCOPE_MODEL; + public final class URLBuilder extends ServiceConfigURL { private String protocol; @@ -206,6 +209,12 @@ public final class URLBuilder extends ServiceConfigURL { return this; } + @Override + public URLBuilder setScopeModel(ScopeModel scopeModel) { + this.attributes.put(SCOPE_MODEL, scopeModel); + return this; + } + @Override public URLBuilder addParameterAndEncoded(String key, String value) { if (StringUtils.isEmpty(value)) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java new file mode 100644 index 0000000000..a6bb1b3e8b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java @@ -0,0 +1,28 @@ +/* + * 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; + +public class ScopeBeanException extends RuntimeException { + + 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/beans/ScopeBeanExtensionInjector.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java new file mode 100644 index 0000000000..05dc985a54 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java @@ -0,0 +1,41 @@ +/* + * 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; + +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; + +/** + * Inject scope bean to SPI extension instance + */ +public class ScopeBeanExtensionInjector implements ExtensionInjector, ScopeModelAware { + private ScopeModel scopeModel; + private ScopeBeanFactory beanFactory; + + @Override + public void setScopeModel(ScopeModel scopeModel) { + this.scopeModel = scopeModel; + this.beanFactory = scopeModel.getBeanFactory(); + } + + @Override + public T getInstance(Class 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 0000000000..bdc45e451a --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java @@ -0,0 +1,195 @@ +/* + * 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.Collections; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * A bean factory for internal sharing. + */ +public class ScopeBeanFactory { + + private final ScopeBeanFactory parent; + private ExtensionAccessor extensionAccessor; + private List extensionPostProcessors; + private Map beanNameIdCounterMap = new ConcurrentHashMap<>(); + private List registeredBeanInfos = Collections.synchronizedList(new ArrayList<>()); + + public ScopeBeanFactory(ScopeBeanFactory parent, ExtensionAccessor extensionAccessor) { + this.parent = parent; + this.extensionAccessor = extensionAccessor; + extensionPostProcessors = extensionAccessor.getExtensionDirector().getExtensionPostProcessors(); + } + + public T registerBean(Class bean) throws ScopeBeanException { + return this.registerBean(null, bean); + } + + public T registerBean(String name, Class 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) { + // avoid duplicated register same bean + if (containsBean(name, bean)) { + return; + } + + Class beanClass = bean.getClass(); + if (name == null) { + name = beanClass.getName() + "#" + getNextId(beanClass); + } + initializeBean(name, bean); + + registeredBeanInfos.add(new BeanInfo(name, bean)); + } + + public T registerBeanIfAbsent(Class type) { + return registerBeanIfAbsent(null, type); + } + + public T registerBeanIfAbsent(String name, Class type) { + T bean = getBean(name, type); + if (bean == null) { + bean = registerBean(name, type); + } + return bean; + } + + public T registerBeanIfAbsent(Class type, Function, ? extends T> mappingFunction) { + return registerBeanIfAbsent(null, type, mappingFunction); + } + + public T registerBeanIfAbsent(String name, Class type, Function, ? extends T> mappingFunction) { + T bean = getBean(name, type); + if (bean == null) { + //TODO add lock + bean = mappingFunction.apply(type); + registerBean(name, bean); + } + return bean; + } + + public T initializeBean(T bean) { + this.initializeBean(null, bean); + return bean; + } + + private void initializeBean(String name, Object bean) { + 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=" + bean.getClass().getName(), e); + } + } + + private boolean containsBean(String name, Object bean) { + for (BeanInfo beanInfo : registeredBeanInfos) { + if (beanInfo.instance == bean && + (name == null || StringUtils.isEquals(name, beanInfo.name))) { + return true; + } + } + return false; + } + + private int getNextId(Class beanClass) { + return beanNameIdCounterMap.computeIfAbsent(beanClass, key -> new AtomicInteger()).incrementAndGet(); + } + + public T getBean(Class type) { + return this.getBean(null, type); + } + + public T getBean(String name, Class type) { + T bean = getBeanInternal(name, type); + if (bean == null && parent != null) { + return parent.getBean(name, type); + } + return bean; + } + + private T getBeanInternal(String name, Class type) { + List candidates = null; + for (BeanInfo beanInfo : registeredBeanInfos) { + // if required bean type is same class/superclass/interface of the registered bean + if (type.isAssignableFrom(beanInfo.instance.getClass())) { + if (StringUtils.isEquals(beanInfo.name, name)) { + return (T) beanInfo.instance; + } else { + if (candidates == null) { + candidates = new ArrayList<>(); + } + candidates.add(beanInfo); + } + } + } + + // if bean name not matched and only single candidate + if (candidates != null) { + if (candidates.size() == 1) { + return (T) candidates.get(0).instance; + } else if (candidates.size() > 1) { + List candidateBeanNames = candidates.stream().map(beanInfo -> beanInfo.name).collect(Collectors.toList()); + throw new ScopeBeanException("expected single matching bean but found " + candidates.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 0000000000..07ced8d66c --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java @@ -0,0 +1,75 @@ +/* + * 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.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/compiler/Compiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java index acac7bdd2e..ecf6f14528 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/Compiler.java @@ -16,12 +16,13 @@ */ package org.apache.dubbo.common.compiler; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; /** * Compiler. (SPI, Singleton, ThreadSafe) */ -@SPI("javassist") +@SPI(value = "javassist", scope = ExtensionScope.FRAMEWORK) public interface Compiler { /** 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 913b218e58..c206f2b9a7 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,10 +16,15 @@ */ 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; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.io.IOException; import java.io.StringReader; @@ -48,8 +53,8 @@ public class ConfigurationUtils { * * @return */ - public static Configuration getSystemConfiguration() { - return ApplicationModel.getEnvironment().getSystemConfiguration(); + public static Configuration getSystemConfiguration(ScopeModel scopeModel) { + return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getSystemConfiguration(); } /** @@ -57,8 +62,9 @@ public class ConfigurationUtils { * * @return */ - public static Configuration getEnvConfiguration() { - return ApplicationModel.getEnvironment().getEnvironmentConfiguration(); + + public static Configuration getEnvConfiguration(ScopeModel scopeModel) { + return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getEnvironmentConfiguration(); } /** @@ -68,19 +74,20 @@ public class ConfigurationUtils { * * @return */ - public static Configuration getGlobalConfiguration() { - return ApplicationModel.getEnvironment().getConfiguration(); + + public static Configuration getGlobalConfiguration(ScopeModel scopeModel) { + return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getConfiguration(); } - public static Configuration getDynamicGlobalConfiguration() { - return ApplicationModel.getEnvironment().getDynamicGlobalConfiguration(); + public static Configuration getDynamicGlobalConfiguration(ScopeModel scopeModel) { + return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getDynamicGlobalConfiguration(); } // FIXME @SuppressWarnings("deprecation") - public static int getServerShutdownTimeout() { + public static int getServerShutdownTimeout(ScopeModel scopeModel) { int timeout = DEFAULT_SERVER_SHUTDOWN_TIMEOUT; - Configuration configuration = getGlobalConfiguration(); + Configuration configuration = getGlobalConfiguration(scopeModel); String value = StringUtils.trim(configuration.getString(SHUTDOWN_WAIT_KEY)); if (value != null && value.length() > 0) { @@ -102,29 +109,29 @@ public class ConfigurationUtils { return timeout; } - public static String getCachedDynamicProperty(String key, String defaultValue) { - String value = CACHED_DYNAMIC_PROPERTIES.computeIfAbsent(key, _k -> ConfigurationUtils.getDynamicProperty(key, "")); + public static String getCachedDynamicProperty(ScopeModel scopeModel, String key, String defaultValue) { + String value = CACHED_DYNAMIC_PROPERTIES.computeIfAbsent(key, _k -> ConfigurationUtils.getDynamicProperty(scopeModel, key, "")); return StringUtils.isEmpty(value) ? defaultValue : value; } - public static String getDynamicProperty(String property) { - return getDynamicProperty(property, null); + public static String getDynamicProperty(ScopeModel scopeModel, String property) { + return getDynamicProperty(scopeModel, property, null); } - public static String getDynamicProperty(String property, String defaultValue) { - return StringUtils.trim(getDynamicGlobalConfiguration().getString(property, defaultValue)); + public static String getDynamicProperty(ScopeModel scopeModel, String property, String defaultValue) { + return StringUtils.trim(getDynamicGlobalConfiguration(scopeModel).getString(property, defaultValue)); } - public static String getProperty(String property) { - return getProperty(property, null); + public static String getProperty(ScopeModel scopeModel, String property) { + return getProperty(scopeModel, property, null); } - public static String getProperty(String property, String defaultValue) { - return StringUtils.trim(getGlobalConfiguration().getString(property, defaultValue)); + public static String getProperty(ScopeModel scopeModel, String property, String defaultValue) { + return StringUtils.trim(getGlobalConfiguration(scopeModel).getString(property, defaultValue)); } - public static int get(String property, int defaultValue) { - return getGlobalConfiguration().getInt(property, defaultValue); + public static int get(ScopeModel scopeModel, String property, int defaultValue) { + return getGlobalConfiguration(scopeModel).getInt(property, defaultValue); } public static Map parseProperties(String content) throws IOException { @@ -275,4 +282,70 @@ 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 loader = extensionAccessor.getExtensionLoader(DynamicConfigurationFactory.class); + return loader.getOrDefaultExtension(name); + } + + /** + * For compact single instance + */ + @Deprecated + public static Configuration getSystemConfiguration() { + return ApplicationModel.defaultModel().getApplicationEnvironment().getSystemConfiguration(); + } + + @Deprecated + public static Configuration getEnvConfiguration() { + return ApplicationModel.defaultModel().getApplicationEnvironment().getEnvironmentConfiguration(); + } + + @Deprecated + public static Configuration getGlobalConfiguration() { + return ApplicationModel.defaultModel().getApplicationEnvironment().getConfiguration(); + } + + @Deprecated + public static Configuration getDynamicGlobalConfiguration() { + return ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicGlobalConfiguration(); + } + + @Deprecated + public static String getCachedDynamicProperty(String key, String defaultValue) { + return getCachedDynamicProperty(ApplicationModel.defaultModel(), key, defaultValue); + } + + @Deprecated + public static String getDynamicProperty(String property) { + return getDynamicProperty(ApplicationModel.defaultModel(), property); + } + + @Deprecated + public static String getDynamicProperty(String property, String defaultValue) { + return getDynamicProperty(ApplicationModel.defaultModel(), property, defaultValue); + } + + @Deprecated + public static String getProperty(String property) { + return getProperty(ApplicationModel.defaultModel(), property); + } + + @Deprecated + public static String getProperty(String property, String defaultValue) { + return getProperty(ApplicationModel.defaultModel(), property, defaultValue); + } + + @Deprecated + public static int get(String property, int defaultValue) { + return get(ApplicationModel.defaultModel(), property, defaultValue); + } + } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/OrderedPropertiesProvider.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/OrderedPropertiesProvider.java index 4068311af9..e1c02e780b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/OrderedPropertiesProvider.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/OrderedPropertiesProvider.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.config; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.Properties; @@ -26,7 +27,7 @@ import java.util.Properties; * The smaller value, the higher priority * */ -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface OrderedPropertiesProvider { /** * order 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 f1f61001f8..a6b6dbc076 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,30 +17,15 @@ 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} */ -@SPI("nop") // 2.7.5 change the default SPI implementation +@SPI(value = "nop", scope = ExtensionScope.APPLICATION) // 2.7.5 change the default SPI implementation 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 factoryClass = DynamicConfigurationFactory.class; - ExtensionLoader loader = getExtensionLoader(factoryClass); - return loader.getOrDefaultExtension(name); - } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java index 7c59e88852..c1019ea21b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java @@ -464,6 +464,10 @@ public interface CommonConstants { String SERVICE_NAME_MAPPING_KEY = "service-name-mapping"; + String SCOPE_MODEL = "scopeModel"; + + String SERVICE_MODEL = "serviceModel"; + /** * The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that * the Dubbo application will be ignored diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/context/FrameworkExt.java b/dubbo-common/src/main/java/org/apache/dubbo/common/context/FrameworkExt.java index 47cd15e524..8fd724d776 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/context/FrameworkExt.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/context/FrameworkExt.java @@ -16,9 +16,10 @@ */ package org.apache.dubbo.common.context; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface FrameworkExt extends Lifecycle { } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java index e36fdf2324..ec7c1da49e 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.convert; 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.common.lang.Prioritized; @@ -31,7 +32,7 @@ import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument; * @param The target type * @since 2.7.6 */ -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) @FunctionalInterface public interface Converter extends Prioritized { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java index 637d1a8f30..9b5210d541 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.convert.multiple; 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.common.lang.Prioritized; @@ -32,7 +33,7 @@ import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument; * @param The source type * @since 2.7.6 */ -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) public interface MultiValueConverter extends Prioritized { /** 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 0000000000..be13080d37 --- /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 ExtensionLoader getExtensionLoader(Class type) { + return this.getExtensionDirector().getExtensionLoader(type); + } + + default T getExtension(Class type, String name) { + ExtensionLoader extensionLoader = getExtensionLoader(type); + return extensionLoader != null ? extensionLoader.getExtension(name) : null; + } + + default T getAdaptiveExtension(Class type) { + ExtensionLoader extensionLoader = getExtensionLoader(type); + return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null; + } + + default T getDefaultExtension(Class type) { + ExtensionLoader extensionLoader = getExtensionLoader(type); + return extensionLoader != null ? extensionLoader.getDefaultExtension() : null; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java new file mode 100644 index 0000000000..e2215e5aa9 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java @@ -0,0 +1,26 @@ +/* + * 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; + +/** + * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionAccessor} instance. + */ +public interface ExtensionAccessorAware { + + 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 new file mode 100644 index 0000000000..07d8cdee98 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionDirector.java @@ -0,0 +1,127 @@ +/* + * 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; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * ExtensionDirector is a scoped extension loader manager. + * + *

+ *

ExtensionDirector supports multiple levels, and the child can inherit the parent's extension instances.

+ *

The way to find and create an extension instance is similar to Java classloader.

+ */ +public class ExtensionDirector implements ExtensionAccessor { + + private final ConcurrentMap, ExtensionLoader> extensionLoadersMap = new ConcurrentHashMap<>(64); + private ExtensionDirector parent; + private final ExtensionScope scope; + private List extensionPostProcessors = new ArrayList<>(); + + public ExtensionDirector(ExtensionDirector parent, ExtensionScope scope) { + this.parent = parent; + this.scope = scope; + } + + public void addExtensionPostProcessor(ExtensionPostProcessor processor) { + if (!this.extensionPostProcessors.contains(processor)) { + this.extensionPostProcessors.add(processor); + } + } + + public List getExtensionPostProcessors() { + return extensionPostProcessors; + } + + @Override + public ExtensionDirector getExtensionDirector() { + return this; + } + + @Override + public ExtensionLoader getExtensionLoader(Class type) { + if (type == null) { + throw new IllegalArgumentException("Extension type == null"); + } + if (!type.isInterface()) { + throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); + } + if (!withExtensionAnnotation(type)) { + throw new IllegalArgumentException("Extension type (" + type + + ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); + } + + // 1. find in local cache + ExtensionLoader loader = (ExtensionLoader) extensionLoadersMap.get(type); + + final SPI annotation = type.getAnnotation(SPI.class); + ExtensionScope scope = annotation.scope(); + + if (loader == null && scope == ExtensionScope.SELF) { + // create an instance in self scope + loader = createExtensionLoader0(type); + } + + // 2. find in parent + if (loader == null) { + if (this.parent != null) { + loader = this.parent.getExtensionLoader(type); + } + } + + // 3. create it + if (loader == null) { + loader = createExtensionLoader(type); + } + + return loader; + } + + private ExtensionLoader createExtensionLoader(Class type) { + ExtensionLoader loader = null; + if (isScopeMatched(type)) { + // if scope is matched, just create it + loader = createExtensionLoader0(type); + } else { + // if scope is not matched, ignore it + } + return loader; + } + + private ExtensionLoader createExtensionLoader0(Class type) { + ExtensionLoader loader; + extensionLoadersMap.putIfAbsent(type, new ExtensionLoader(type, this)); + loader = (ExtensionLoader) extensionLoadersMap.get(type); + return loader; + } + + private boolean isScopeMatched(Class type) { + final SPI defaultAnnotation = type.getAnnotation(SPI.class); + return defaultAnnotation.scope().equals(scope); + } + + private static boolean withExtensionAnnotation(Class type) { + return type.isAnnotationPresent(SPI.class); + } + + public ExtensionDirector getParent() { + return parent; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java index 32bb8465d9..6eab44d6bb 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java @@ -18,9 +18,16 @@ package org.apache.dubbo.common.extension; /** * ExtensionFactory + * @deprecated use {@link ExtensionInjector} instead */ -@SPI -public interface ExtensionFactory { +@Deprecated +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface ExtensionFactory extends ExtensionInjector { + + @Override + default T getInstance(Class type, String name) { + return getExtension(type, name); + } /** * Get extension. 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 new file mode 100644 index 0000000000..490680513b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java @@ -0,0 +1,37 @@ +/* + * 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; + +/** + * An injector to provide resources for SPI extension. + */ +@SPI(scope = ExtensionScope.SELF) +public interface ExtensionInjector extends ExtensionAccessorAware { + + /** + * Get instance of specify type and name. + * + * @param type object type. + * @param name object name. + * @return object instance. + */ + T getInstance(Class type, String name); + + @Override + 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 e7d00d222a..c71ed7d2f3 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 @@ -17,6 +17,8 @@ package org.apache.dubbo.common.extension; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.config.Environment; +import org.apache.dubbo.common.context.FrameworkExt; import org.apache.dubbo.common.context.Lifecycle; import org.apache.dubbo.common.extension.support.ActivateComparator; import org.apache.dubbo.common.extension.support.WrapperComparator; @@ -32,6 +34,8 @@ import org.apache.dubbo.common.utils.Holder; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleModel; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -90,13 +94,11 @@ public class ExtensionLoader { private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*"); - private static final ConcurrentMap, ExtensionLoader> EXTENSION_LOADERS = new ConcurrentHashMap<>(64); - - private static final ConcurrentMap, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64); + private final ConcurrentMap, Object> extensionInstances = new ConcurrentHashMap<>(64); private final Class type; - private final ExtensionFactory objectFactory; + private final ExtensionInjector injector; private final ConcurrentMap, String> cachedNames = new ConcurrentHashMap<>(); @@ -121,6 +123,9 @@ public class ExtensionLoader { * Record all unacceptable exceptions when using SPI */ private Set unacceptableExceptions = new ConcurrentHashSet<>(); + private ExtensionDirector extensionDirector; + private List extensionPostProcessors; + private Environment environment; public static void setLoadingStrategies(LoadingStrategy... strategies) { if (ArrayUtils.isNotEmpty(strategies)) { @@ -152,52 +157,42 @@ public class ExtensionLoader { return asList(strategies); } - private ExtensionLoader(Class type) { + ExtensionLoader(Class type, ExtensionDirector extensionDirector) { + this.extensionDirector = extensionDirector; + this.extensionPostProcessors = extensionDirector.getExtensionPostProcessors(); this.type = type; - objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension()); + this.injector = (type == ExtensionInjector.class ? null : extensionDirector.getExtensionLoader(ExtensionInjector.class) + .getAdaptiveExtension()); } - private static boolean withExtensionAnnotation(Class type) { - return type.isAnnotationPresent(SPI.class); - } - - @SuppressWarnings("unchecked") + /** + * @see ApplicationModel#getExtensionDirector() + * @see FrameworkModel#getExtensionDirector() + * @see ModuleModel#getExtensionDirector() + * @see ExtensionDirector#getExtensionLoader(java.lang.Class) + * @deprecated get extension loader from extension director of some module. + */ + @Deprecated public static ExtensionLoader getExtensionLoader(Class type) { - if (type == null) { - throw new IllegalArgumentException("Extension type == null"); - } - if (!type.isInterface()) { - throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!"); - } - if (!withExtensionAnnotation(type)) { - throw new IllegalArgumentException("Extension type (" + type + - ") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!"); - } - - ExtensionLoader loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); - if (loader == null) { - EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader(type)); - loader = (ExtensionLoader) EXTENSION_LOADERS.get(type); - } - return loader; + return ApplicationModel.defaultModel().getExtensionLoader(type); } // For testing purposes only public static void resetExtensionLoader(Class type) { - ExtensionLoader loader = EXTENSION_LOADERS.get(type); - if (loader != null) { - // Remove all instances associated with this loader as well - Map> classes = loader.getExtensionClasses(); - for (Map.Entry> entry : classes.entrySet()) { - EXTENSION_INSTANCES.remove(entry.getValue()); - } - classes.clear(); - EXTENSION_LOADERS.remove(type); - } +// ExtensionLoader loader = EXTENSION_LOADERS.get(type); +// if (loader != null) { +// // Remove all instances associated with this loader as well +// Map> classes = loader.getExtensionClasses(); +// for (Map.Entry> entry : classes.entrySet()) { +// EXTENSION_INSTANCES.remove(entry.getValue()); +// } +// classes.clear(); +// EXTENSION_LOADERS.remove(type); +// } } - public static void destroyAll() { - EXTENSION_INSTANCES.forEach((_type, instance) -> { + public void destroy() { + extensionInstances.forEach((_type, instance) -> { if (instance instanceof Lifecycle) { Lifecycle lifecycle = (Lifecycle) instance; try { @@ -207,13 +202,9 @@ public class ExtensionLoader { } } }); + extensionInstances.clear(); - // TODO Improve extension loader, clear static refer extension instance. - // Some extension instances may be referenced by static fields, if clear EXTENSION_INSTANCES may cause inconsistent. - // e.g. org.apache.dubbo.registry.client.metadata.MetadataUtils.localMetadataService - // EXTENSION_INSTANCES.clear(); - - EXTENSION_LOADERS.clear(); + // TODO destroy extension loader, release resources. } private static ClassLoader findClassLoader() { @@ -695,16 +686,16 @@ public class ExtensionLoader { throw findException(name); } try { - T instance = (T) EXTENSION_INSTANCES.get(clazz); + T instance = (T) extensionInstances.get(clazz); if (instance == null) { - EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance()); - instance = (T) EXTENSION_INSTANCES.get(clazz); + extensionInstances.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance()); + instance = (T) extensionInstances.get(clazz); } + instance = postProcessBeforeInitialization(instance, name); injectExtension(instance); - + instance = postProcessAfterInitialization(instance, name); if (wrap) { - List> wrapperClassesList = new ArrayList<>(); if (cachedWrapperClasses != null) { wrapperClassesList.addAll(cachedWrapperClasses); @@ -718,6 +709,7 @@ public class ExtensionLoader { if (wrapper == null || (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) { instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance)); + instance = postProcessAfterInitialization(instance, name); } } } @@ -732,13 +724,34 @@ public class ExtensionLoader { } } + private T postProcessBeforeInitialization(T instance, String name) throws Exception { + if (extensionPostProcessors != null) { + for (ExtensionPostProcessor processor : extensionPostProcessors) { + instance = (T) processor.postProcessBeforeInitialization(instance, name); + } + } + return instance; + } + + private T postProcessAfterInitialization(T instance, String name) throws Exception { + if (instance instanceof ExtensionAccessorAware) { + ((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector); + } + if (extensionPostProcessors != null) { + for (ExtensionPostProcessor processor : extensionPostProcessors) { + instance = (T) processor.postProcessAfterInitialization(instance, name); + } + } + return instance; + } + private boolean containsExtension(String name) { return getExtensionClasses().containsKey(name); } private T injectExtension(T instance) { - if (objectFactory == null) { + if (injector == null) { return instance; } @@ -760,7 +773,7 @@ public class ExtensionLoader { try { String property = getSetterProperty(method); - Object object = objectFactory.getExtension(pt, property); + Object object = injector.getInstance(pt, property); if (object != null) { method.invoke(instance, object); } @@ -840,13 +853,25 @@ public class ExtensionLoader { Map> extensionClasses = new HashMap<>(); for (LoadingStrategy strategy : strategies) { - loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages()); - loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages()); + loadDirectory(extensionClasses, strategy, type.getName()); + + // compatible with old ExtensionFactory + if (this.type == ExtensionInjector.class) { + loadDirectory(extensionClasses, strategy, ExtensionFactory.class.getName()); + } } return extensionClasses; } + private void loadDirectory(Map> extensionClasses, LoadingStrategy strategy, String type) { + loadDirectory(extensionClasses, strategy.directory(), type, strategy.preferExtensionClassLoader(), + strategy.overridden(), strategy.excludedPackages()); + String oldType = type.replace("org.apache", "com.alibaba"); + loadDirectory(extensionClasses, strategy.directory(), oldType, strategy.preferExtensionClassLoader(), + strategy.overridden(), strategy.excludedPackages()); + } + /** * extract and cache default extension name if exists */ @@ -934,7 +959,8 @@ public class ExtensionLoader { loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden); } } catch (Throwable t) { - IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t); + IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t); exceptions.put(line, e); } } @@ -1087,7 +1113,12 @@ public class ExtensionLoader { @SuppressWarnings("unchecked") private T createAdaptiveExtension() { try { - return injectExtension((T) getAdaptiveExtensionClass().newInstance()); + T instance = (T) getAdaptiveExtensionClass().newInstance(); + instance = postProcessBeforeInitialization(instance, null); + instance = injectExtension(instance); + instance = postProcessAfterInitialization(instance, null); + initExtension(instance); + return instance; } catch (Exception e) { throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e); } @@ -1104,17 +1135,25 @@ public class ExtensionLoader { private Class createAdaptiveExtensionClass() { ClassLoader classLoader = findClassLoader(); try { - if (ApplicationModel.getEnvironment().getConfiguration().getBoolean(NATIVE, false)) { + if (getEnvironment().getConfiguration().getBoolean(NATIVE, false)) { return classLoader.loadClass(type.getName() + "$Adaptive"); } } catch (Throwable ignore) { } String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate(); - org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); + org.apache.dubbo.common.compiler.Compiler compiler = extensionDirector.getExtensionLoader( + org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension(); return compiler.compile(code, classLoader); } + private Environment getEnvironment() { + if (environment == null) { + environment = (Environment) extensionDirector.getExtensionLoader(FrameworkExt.class).getExtension(Environment.NAME); + } + return environment; + } + @Override public String toString() { return this.getClass().getName() + "[" + type.getName() + "]"; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionPostProcessor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionPostProcessor.java new file mode 100644 index 0000000000..fcc4822809 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionPostProcessor.java @@ -0,0 +1,32 @@ +/* + * 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; + +/** + * A Post-processor called before or after extension initialization. + */ +public interface ExtensionPostProcessor { + + default Object postProcessBeforeInitialization(Object instance, String name) throws Exception { + return instance; + } + + default Object postProcessAfterInitialization(Object instance, String name) throws Exception { + return instance; + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionScope.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionScope.java new file mode 100644 index 0000000000..170a9c05b8 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionScope.java @@ -0,0 +1,78 @@ +/* + * 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; + +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleModel; + +/** + * Extension SPI Scope + * @see SPI + * @see ExtensionDirector + */ +public enum ExtensionScope { + + /** + * The extension instance is used within framework, shared with all applications and modules. + * + *

Framework scope SPI extension can only obtain {@link FrameworkModel}, + * cannot get the {@link ApplicationModel} and {@link ModuleModel}.

+ * + *

+ * Consideration: + *
    + *
  1. Some SPI need share data between applications inside framework
  2. + *
  3. Stateless SPI is safe shared inside framework
  4. + *
+ */ + FRAMEWORK, + + /** + * The extension instance is used within one application, shared with all modules of the application, + * and different applications create different extension instances. + * + *

Application scope SPI extension can obtain {@link FrameworkModel} and {@link ApplicationModel}, + * cannot get the {@link ModuleModel}.

+ * + *

+ * Consideration: + *
    + *
  1. Isolate extension data in different applications inside framework
  2. + *
  3. Share extension data between all modules inside application
  4. + *
+ */ + APPLICATION, + + /** + * The extension instance is used within one module, and different modules create different extension instances. + * + *

Module scope SPI extension can obtain {@link FrameworkModel}, {@link ApplicationModel} and {@link ModuleModel}.

+ * + *

+ * Consideration: + *
    + *
  1. Isolate extension data in different modules inside application
  2. + *
+ */ + MODULE, + + /** + * self-sufficient, creates an instance for per scope, for special SPI extension, like {@link ExtensionInjector} + */ + SELF +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java index 70aa5b7f77..47cd1fc646 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/SPI.java @@ -61,4 +61,8 @@ public @interface SPI { */ String value() default ""; + /** + * scope of SPI, default value is application scope. + */ + ExtensionScope scope() default ExtensionScope.APPLICATION; } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java deleted file mode 100644 index d136ebc9a6..0000000000 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/AdaptiveExtensionFactory.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * 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.factory; - -import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.ExtensionFactory; -import org.apache.dubbo.common.extension.ExtensionLoader; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * AdaptiveExtensionFactory - */ -@Adaptive -public class AdaptiveExtensionFactory implements ExtensionFactory { - - private final List factories; - - public AdaptiveExtensionFactory() { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class); - List list = new ArrayList(); - for (String name : loader.getSupportedExtensions()) { - list.add(loader.getExtension(name)); - } - factories = Collections.unmodifiableList(list); - } - - @Override - public T getExtension(Class type, String name) { - for (ExtensionFactory factory : factories) { - T extension = factory.getExtension(type, name); - if (extension != null) { - return extension; - } - } - return null; - } - -} 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 new file mode 100644 index 0000000000..1ae03cfeb8 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/AdaptiveExtensionInjector.java @@ -0,0 +1,77 @@ +/* + * 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.inject; + +import org.apache.dubbo.common.context.Lifecycle; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionAccessor; +import org.apache.dubbo.common.extension.ExtensionInjector; +import org.apache.dubbo.common.extension.ExtensionLoader; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * AdaptiveExtensionInjector + */ +@Adaptive +public class AdaptiveExtensionInjector implements ExtensionInjector, Lifecycle { + + private List injectors = Collections.emptyList(); + + private ExtensionAccessor extensionAccessor; + + public AdaptiveExtensionInjector() { + } + + @Override + public void setExtensionAccessor(ExtensionAccessor extensionAccessor) { + this.extensionAccessor = extensionAccessor; + } + + @Override + public void initialize() throws IllegalStateException { + ExtensionLoader loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class); + List list = new ArrayList(); + for (String name : loader.getSupportedExtensions()) { + list.add(loader.getExtension(name)); + } + injectors = Collections.unmodifiableList(list); + } + + @Override + public T getInstance(Class type, String name) { + for (ExtensionInjector injector : injectors) { + T extension = injector.getInstance(type, name); + if (extension != null) { + return extension; + } + } + return null; + } + + @Override + public void start() throws IllegalStateException { + + } + + @Override + public void destroy() throws IllegalStateException { + + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java similarity index 63% rename from dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java rename to dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java index 46cbe19f15..d45cc7b700 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/inject/SpiExtensionInjector.java @@ -14,21 +14,32 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.apache.dubbo.common.extension.factory; +package org.apache.dubbo.common.extension.inject; -import org.apache.dubbo.common.extension.ExtensionFactory; +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; /** - * SpiExtensionFactory + * SpiExtensionInjector */ -public class SpiExtensionFactory implements ExtensionFactory { +public class SpiExtensionInjector implements ExtensionInjector { + + private ExtensionAccessor extensionAccessor; @Override - public T getExtension(Class type, String name) { + public void setExtensionAccessor(ExtensionAccessor extensionAccessor) { + this.extensionAccessor = extensionAccessor; + } + + @Override + public T getInstance(Class type, String name) { if (type.isInterface() && type.isAnnotationPresent(SPI.class)) { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(type); + ExtensionLoader loader = extensionAccessor.getExtensionLoader(type); + if (loader == null) { + return null; + } if (!loader.getSupportedExtensions().isEmpty()) { return loader.getAdaptiveExtension(); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/infra/InfraAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/infra/InfraAdapter.java index 539ffe9b19..3784069d61 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/infra/InfraAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/infra/InfraAdapter.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.infra; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.Map; @@ -26,7 +27,7 @@ import java.util.Map; * 2. get configurations from third-party systems which maybe useful for a specific component. */ -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface InfraAdapter { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/infra/support/EnvironmentAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/infra/support/EnvironmentAdapter.java index 4a3844617f..e7b509ca58 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/infra/support/EnvironmentAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/infra/support/EnvironmentAdapter.java @@ -20,6 +20,8 @@ import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.extension.Activate; import org.apache.dubbo.common.infra.InfraAdapter; import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.HashMap; import java.util.Map; @@ -31,7 +33,14 @@ import static org.apache.dubbo.common.constants.CommonConstants.EQUAL_SPLIT_PATT import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN; @Activate -public class EnvironmentAdapter implements InfraAdapter { +public class EnvironmentAdapter implements InfraAdapter, ScopeModelAware { + + private ApplicationModel applicationModel; + + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } /** * 1. OS Environment: DUBBO_LABELS=tag=pre;key=value @@ -41,7 +50,7 @@ public class EnvironmentAdapter implements InfraAdapter { public Map getExtraAttributes(Map params) { Map parameters = new HashMap<>(); - String rawLabels = ConfigurationUtils.getProperty(DUBBO_LABELS); + String rawLabels = ConfigurationUtils.getProperty(applicationModel, DUBBO_LABELS); if (StringUtils.isNotEmpty(rawLabels)) { String[] labelPairs = SEMICOLON_SPLIT_PATTERN.split(rawLabels); for (String pair : labelPairs) { @@ -52,11 +61,11 @@ public class EnvironmentAdapter implements InfraAdapter { } } - String rawKeys = ConfigurationUtils.getProperty(DUBBO_ENV_KEYS); + String rawKeys = ConfigurationUtils.getProperty(applicationModel, DUBBO_ENV_KEYS); if (StringUtils.isNotEmpty(rawKeys)) { String[] keys = COMMA_SPLIT_PATTERN.split(rawKeys); for (String key : keys) { - String value = ConfigurationUtils.getProperty(key); + String value = ConfigurationUtils.getProperty(applicationModel, key); if (value != null) { parameters.put(key, value); } @@ -67,6 +76,6 @@ public class EnvironmentAdapter implements InfraAdapter { @Override public String getAttribute(String key) { - return ConfigurationUtils.getProperty(key); + return ConfigurationUtils.getProperty(applicationModel, key); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java index 52d5605a19..3ce6556a7c 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallback.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.lang; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; /** @@ -23,7 +24,7 @@ import org.apache.dubbo.common.extension.SPI; * * @since 2.7.5 */ -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface ShutdownHookCallback extends Prioritized { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java index 1560c64f26..fc644e5ad4 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerAdapter.java @@ -16,6 +16,7 @@ */ package org.apache.dubbo.common.logger; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.io.File; @@ -23,7 +24,7 @@ import java.io.File; /** * Logger provider */ -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) public interface LoggerAdapter { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java index b5d7c41a6b..2ff75cfaa7 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/StatusChecker.java @@ -16,12 +16,13 @@ */ package org.apache.dubbo.common.status; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; /** * StatusChecker */ -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface StatusChecker { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReportService.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReportService.java new file mode 100644 index 0000000000..2dacee5491 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReportService.java @@ -0,0 +1,109 @@ +/* + * 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.status.reporter; + +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.utils.CollectionUtils; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; + +import com.google.gson.Gson; + +import java.util.HashMap; +import java.util.Set; + +/** + * + */ +public class FrameworkStatusReportService implements ScopeModelAware { + + private static final Logger logger = LoggerFactory.getLogger(FrameworkStatusReporter.class); + public static final String REGISTRATION_STATUS = "registration"; + public static final String ADDRESS_CONSUMPTION_STATUS = "consumption"; + public static final String MIGRATION_STEP_STATUS = "migrationStepStatus"; + + private ApplicationModel applicationModel; + private Set reporters; + private Gson gson = new Gson(); + + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + reporters = applicationModel.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances(); + } + + public void reportRegistrationStatus(Object obj) { + doReport(REGISTRATION_STATUS, obj); + } + + public void reportConsumptionStatus(Object obj) { + doReport(ADDRESS_CONSUMPTION_STATUS, obj); + } + + public void reportMigrationStepStatus(Object obj) { + doReport(MIGRATION_STEP_STATUS, obj); + } + + public boolean hasReporter() { + return reporters.size() > 0; + } + + private void doReport(String type, Object obj) { + // TODO, report asynchronously + try { + if (CollectionUtils.isNotEmpty(reporters)) { + FrameworkStatusReporter reporter = reporters.iterator().next(); + reporter.report(type, obj); + } + } catch (Exception e) { + logger.info("Report " + type + " status failed because of " + e.getMessage()); + } + } + + public String createRegistrationReport(String status) { + return "{\"application\":\"" + + applicationModel.getApplicationName() + + "\",\"status\":\"" + + status + + "\"}"; + } + + public String createConsumptionReport(String interfaceName, String version, String group, String status) { + HashMap migrationStatus = new HashMap<>(); + migrationStatus.put("type", "consumption"); + migrationStatus.put("application", applicationModel.getApplicationName()); + migrationStatus.put("service", interfaceName); + migrationStatus.put("version", version); + migrationStatus.put("group", group); + migrationStatus.put("status", status); + return gson.toJson(migrationStatus); + } + + public String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) { + HashMap migrationStatus = new HashMap<>(); + migrationStatus.put("type", "migrationStepStatus"); + migrationStatus.put("application", applicationModel.getApplicationName()); + migrationStatus.put("service", interfaceName); + migrationStatus.put("version", version); + migrationStatus.put("group", group); + migrationStatus.put("originStep", originStep); + migrationStatus.put("newStep", newStep); + migrationStatus.put("success", success); + return gson.toJson(migrationStatus); + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReporter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReporter.java index d122f910d8..293bb491bf 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReporter.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReporter.java @@ -16,86 +16,14 @@ */ package org.apache.dubbo.common.status.reporter; -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.common.logger.Logger; -import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; -import com.google.gson.Gson; -import java.util.HashMap; -import java.util.Set; - -@SPI -public interface FrameworkStatusReporter { - static final Gson gson = new Gson(); - Logger logger = LoggerFactory.getLogger(FrameworkStatusReporter.class); - String REGISTRATION_STATUS = "registration"; - String ADDRESS_CONSUMPTION_STATUS = "consumption"; - String MIGRATION_STEP_STATUS = "migrationStepStatus"; +@SPI(scope = ExtensionScope.APPLICATION) +public interface FrameworkStatusReporter extends ScopeModelAware { void report(String type, Object obj); - static void reportRegistrationStatus(Object obj) { - doReport(REGISTRATION_STATUS, obj); - } - - static void reportConsumptionStatus(Object obj) { - doReport(ADDRESS_CONSUMPTION_STATUS, obj); - } - - static void reportMigrationStepStatus(Object obj) { - doReport(MIGRATION_STEP_STATUS, obj); - } - - static boolean hasReporter() { - return ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensions().size() > 0; - } - - static void doReport(String type, Object obj) { - // TODO, report asynchronously - try { - Set reporters = ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances(); - if (CollectionUtils.isNotEmpty(reporters)) { - FrameworkStatusReporter reporter = reporters.iterator().next(); - reporter.report(type, obj); - } - } catch (Exception e) { - logger.info("Report " + type + " status failed because of " + e.getMessage()); - } - } - - static String createRegistrationReport(String status) { - return "{\"application\":\"" + - ApplicationModel.getName() + - "\",\"status\":\"" + - status + - "\"}"; - } - - static String createConsumptionReport(String interfaceName, String version, String group, String status) { - HashMap migrationStatus = new HashMap<>(); - migrationStatus.put("type", "consumption"); - migrationStatus.put("application", ApplicationModel.getName()); - migrationStatus.put("service", interfaceName); - migrationStatus.put("version", version); - migrationStatus.put("group", group); - migrationStatus.put("status", status); - return gson.toJson(migrationStatus); - } - - static String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) { - HashMap migrationStatus = new HashMap<>(); - migrationStatus.put("type", "migrationStepStatus"); - migrationStatus.put("application", ApplicationModel.getName()); - migrationStatus.put("service", interfaceName); - migrationStatus.put("version", version); - migrationStatus.put("group", group); - migrationStatus.put("originStep", originStep); - migrationStatus.put("newStep", newStep); - migrationStatus.put("success", success); - return gson.toJson(migrationStatus); - } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/store/DataStore.java b/dubbo-common/src/main/java/org/apache/dubbo/common/store/DataStore.java index 8a6d475e4c..59d7414f7b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/store/DataStore.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/store/DataStore.java @@ -17,11 +17,12 @@ package org.apache.dubbo.common.store; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.Map; -@SPI("simple") +@SPI(value = "simple", scope = ExtensionScope.APPLICATION) public interface DataStore { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java index 312cd690ff..b1ff4a8b08 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadPool.java @@ -18,6 +18,7 @@ package org.apache.dubbo.common.threadpool; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.concurrent.Executor; @@ -27,7 +28,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY; /** * ThreadPool */ -@SPI("fixed") +//TODO which scope for ThreadPool? APPLICATION or FRAMEWORK +@SPI(value = "fixed", scope = ExtensionScope.FRAMEWORK) public interface ThreadPool { /** 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 ae437eefb0..5c93b23fc7 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; @@ -27,6 +28,8 @@ import org.apache.dubbo.common.utils.ExecutorUtil; import org.apache.dubbo.common.utils.NamedThreadFactory; import org.apache.dubbo.config.ConsumerConfig; import org.apache.dubbo.config.ProviderConfig; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.List; import java.util.Map; @@ -46,12 +49,11 @@ import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_REFER_TH import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY; -import static org.apache.dubbo.rpc.model.ApplicationModel.getConfigManager; /** * Consider implementing {@code Licycle} to enable executors shutdown when the process stops. */ -public class DefaultExecutorRepository implements ExecutorRepository { +public class DefaultExecutorRepository implements ExecutorRepository, ExtensionAccessorAware, ScopeModelAware { private static final Logger logger = LoggerFactory.getLogger(DefaultExecutorRepository.class); private int DEFAULT_SCHEDULER_SIZE = Runtime.getRuntime().availableProcessors(); @@ -79,6 +81,9 @@ public class DefaultExecutorRepository implements ExecutorRepository { private static Ring executorServiceRing = new Ring(); private static final Object LOCK = new Object(); + private ExtensionAccessor extensionAccessor; + + private ApplicationModel applicationModel; public DefaultExecutorRepository() { for (int i = 0; i < DEFAULT_SCHEDULER_SIZE; i++) { @@ -228,7 +233,7 @@ public class DefaultExecutorRepository implements ExecutorRepository { } private Integer getExportThreadNum() { - List threadNum = getConfigManager().getProviders() + List threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getProviders() .stream() .map(ProviderConfig::getExportThreadNum) .filter(k -> k != null && k > 0) @@ -275,7 +280,7 @@ public class DefaultExecutorRepository implements ExecutorRepository { } private Integer getReferThreadNum() { - List threadNum = getConfigManager().getConsumers() + List threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getConsumers() .stream() .map(ConsumerConfig::getReferThreadNum) .filter(k -> k != null && k > 0) @@ -311,7 +316,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 +367,14 @@ public class DefaultExecutorRepository implements ExecutorRepository { // executorService.shutdown(); // } } + + @Override + public void setExtensionAccessor(ExtensionAccessor extensionAccessor) { + this.extensionAccessor = extensionAccessor; + } + + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepository.java index b209f48564..dabd581443 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepository.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepository.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.threadpool.manager; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.concurrent.ExecutorService; @@ -25,7 +26,7 @@ import java.util.concurrent.ScheduledExecutorService; /** * */ -@SPI("default") +@SPI(value = "default", scope = ExtensionScope.APPLICATION) public interface ExecutorRepository { /** diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java index d0eccffe9e..b9299881c6 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/DubboServiceAddressURL.java @@ -18,6 +18,8 @@ package org.apache.dubbo.common.url.component; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.utils.StringUtils; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ServiceModel; import java.util.Map; import java.util.Objects; @@ -96,6 +98,16 @@ public class DubboServiceAddressURL extends ServiceAddressURL { this.overrideURL = overrideURL; } + @Override + public ScopeModel getScopeModel() { + return consumerURL.getScopeModel(); + } + + @Override + public ServiceModel getServiceModel() { + return consumerURL.getServiceModel(); + } + @Override public int hashCode() { final int prime = 31; diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceConfigURL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceConfigURL.java index 47712972cd..5fcd26304f 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceConfigURL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/ServiceConfigURL.java @@ -23,7 +23,6 @@ import java.util.HashMap; import java.util.Map; public class ServiceConfigURL extends URL { - private final Map attributes; private volatile transient String full; private volatile transient String string; @@ -31,12 +30,11 @@ public class ServiceConfigURL extends URL { private volatile transient String parameter; public ServiceConfigURL() { - this.attributes = null; + super(); } public ServiceConfigURL(URLAddress urlAddress, URLParam urlParam, Map attributes) { - super(urlAddress, urlParam); - this.attributes = (attributes != null ? attributes : new HashMap<>()); + super(urlAddress, urlParam, attributes); } @@ -98,22 +96,11 @@ public class ServiceConfigURL extends URL { return (T) new ServiceConfigURL(urlAddress, urlParam, attributes); } - @Override - public Map getAttributes() { - return attributes; - } - - @Override - public Object getAttribute(String key) { - return attributes.get(key); - } - @Override public URL addAttributes(Map attributes) { Map newAttributes = new HashMap<>(); newAttributes.putAll(this.attributes); newAttributes.putAll(attributes); - return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes); } @@ -121,7 +108,6 @@ public class ServiceConfigURL extends URL { public ServiceConfigURL putAttribute(String key, Object obj) { Map newAttributes = new HashMap<>(attributes); newAttributes.put(key, obj); - return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes); } @@ -129,15 +115,9 @@ public class ServiceConfigURL extends URL { public URL removeAttribute(String key) { Map newAttributes = new HashMap<>(attributes); newAttributes.remove(key); - return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes); } - @Override - public boolean hasAttribute(String key) { - return getAttribute(key) != null; - } - @Override public String toString() { if (string != null) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/param/DynamicParamSource.java b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/param/DynamicParamSource.java index 15df9aa9ac..49008f1aac 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/param/DynamicParamSource.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/param/DynamicParamSource.java @@ -16,11 +16,12 @@ */ package org.apache.dubbo.common.url.component.param; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; import java.util.List; -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) public interface DynamicParamSource { void init(List keys, List values); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java index dbeeff9ca0..d4098069cc 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/NetUtils.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.logger.support.FailsafeLogger; +import org.apache.dubbo.rpc.model.ScopeModel; import java.io.IOException; import java.net.Inet4Address; @@ -237,8 +238,8 @@ public class NetUtils { return host; } - public static String getIpByConfig() { - String configIp = ConfigurationUtils.getProperty(DUBBO_IP_TO_BIND); + public static String getIpByConfig(ScopeModel scopeModel) { + String configIp = ConfigurationUtils.getProperty(scopeModel, DUBBO_IP_TO_BIND); if (configIp != null) { return configIp; } 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 249fd3ee19..994444bc70 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.ApplicationModel; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.apache.dubbo.rpc.model.ScopeModel; import java.beans.BeanInfo; import java.beans.IntrospectionException; @@ -93,6 +97,21 @@ public abstract class AbstractConfig implements Serializable { */ protected Boolean isDefault; + /** + * The scope model of this config instance. + *

+ * NOTE: the model maybe changed during config processing, + * the extension spi instance needs to be reinitialized after changing the model! + */ + protected ScopeModel scopeModel; + + public AbstractConfig() { + this(ApplicationModel.defaultModel()); + } + + public AbstractConfig(ScopeModel scopeModel) { + this.setScopeModel(scopeModel); + } public static String getTagName(Class cls) { return tagNameCache.computeIfAbsent(cls, (key) -> { @@ -302,6 +321,46 @@ 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) { + if (this.scopeModel != scopeModel) { + this.scopeModel = scopeModel; + // reinitialize spi extension here + this.initExtensions(); + } + } + + /** + * Subclass should override this method to initialize its SPI extensions. + *

+ * For example: + *

+     * this.protocol = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+     * 
+ */ + protected void initExtensions() { + } + + protected ExtensionLoader getExtensionLoader(Class 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 +502,7 @@ public abstract class AbstractConfig implements Serializable { // check and init before do refresh preProcessRefresh(); - Environment environment = ApplicationModel.getEnvironment(); + Environment environment = getApplicationModel().getApplicationEnvironment(); List> configurationMaps = environment.getConfigurationMaps(); // Search props starts with PREFIX in order @@ -729,4 +788,7 @@ public abstract class AbstractConfig implements Serializable { return methods; } + protected ConfigManager getConfigManager() { + return getApplicationModel().getApplicationConfigManager(); + } } 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 cd9fddae4a..6acdfa7d2c 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,7 @@ 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.ScopeModel; import org.apache.dubbo.rpc.model.ServiceMetadata; import java.lang.reflect.Method; @@ -42,12 +43,12 @@ import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.NATIVE; import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY; import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY; import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY; import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.NATIVE; /** @@ -196,6 +197,34 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { return urls; } + @Override + public void setScopeModel(ScopeModel scopeModel) { + super.setScopeModel(scopeModel); +// ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(scopeModel); +// if (this.configCenter != null && this.configCenter.getScopeModel() != applicationModel) { +// this.configCenter.setScopeModel(applicationModel); +// } +// if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) { +// this.metadataReportConfig.setScopeModel(applicationModel); +// } +// if (this.metrics != null && this.metrics.getScopeModel() != applicationModel) { +// this.metrics.setScopeModel(applicationModel); +// } +// if (this.monitor != null && this.monitor.getScopeModel() != applicationModel) { +// this.monitor.setScopeModel(applicationModel); +// } +// if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) { +// this.metadataReportConfig.setScopeModel(applicationModel); +// } +// if (CollectionUtils.isNotEmpty(this.registries)) { +// this.registries.forEach(registryConfig -> { +// if (registryConfig.getScopeModel() != applicationModel) { +// registryConfig.setScopeModel(applicationModel); +// } +// }); +// } + } + /** * Check whether the registry config is exists, and then conversion it to {@link RegistryConfig} */ @@ -225,7 +254,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { * @return */ protected String[] methods(Class interfaceClass) { - boolean isNative = ApplicationModel.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 +262,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { } } + protected Environment getEnvironment() { + return getApplicationModel().getApplicationEnvironment(); + } + @Override protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) { if (StringUtils.hasText(interfaceName)) { @@ -278,13 +311,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { List methodConfigs = this.getMethods(); if (methodConfigs != null && methodConfigs.size() > 0) { // whether ignore invalid method config - Object ignoreInvalidMethodConfigVal = ApplicationModel.getEnvironment().getConfiguration() + Object ignoreInvalidMethodConfigVal = getEnvironment().getConfiguration() .getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_INVALID_METHOD_CONFIG, "false"); boolean ignoreInvalidMethodConfig = Boolean.parseBoolean(ignoreInvalidMethodConfigVal.toString()); Class finalInterfaceClass = interfaceClass; List validMethodConfigs = methodConfigs.stream().filter(methodConfig -> { methodConfig.setParentPrefix(preferredPrefix); + methodConfig.setScopeModel(getScopeModel()); methodConfig.refresh(); // verify method config return verifyMethodConfig(methodConfig, finalInterfaceClass, ignoreInvalidMethodConfig); @@ -388,7 +422,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { computeValidRegistryIds(); if (StringUtils.isEmpty(registryIds)) { if (CollectionUtils.isEmpty(registries)) { - List registryConfigs = ApplicationModel.getConfigManager().getDefaultRegistries(); + List registryConfigs = getConfigManager().getDefaultRegistries(); registryConfigs = new ArrayList<>(registryConfigs); setRegistries(registryConfigs); } @@ -397,7 +431,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { List tmpRegistries = new ArrayList<>(); Arrays.stream(ids).forEach(id -> { if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) { - Optional globalRegistry = ApplicationModel.getConfigManager().getRegistry(id); + Optional globalRegistry = getConfigManager().getRegistry(id); if (globalRegistry.isPresent()) { tmpRegistries.add(globalRegistry.get()); } else { @@ -561,14 +595,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { if (application != null) { return application; } - return ApplicationModel.getConfigManager().getApplicationOrElseThrow(); + return getConfigManager().getApplicationOrElseThrow(); } @Deprecated public void setApplication(ApplicationConfig application) { this.application = application; if (application != null) { - ApplicationModel.getConfigManager().setApplication(application); + getConfigManager().setApplication(application); } } @@ -576,14 +610,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { if (module != null) { return module; } - return ApplicationModel.getConfigManager().getModule().orElse(null); + return getConfigManager().getModule().orElse(null); } @Deprecated public void setModule(ModuleConfig module) { this.module = module; if (module != null) { - ApplicationModel.getConfigManager().setModule(module); + getConfigManager().setModule(module); } } @@ -637,7 +671,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.getConfigManager().getMonitor().orElse(null); + return getConfigManager().getMonitor().orElse(null); } @Deprecated @@ -649,7 +683,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { public void setMonitor(MonitorConfig monitor) { this.monitor = monitor; if (monitor != null) { - ApplicationModel.getConfigManager().setMonitor(monitor); + getConfigManager().setMonitor(monitor); } } @@ -666,7 +700,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { if (configCenter != null) { return configCenter; } - Collection configCenterConfigs = ApplicationModel.getConfigManager().getConfigCenters(); + Collection configCenterConfigs = getConfigManager().getConfigCenters(); if (CollectionUtils.isNotEmpty(configCenterConfigs)) { return configCenterConfigs.iterator().next(); } @@ -677,7 +711,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { public void setConfigCenter(ConfigCenterConfig configCenter) { this.configCenter = configCenter; if (configCenter != null) { - ApplicationModel.getConfigManager().addConfigCenter(configCenter); + getConfigManager().addConfigCenter(configCenter); } } @@ -718,7 +752,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { if (metadataReportConfig != null) { return metadataReportConfig; } - Collection metadataReportConfigs = ApplicationModel.getConfigManager().getMetadataConfigs(); + Collection metadataReportConfigs = getConfigManager().getMetadataConfigs(); if (CollectionUtils.isNotEmpty(metadataReportConfigs)) { return metadataReportConfigs.iterator().next(); } @@ -729,7 +763,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { public void setMetadataReportConfig(MetadataReportConfig metadataReportConfig) { this.metadataReportConfig = metadataReportConfig; if (metadataReportConfig != null) { - ApplicationModel.getConfigManager().addMetadataReport(metadataReportConfig); + getConfigManager().addMetadataReport(metadataReportConfig); } } @@ -738,14 +772,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { if (metrics != null) { return metrics; } - return ApplicationModel.getConfigManager().getMetrics().orElse(null); + return getConfigManager().getMetrics().orElse(null); } @Deprecated public void setMetrics(MetricsConfig metrics) { this.metrics = metrics; if (metrics != null) { - ApplicationModel.getConfigManager().setMetrics(metrics); + getConfigManager().setMetrics(metrics); } } @@ -767,7 +801,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig { } public SslConfig getSslConfig() { - return ApplicationModel.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/AbstractMethodConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java index 2c43206ca8..b234d98824 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java @@ -17,6 +17,9 @@ package org.apache.dubbo.config; import org.apache.dubbo.config.support.Parameter; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.apache.dubbo.rpc.model.ScopeModel; import java.util.Map; @@ -95,6 +98,23 @@ public abstract class AbstractMethodConfig extends AbstractConfig { */ protected Integer forks; + public AbstractMethodConfig() { + super(ApplicationModel.defaultModel().getDefaultModule()); + } + + @Override + public void setScopeModel(ScopeModel scopeModel) { + if (!(scopeModel instanceof ModuleModel)) { + throw new IllegalArgumentException("Invalid scope model, expect to be a ModuleModel but got: " + scopeModel); + } + super.setScopeModel(scopeModel); + } + + @Override + public ModuleModel getScopeModel() { + return (ModuleModel) scopeModel; + } + public Integer getForks() { return forks; } 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 4521c6b973..d990ddb263 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; @@ -34,17 +33,17 @@ import java.util.Map; import java.util.Set; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.DUBBO; import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY; import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY; +import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED; import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.STARTUP_PROBE; import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP; import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE; @@ -557,7 +556,7 @@ public class ApplicationConfig extends AbstractConfig { parameters = new HashMap<>(); } - Set adapters = ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances(); + Set adapters = this.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances(); if (CollectionUtils.isNotEmpty(adapters)) { Map inputParameters = new HashMap<>(); inputParameters.put(APPLICATION_KEY, getName()); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java index 412122eebd..59ff045294 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java @@ -149,7 +149,9 @@ public class ConfigCenterConfig extends AbstractConfig { if (StringUtils.isEmpty(map.get(PROTOCOL_KEY))) { map.put(PROTOCOL_KEY, ZOOKEEPER_PROTOCOL); } - return UrlUtils.parseURL(address, map); + URL url = UrlUtils.parseURL(address, map); + url.setScopeModel(getScopeModel()); + return url; } public boolean checkOrUpdateInitialized(boolean update) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java index 239d11c0f8..65f560e3f3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MetadataReportConfig.java @@ -124,7 +124,7 @@ public class MetadataReportConfig extends AbstractConfig { throw new IllegalArgumentException("The address of metadata report is invalid."); } Map map = new HashMap(); - URL url = URL.valueOf(address); + URL url = URL.valueOf(address, getScopeModel()); // Issue : https://github.com/apache/dubbo/issues/6491 // Append the parameters from address map.putAll(url.getParameters()); @@ -135,7 +135,7 @@ public class MetadataReportConfig extends AbstractConfig { // put the protocol of URL as the "metadata" map.put("metadata", url.getProtocol()); return new ServiceConfigURL("metadata", url.getUsername(), url.getPassword(), url.getHost(), - url.getPort(), url.getPath(), map); + url.getPort(), url.getPath(), map).setScopeModel(getScopeModel()); } 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 2210d6ddf8..2eb2870825 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.getEnvironment(); + Environment environment = getApplicationModel().getApplicationEnvironment(); 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 88e9b2a664..525ccbc7f7 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,7 @@ 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.ScopeModel; import org.apache.dubbo.rpc.model.ServiceMetadata; import org.apache.dubbo.rpc.service.GenericService; import org.apache.dubbo.rpc.support.ProtocolUtils; @@ -115,7 +115,7 @@ public abstract class ReferenceConfigBase extends AbstractReferenceConfig { protected void preProcessRefresh() { super.preProcessRefresh(); if (consumer == null) { - consumer = ApplicationModel.getConfigManager() + consumer = getConfigManager() .getDefaultConsumer() .orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized")); } @@ -200,6 +200,14 @@ public abstract class ReferenceConfigBase extends AbstractReferenceConfig { return null; } + @Override + public void setScopeModel(ScopeModel scopeModel) { + super.setScopeModel(scopeModel); + if (this.consumer != null && this.consumer.getScopeModel() != scopeModel) { + this.consumer.setScopeModel(scopeModel); + } + } + @Override public String getInterface() { return interfaceName; 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 9ed3df13b8..f007b54d0a 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 4d2fbfcdcb..6d619145cb 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,7 @@ 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.ScopeModel; import org.apache.dubbo.rpc.model.ServiceMetadata; import org.apache.dubbo.rpc.service.GenericService; import org.apache.dubbo.rpc.support.ProtocolUtils; @@ -105,6 +105,14 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { return protocols; } + @Override + public void setScopeModel(ScopeModel scopeModel) { + super.setScopeModel(scopeModel); + if (this.provider != null && this.provider.getScopeModel() != scopeModel) { + this.provider.setScopeModel(scopeModel); + } + } + @Deprecated private static List convertProtocolToProvider(List protocols) { if (CollectionUtils.isEmpty(protocols)) { @@ -199,7 +207,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { super.preProcessRefresh(); convertProviderIdToProvider(); if (provider == null) { - provider = ApplicationModel.getConfigManager() + provider = getConfigManager() .getDefaultProvider() .orElseThrow(() -> new IllegalArgumentException("Default provider is not initialized")); } @@ -247,7 +255,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { protected void convertProviderIdToProvider() { if (provider == null && StringUtils.hasText(providerIds)) { - provider = ApplicationModel.getConfigManager().getProvider(providerIds) + provider = getConfigManager().getProvider(providerIds) .orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds)); } } @@ -255,7 +263,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { protected void convertProtocolIdsToProtocols() { if (StringUtils.isEmpty(protocolIds)) { if (CollectionUtils.isEmpty(protocols)) { - List protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols(); + List protocolConfigs = getConfigManager().getDefaultProtocols(); if (protocolConfigs.isEmpty()) { throw new IllegalStateException("The default protocol has not been initialized."); } @@ -266,7 +274,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { Set idsSet = new LinkedHashSet<>(Arrays.asList(idsArray)); List tmpProtocols = new ArrayList<>(); for (String id : idsSet) { - Optional globalProtocol = ApplicationModel.getConfigManager().getProtocol(id); + Optional globalProtocol = getConfigManager().getProtocol(id); if (globalProtocol.isPresent()) { tmpProtocols.add(globalProtocol.get()); } else { @@ -336,7 +344,7 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { } public void setProvider(ProviderConfig provider) { - ApplicationModel.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 5d7584c5ee..4cd79ded63 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.getEnvironment().getConfiguration(); + CompositeConfiguration configuration = applicationModel.getApplicationEnvironment().getConfiguration(); String configModeStr = (String) configuration.getProperty(DUBBO_CONFIG_MODE); try { if (StringUtils.hasText(configModeStr)) { @@ -367,6 +375,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt { // ServiceConfig correlative methods public void addService(ServiceConfigBase serviceConfig) { + if (serviceConfig.getScopeModel() == null) { + serviceConfig.setScopeModel(applicationModel.getDefaultModule()); + } addConfig(serviceConfig); } @@ -385,6 +396,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt { // ReferenceConfig correlative methods public void addReference(ReferenceConfigBase referenceConfig) { + if (referenceConfig.getScopeModel() == null) { + referenceConfig.setScopeModel(applicationModel.getDefaultModule()); + } addConfig(referenceConfig); } @@ -458,6 +472,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt { if (config == null) { return; } + if (config.getScopeModel() == null) { + config.setScopeModel(applicationModel); + } addConfig(config, isUniqueConfig(config)); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java index 8b0f488236..1e4b50b2ec 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java @@ -16,9 +16,10 @@ */ package org.apache.dubbo.rpc.model; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; -@SPI +@SPI(scope = ExtensionScope.APPLICATION) public interface ApplicationInitListener { /** * init the application 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 9e0521b4ed..cd814ea9ee 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 @@ -18,14 +18,19 @@ package org.apache.dubbo.rpc.model; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.context.FrameworkExt; +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 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.List; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; @@ -43,18 +48,48 @@ import java.util.concurrent.atomic.AtomicBoolean; *

*/ -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 static AtomicBoolean INIT_FLAG = new AtomicBoolean(false); - private static Environment environment; - private static ConfigManager configManager; - private static ServiceRepository serviceRepository; + private volatile List moduleModels = Collections.synchronizedList(new ArrayList<>()); + private AtomicBoolean initFlag = new AtomicBoolean(false); + private Environment environment; + private ConfigManager configManager; + private ServiceRepository serviceRepository; - public static void init() { - if (INIT_FLAG.compareAndSet(false, true)) { - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(ApplicationInitListener.class); + private FrameworkModel frameworkModel; + + public ApplicationModel(FrameworkModel frameworkModel) { + super(frameworkModel, new ExtensionDirector(frameworkModel.getExtensionDirector(), ExtensionScope.APPLICATION)); + this.frameworkModel = frameworkModel; + frameworkModel.addApplication(this); + postProcessAfterCreated(); + } + + public static ApplicationModel ofNullable(ApplicationModel applicationModel) { + if (applicationModel != null) { + return applicationModel; + } else { + return defaultModel(); + } + } + + public static ApplicationModel defaultModel() { + if (defaultInstance == null) { + synchronized (ApplicationModel.class) { + if (defaultInstance == null) { + defaultInstance = new ApplicationModel(FrameworkModel.defaultModel()); + } + } + } + return defaultInstance; + } + + public void init() { + if (initFlag.compareAndSet(false, true)) { + ExtensionLoader extensionLoader = this.getExtensionLoader(ApplicationInitListener.class); Set listenerNames = extensionLoader.getSupportedExtensions(); for (String listenerName : listenerNames) { extensionLoader.getExtension(listenerName).init(); @@ -62,99 +97,159 @@ public class ApplicationModel { } } + public void destroy() { + // TODO destroy application resources + } + + public boolean isInit() { + return initFlag.get(); + } + + public FrameworkModel getFrameworkModel() { + return frameworkModel; + } + + @Deprecated public static Collection allConsumerModels() { - return getServiceRepository().getReferredServices(); + return defaultModel().getApplicationServiceRepository().getReferredServices(); } + public Collection allApplicationConsumerModels() { + // TODO: aggregate from sub modules + return defaultModel().getApplicationServiceRepository().getReferredServices(); + } + + + @Deprecated public static Collection allProviderModels() { - return getServiceRepository().getExportedServices(); + return defaultModel().getApplicationServiceRepository().getExportedServices(); } + public Collection allApplicationProviderModels() { + // TODO: aggregate from sub modules + return defaultModel().getApplicationServiceRepository().getExportedServices(); + } + + @Deprecated public static ProviderModel getProviderModel(String serviceKey) { - return getServiceRepository().lookupExportedService(serviceKey); + return defaultModel().getApplicationServiceRepository().lookupExportedService(serviceKey); } + @Deprecated public static ConsumerModel getConsumerModel(String serviceKey) { - return getServiceRepository().lookupReferredService(serviceKey); + return defaultModel().getApplicationServiceRepository().lookupReferredService(serviceKey); } - private static ExtensionLoader LOADER = ExtensionLoader.getExtensionLoader(FrameworkExt.class); - - public static void initFrameworkExts() { - Set exts = ExtensionLoader.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances(); + public void initFrameworkExts() { + Set exts = this.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances(); for (FrameworkExt ext : exts) { ext.initialize(); } } + @Deprecated public static Environment getEnvironment() { + return defaultModel().getApplicationEnvironment(); + } + + public Environment getApplicationEnvironment() { if (environment == null) { - environment = (Environment) LOADER.getExtension(Environment.NAME); + environment = (Environment) this.getExtensionLoader(FrameworkExt.class) + .getExtension(Environment.NAME); } return environment; } + @Deprecated public static ConfigManager getConfigManager() { + return defaultModel().getApplicationConfigManager(); + } + + public ConfigManager getApplicationConfigManager() { if (configManager == null) { - configManager = (ConfigManager) LOADER.getExtension(ConfigManager.NAME); + configManager = (ConfigManager) this.getExtensionLoader(FrameworkExt.class) + .getExtension(ConfigManager.NAME); } return configManager; } + @Deprecated public static ServiceRepository getServiceRepository() { + return defaultModel().getApplicationServiceRepository(); + } + + public ServiceRepository getApplicationServiceRepository() { if (serviceRepository == null) { - serviceRepository = (ServiceRepository) LOADER.getExtension(ServiceRepository.NAME); + serviceRepository = (ServiceRepository) this.getExtensionLoader(FrameworkExt.class) + .getExtension(ServiceRepository.NAME); } return serviceRepository; } + @Deprecated public static ExecutorRepository getExecutorRepository() { - return ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + return defaultModel().getApplicationExecutorRepository(); } - public static ApplicationConfig getApplicationConfig() { - return getConfigManager().getApplicationOrElseThrow(); - } - - public static String getName() { - return getApplicationConfig().getName(); + public ExecutorRepository getApplicationExecutorRepository() { + return this.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); } @Deprecated - //It will be remove at next version - private static String application; + public static ApplicationConfig getApplicationConfig() { + return defaultModel().getCurrentConfig(); + } + + public ApplicationConfig getCurrentConfig() { + return getApplicationConfigManager().getApplicationOrElseThrow(); + } + + @Deprecated + public static String getName() { + return defaultModel().getCurrentConfig().getName(); + } - /** - * - * @deprecated Use {@link #getName()} instead. It will be remove at next version. - */ @Deprecated public static String getApplication() { - return application == null ? getName() : application; + return getName(); } - // Currently used by UT, it will be remove at next version. - @Deprecated - public static void setApplication(String application) { - ApplicationModel.application = application; + public String getApplicationName() { + return getCurrentConfig().getName(); + } + + public void addModule(ModuleModel model) { + if (!this.moduleModels.contains(model)) { + this.moduleModels.add(model); + } + } + + public void removeModule(ModuleModel model) { + this.moduleModels.remove(model); + } + + public List 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() { - if (serviceRepository!=null){ - serviceRepository.destroy(); - serviceRepository = null; + if (defaultInstance != null) { + defaultInstance.destroy(); + defaultInstance = null; } - if (configManager != null) { - configManager.destroy(); - configManager = null; - } - if (environment != null) { - environment.destroy(); - environment = null; - } - ExtensionLoader.resetExtensionLoader(FrameworkExt.class); - LOADER = ExtensionLoader.getExtensionLoader(FrameworkExt.class); } + @Override + public String toString() { + return "ApplicationModel"; + } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java index 06a57252cb..ca27eb7f5b 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java @@ -16,9 +16,10 @@ */ package org.apache.dubbo.rpc.model; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) public interface BuiltinServiceDetector { Class getService(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java index 81b1a883ae..444b85a8e3 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ConsumerModel.java @@ -16,9 +16,7 @@ */ package org.apache.dubbo.rpc.model; -import org.apache.dubbo.common.BaseServiceMetadata; import org.apache.dubbo.common.utils.Assert; -import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.config.ReferenceConfigBase; import java.lang.reflect.Method; @@ -34,15 +32,11 @@ import java.util.TreeSet; /** * This model is bound to your reference's configuration, for example, group, version or method level configuration. */ -public class ConsumerModel { - private String serviceKey; - private final ServiceDescriptor serviceModel; - private final ReferenceConfigBase referenceConfig; +public class ConsumerModel extends ServiceModel { private final Set apps = new TreeSet<>(); - private Object proxyObject; - private final Map methodConfigs; + private Map methodModels = new HashMap<>(); /** * This constructor create an instance of ConsumerModel and passed objects should not be null. @@ -58,57 +52,43 @@ public class ConsumerModel { ReferenceConfigBase referenceConfig, Map methodConfigs) { + super(proxyObject, serviceKey, serviceModel, referenceConfig); Assert.notEmptyString(serviceKey, "Service name can't be null or blank"); - this.serviceKey = serviceKey; - this.proxyObject = proxyObject; - this.serviceModel = serviceModel; - this.referenceConfig = referenceConfig; this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs; } - /** - * Return the proxy object used by called while creating instance of ConsumerModel - * - * @return - */ - public Object getProxyObject() { - return proxyObject; + public ConsumerModel(String serviceKey, + Object proxyObject, + ServiceDescriptor serviceModel, + ReferenceConfigBase referenceConfig, + ServiceMetadata metadata, + Map methodConfigs) { + + super(proxyObject, serviceKey, serviceModel, referenceConfig, metadata); + Assert.notEmptyString(serviceKey, "Service name can't be null or blank"); + + this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs; } - public void setProxyObject(Object proxyObject) { - this.proxyObject = proxyObject; - } + public ConsumerModel(String serviceKey, + Object proxyObject, + ServiceDescriptor serviceModel, + ReferenceConfigBase referenceConfig, + ModuleModel moduleModel, + ServiceMetadata metadata, + Map methodConfigs) { - /** - * Return all method models for the current service - * - * @return method model list - */ - public Set getAllMethods() { - return serviceModel.getAllMethods(); - } + super(proxyObject, serviceKey, serviceModel, referenceConfig, moduleModel, metadata); + Assert.notEmptyString(serviceKey, "Service name can't be null or blank"); - public Class getServiceInterfaceClass() { - return serviceModel.getServiceInterfaceClass(); - } - - public String getServiceKey() { - return serviceKey; + this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs; } public AsyncMethodInfo getMethodConfig(String methodName) { return methodConfigs.get(methodName); } - public ServiceDescriptor getServiceModel() { - return serviceModel; - } - - public ReferenceConfigBase getReferenceConfig() { - return referenceConfig; - } - public Set getApps() { return apps; } @@ -117,41 +97,17 @@ public class ConsumerModel { return methodConfigs.get(methodName); } - /* *************** Start, metadata compatible **************** */ - - private ServiceMetadata serviceMetadata; - private Map methodModels = new HashMap<>(); - - public ConsumerModel(String serviceKey, - Object proxyObject, - ServiceDescriptor serviceModel, - ReferenceConfigBase referenceConfig, - ServiceMetadata metadata, - Map methodConfigs) { - - this(serviceKey, proxyObject, serviceModel, referenceConfig, methodConfigs); - this.serviceMetadata = metadata; - } - - public void setServiceKey(String serviceKey) { - this.serviceKey = serviceKey; - if (serviceMetadata != null) { - serviceMetadata.setServiceKey(serviceKey); - serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey)); - } - } - public void initMethodModels() { Class[] interfaceList; - if (proxyObject == null) { - Class serviceInterfaceClass = referenceConfig.getServiceInterfaceClass(); + if (getProxyObject() == null) { + Class serviceInterfaceClass = getReferenceConfig().getServiceInterfaceClass(); if (serviceInterfaceClass != null) { interfaceList = new Class[]{serviceInterfaceClass}; } else { interfaceList = new Class[0]; } } else { - interfaceList = proxyObject.getClass().getInterfaces(); + interfaceList = getProxyObject().getClass().getInterfaces(); } for (Class interfaceClass : interfaceList) { for (Method method : interfaceClass.getMethods()) { @@ -160,18 +116,6 @@ public class ConsumerModel { } } - public ClassLoader getClassLoader() { - Class serviceType = serviceMetadata.getServiceType(); - return serviceType != null ? serviceType.getClassLoader() : ClassUtils.getClassLoader(); - } - - /** - * @return serviceMetadata - */ - public ServiceMetadata getServiceMetadata() { - return serviceMetadata; - } - /** * Return method model for the given method on consumer side * @@ -214,10 +158,4 @@ public class ConsumerModel { public List getAllMethodModels() { return new ArrayList<>(methodModels.values()); } - - public String getServiceName() { - return this.serviceMetadata.getServiceKey(); - } - - } 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 new file mode 100644 index 0000000000..7b3740f709 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java @@ -0,0 +1,73 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionDirector; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.logger.Logger; +import org.apache.dubbo.common.logger.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * Model of dubbo framework, it can be shared with multiple applications. + */ +public class FrameworkModel extends ScopeModel { + + protected static final Logger LOGGER = LoggerFactory.getLogger(FrameworkModel.class); + + private volatile static FrameworkModel defaultInstance; + + private List applicationModels = Collections.synchronizedList(new ArrayList<>()); + + public FrameworkModel() { + super(null, new ExtensionDirector(null, ExtensionScope.FRAMEWORK)); + postProcessAfterCreated(); + } + + public static FrameworkModel defaultModel() { + if (defaultInstance == null) { + synchronized (FrameworkModel.class) { + if (defaultInstance == null) { + defaultInstance = new FrameworkModel(); + } + } + } + return defaultInstance; + } + + public void addApplication(ApplicationModel model) { + if (!this.applicationModels.contains(model)) { + this.applicationModels.add(model); + } + } + + public void removeApplication(ApplicationModel model) { + this.applicationModels.remove(model); + } + + public List getApplicationModels() { + return applicationModels; + } + + @Override + public String toString() { + return "FrameworkModel"; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java new file mode 100644 index 0000000000..e9757f345c --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionDirector; +import org.apache.dubbo.common.extension.ExtensionScope; + +/** + * Model of a service module + */ +public class ModuleModel extends ScopeModel { + + private final ApplicationModel applicationModel; + + public ModuleModel(ApplicationModel applicationModel) { + super(applicationModel, new ExtensionDirector(applicationModel.getExtensionDirector(), ExtensionScope.MODULE)); + this.applicationModel = applicationModel; + applicationModel.addModule(this); + postProcessAfterCreated(); + } + + public ApplicationModel getApplicationModel() { + return applicationModel; + } + + @Override + public String toString() { + return "ModuleModel"; + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java index a64020413a..235f7a54d2 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ProviderModel.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.rpc.model; -import org.apache.dubbo.common.BaseServiceMetadata; import org.apache.dubbo.common.URL; import org.apache.dubbo.config.ServiceConfigBase; @@ -27,56 +26,57 @@ import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; /** * ProviderModel is about published services */ -public class ProviderModel { - private String serviceKey; - private final Object serviceInstance; - private final ServiceDescriptor serviceModel; - private final ServiceConfigBase serviceConfig; +public class ProviderModel extends ServiceModel { private final List urls; + private final Map> methods = new HashMap>(); public ProviderModel(String serviceKey, Object serviceInstance, ServiceDescriptor serviceModel, ServiceConfigBase serviceConfig) { + super(serviceInstance, serviceKey, serviceModel, serviceConfig); if (null == serviceInstance) { throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL."); } - this.serviceKey = serviceKey; - this.serviceInstance = serviceInstance; - this.serviceModel = serviceModel; - this.serviceConfig = serviceConfig; this.urls = new ArrayList<>(1); } - public String getServiceKey() { - return serviceKey; + public ProviderModel(String serviceKey, + Object serviceInstance, + ServiceDescriptor serviceModel, + ServiceConfigBase serviceConfig, + ServiceMetadata serviceMetadata) { + super(serviceInstance, serviceKey, serviceModel, serviceConfig, serviceMetadata); + if (null == serviceInstance) { + throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL."); + } + + initMethod(serviceModel.getServiceInterfaceClass()); + this.urls = new ArrayList<>(1); } + public ProviderModel(String serviceKey, + Object serviceInstance, + ServiceDescriptor serviceModel, + ServiceConfigBase serviceConfig, + ModuleModel moduleModel, + ServiceMetadata serviceMetadata) { + super(serviceInstance, serviceKey, serviceModel, serviceConfig, moduleModel, serviceMetadata); + if (null == serviceInstance) { + throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL."); + } - public Class getServiceInterfaceClass() { - return serviceModel.getServiceInterfaceClass(); + initMethod(serviceModel.getServiceInterfaceClass()); + this.urls = new ArrayList<>(1); } public Object getServiceInstance() { - return serviceInstance; - } - - public Set getAllMethods() { - return serviceModel.getAllMethods(); - } - - public ServiceDescriptor getServiceModel() { - return serviceModel; - } - - public ServiceConfigBase getServiceConfig() { - return serviceConfig; + return getProxyObject(); } public List getStatedUrl() { @@ -125,35 +125,6 @@ public class ProviderModel { } } - /* *************** Start, metadata compatible **************** */ - - private ServiceMetadata serviceMetadata; - private final Map> methods = new HashMap>(); - - public ProviderModel(String serviceKey, - Object serviceInstance, - ServiceDescriptor serviceModel, - ServiceConfigBase serviceConfig, - ServiceMetadata serviceMetadata) { - this(serviceKey, serviceInstance, serviceModel, serviceConfig); - - this.serviceMetadata = serviceMetadata; - initMethod(serviceModel.getServiceInterfaceClass()); - } - - - public void setServiceKey(String serviceKey) { - this.serviceKey = serviceKey; - if (serviceMetadata != null) { - serviceMetadata.setServiceKey(serviceKey); - serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey)); - } - } - - public String getServiceName() { - return this.serviceMetadata.getServiceKey(); - } - public List getAllMethodModels() { List result = new ArrayList(); for (List models : methods.values()) { @@ -195,10 +166,4 @@ public class ProviderModel { } } - /** - * @return serviceMetadata - */ - public ServiceMetadata getServiceMetadata() { - return serviceMetadata; - } } 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 0000000000..d774bb3a75 --- /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 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/ScopeModelAccessor.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java new file mode 100644 index 0000000000..9e9291e24b --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java @@ -0,0 +1,38 @@ +/* + * 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; + +/** + * An accessor for scope model, it can be use in interface default methods to get scope model. + */ +public interface ScopeModelAccessor { + + ScopeModel getScopeModel(); + + default FrameworkModel getFrameworkModel() { + return ScopeModelUtil.getFrameworkModel(getScopeModel()); + } + + default ApplicationModel getApplicationModel() { + return ScopeModelUtil.getApplicationModel(getScopeModel()); + } + + default ModuleModel getModuleModel() { + return ScopeModelUtil.getModuleModel(getScopeModel()); + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java new file mode 100644 index 0000000000..6b60567965 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAware.java @@ -0,0 +1,52 @@ +/* + * 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; + +/** + * An interface to inject FrameworkModel/ApplicationModel/ModuleModel for SPI extensions and internal beans. + */ +public interface ScopeModelAware { + + /** + * Override this method if you need get the scope model (maybe one of FrameworkModel/ApplicationModel/ModuleModel). + * @param scopeModel + */ + default void setScopeModel(ScopeModel scopeModel) { + } + + /** + * Override this method if you just need framework model + * @param frameworkModel + */ + default void setFrameworkModel(FrameworkModel frameworkModel) { + } + + /** + * Override this method if you just need application model + * @param applicationModel + */ + default void setApplicationModel(ApplicationModel applicationModel) { + } + + /** + * Override this method if you just need module model + * @param moduleModel + */ + default void setModuleModel(ModuleModel moduleModel) { + } + +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java new file mode 100644 index 0000000000..49e30128b9 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAwareExtensionProcessor.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionPostProcessor; + +public class ScopeModelAwareExtensionProcessor implements ExtensionPostProcessor { + private ScopeModel scopeModel; + private FrameworkModel frameworkModel; + private ApplicationModel applicationModel; + private ModuleModel moduleModel; + private volatile boolean inited; + + public ScopeModelAwareExtensionProcessor(ScopeModel scopeModel) { + this.scopeModel = scopeModel; + } + + private void init() { + if (inited) { + return; + } + + // NOTE: Do not create a new model or use the default application/module model here! + // Only the visible and only matching scope model can be injected, that is, module -> application -> framework. + // The converse is a one-to-many relationship and cannot be injected. + // One framework may have multiple applications, and one application may have multiple modules. + // So, the spi extension/bean of application scope can be injected it's application model and framework model, + // but the spi extension/bean of framework scope cannot be injected an application or module model. + + if (scopeModel instanceof FrameworkModel) { + frameworkModel = (FrameworkModel) scopeModel; + } else if (scopeModel instanceof ApplicationModel) { + applicationModel = (ApplicationModel) scopeModel; + frameworkModel = applicationModel.getFrameworkModel(); + } else if (scopeModel instanceof ModuleModel) { + moduleModel = (ModuleModel) scopeModel; + applicationModel = moduleModel.getApplicationModel(); + frameworkModel = applicationModel.getFrameworkModel(); + } + inited = true; + } + + @Override + public Object postProcessAfterInitialization(Object instance, String name) throws Exception { + 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/ScopeModelPostProcessor.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java new file mode 100644 index 0000000000..5a78a3f883 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +/** + * A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel) + */ +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface ScopeModelPostProcessor { + + /** + * 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 0000000000..a23a84d770 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.extension.SPI; + +public class ScopeModelUtil { + + public static ModuleModel getModuleModel(ScopeModel scopeModel) { + if (scopeModel == null) { + return ApplicationModel.defaultModel().getDefaultModule(); + } + if (scopeModel instanceof ModuleModel) { + return (ModuleModel) scopeModel; + } else { + throw new IllegalArgumentException("Unable to get ModuleModel from" + scopeModel); + } + } + + public static ApplicationModel getApplicationModel(ScopeModel scopeModel) { + if (scopeModel == null) { + return ApplicationModel.defaultModel(); + } + if (scopeModel instanceof ApplicationModel) { + return (ApplicationModel) scopeModel; + } else if (scopeModel instanceof ModuleModel) { + ModuleModel moduleModel = (ModuleModel) scopeModel; + return moduleModel.getApplicationModel(); + } else { + throw new IllegalArgumentException("Unable to get ApplicationModel from" + scopeModel); + } + } + + public static FrameworkModel getFrameworkModel(ScopeModel scopeModel) { + if (scopeModel == null) { + return FrameworkModel.defaultModel(); + } + 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; + } else { + throw new IllegalArgumentException("Unable to get FrameworkModel from" + scopeModel); + } + } + + public static ExtensionLoader getExtensionLoader(Class type, ScopeModel scopeModel) { + if(scopeModel != null) { + return scopeModel.getExtensionLoader(type); + } else { + SPI spi = type.getAnnotation(SPI.class); + switch (spi.scope()) { + case FRAMEWORK: + return FrameworkModel.defaultModel().getExtensionLoader(type); + case APPLICATION: + return ApplicationModel.defaultModel().getExtensionLoader(type); + default: + return ApplicationModel.defaultModel().getDefaultModule().getExtensionLoader(type); + } + } + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java new file mode 100644 index 0000000000..35bf5e3ea2 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java @@ -0,0 +1,128 @@ +/* + * 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.BaseServiceMetadata; +import org.apache.dubbo.common.utils.ClassUtils; +import org.apache.dubbo.config.AbstractInterfaceConfig; +import org.apache.dubbo.config.ReferenceConfigBase; +import org.apache.dubbo.config.ServiceConfigBase; + +import java.util.Set; + +public class ServiceModel { + private String serviceKey; + private Object proxyObject; + private final ModuleModel moduleModel; + private final ServiceDescriptor serviceModel; + private final AbstractInterfaceConfig config; + + private ServiceMetadata serviceMetadata; + + public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config) { + this(proxyObject, serviceKey, serviceModel, config, null); + } + + public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ServiceMetadata serviceMetadata) { + this(proxyObject, serviceKey, serviceModel, config, ScopeModelUtil.getModuleModel(config != null ? config.getScopeModel() : null), serviceMetadata); + } + public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ModuleModel moduleModel, ServiceMetadata serviceMetadata) { + this.proxyObject = proxyObject; + this.serviceKey = serviceKey; + this.serviceModel = serviceModel; + this.moduleModel = moduleModel; + this.config = config; + this.serviceMetadata = serviceMetadata; + } + + public String getServiceKey() { + return serviceKey; + } + + public void setProxyObject(Object proxyObject) { + this.proxyObject = proxyObject; + } + + public Object getProxyObject() { + return proxyObject; + } + + public ServiceDescriptor getServiceModel() { + return serviceModel; + } + + public ClassLoader getClassLoader() { + Class serviceType = serviceMetadata.getServiceType(); + return serviceType != null ? serviceType.getClassLoader() : ClassUtils.getClassLoader(); + } + + /** + * Return all method models for the current service + * + * @return method model list + */ + public Set getAllMethods() { + return serviceModel.getAllMethods(); + } + + public Class getServiceInterfaceClass() { + return serviceModel.getServiceInterfaceClass(); + } + + public AbstractInterfaceConfig getConfig() { + return config; + } + + public ReferenceConfigBase getReferenceConfig() { + if (config instanceof ReferenceConfigBase) { + return (ReferenceConfigBase) config; + } else { + throw new IllegalArgumentException("Current ServiceModel is not a ConsumerModel"); + } + } + + public ServiceConfigBase getServiceConfig() { + if (config instanceof ServiceConfigBase) { + return (ServiceConfigBase) config; + } else { + throw new IllegalArgumentException("Current ServiceModel is not a ProviderModel"); + } + } + + public void setServiceKey(String serviceKey) { + this.serviceKey = serviceKey; + if (serviceMetadata != null) { + serviceMetadata.setServiceKey(serviceKey); + serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey)); + } + } + + public String getServiceName() { + return this.serviceMetadata.getServiceKey(); + } + + /** + * @return serviceMetadata + */ + public ServiceMetadata getServiceMetadata() { + return serviceMetadata; + } + + public ModuleModel getModuleModel() { + return moduleModel; + } +} 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 7567dcd32d..c136593c3d 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; @@ -30,14 +31,13 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; -import java.util.Map; import java.util.concurrent.ConcurrentHashMap; 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 +55,15 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt // useful to find a url quickly with serviceInterfaceName:version private ConcurrentMap> providerUrlsWithoutGroup = new ConcurrentHashMap<>(); + private ExtensionAccessor extensionAccessor; public ServiceRepository() { + } + + @Override + public void initialize() throws IllegalStateException { Set builtinServices - = ExtensionLoader.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances(); + = extensionAccessor.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances(); if (CollectionUtils.isNotEmpty(builtinServices)) { for (BuiltinServiceDetector service : builtinServices) { registerService(service.getService()); @@ -104,13 +109,16 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt ServiceDescriptor serviceDescriptor, ReferenceConfigBase rc, Object proxy, - ServiceMetadata serviceMetadata, - Map methodConfigs) { + ServiceMetadata serviceMetadata) { ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor, rc, - serviceMetadata, methodConfigs); + serviceMetadata, null); consumers.putIfAbsent(serviceKey, consumerModel); } + public void registerConsumer(ConsumerModel consumerModel) { + consumers.putIfAbsent(consumerModel.getServiceKey(), consumerModel); + } + public void reRegisterConsumer(String newServiceKey, String serviceKey) { ConsumerModel consumerModel = consumers.get(serviceKey); consumerModel.setServiceKey(newServiceKey); @@ -124,12 +132,17 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt ServiceDescriptor serviceModel, ServiceConfigBase serviceConfig, ServiceMetadata serviceMetadata) { - ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel, serviceConfig, - serviceMetadata); + ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel, + serviceConfig, serviceMetadata); providers.putIfAbsent(serviceKey, providerModel); providersWithoutGroup.putIfAbsent(keyWithoutGroup(serviceKey), providerModel); } + public void registerProvider(ProviderModel providerModel) { + providers.putIfAbsent(providerModel.getServiceKey(), providerModel); + providersWithoutGroup.putIfAbsent(keyWithoutGroup(providerModel.getServiceKey()), providerModel); + } + private static String keyWithoutGroup(String serviceKey) { String interfaceName = interfaceFromServiceKey(serviceKey); String version = versionFromServiceKey(serviceKey); @@ -213,4 +226,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.ExtensionFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory deleted file mode 100644 index 094382f773..0000000000 --- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory +++ /dev/null @@ -1,2 +0,0 @@ -adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory -spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory \ No newline at end of file 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 new file mode 100644 index 0000000000..a6ef1e3e2e --- /dev/null +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector @@ -0,0 +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/ConfigurationUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java index 1c8a549d8a..d10ad6a4d6 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/ConfigurationUtilsTest.java @@ -16,6 +16,8 @@ */ package org.apache.dubbo.common.config; +import org.apache.dubbo.rpc.model.ApplicationModel; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -31,14 +33,14 @@ public class ConfigurationUtilsTest { @Test public void testGetServerShutdownTimeout () { System.setProperty(SHUTDOWN_WAIT_KEY, " 10000"); - Assertions.assertEquals(10000, ConfigurationUtils.getServerShutdownTimeout()); + Assertions.assertEquals(10000, ConfigurationUtils.getServerShutdownTimeout(ApplicationModel.defaultModel())); System.clearProperty(SHUTDOWN_WAIT_KEY); } @Test public void testGetProperty () { System.setProperty(SHUTDOWN_WAIT_KEY, " 10000"); - Assertions.assertEquals("10000", ConfigurationUtils.getProperty(SHUTDOWN_WAIT_KEY)); + Assertions.assertEquals("10000", ConfigurationUtils.getProperty(ApplicationModel.defaultModel(), SHUTDOWN_WAIT_KEY)); System.clearProperty(SHUTDOWN_WAIT_KEY); } diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentTest.java index 34f8884fae..2a93ca71a0 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/EnvironmentTest.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.config; import org.apache.dubbo.rpc.model.ApplicationModel; + import org.junit.jupiter.api.Test; import java.util.LinkedHashMap; @@ -31,7 +32,7 @@ public class EnvironmentTest { @Test public void testResolvePlaceholders1() { - Environment environment = ApplicationModel.getEnvironment(); + Environment environment = ApplicationModel.defaultModel().getApplicationEnvironment(); Map externalMap = new LinkedHashMap<>(); externalMap.put("zookeeper.address", "127.0.0.1"); 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 9e8991d4a7..7af1663474 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/ExtensionDirectorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java new file mode 100644 index 0000000000..f2d403055e --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java @@ -0,0 +1,271 @@ +/* + * 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; + +import org.apache.dubbo.common.extension.director.FooAppService; +import org.apache.dubbo.common.extension.director.FooFrameworkService; +import org.apache.dubbo.common.extension.director.FooModuleProvider; +import org.apache.dubbo.common.extension.director.FooModuleService; +import org.apache.dubbo.common.extension.director.impl.TestAppService; +import org.apache.dubbo.common.extension.director.impl.TestFrameworkService; +import org.apache.dubbo.common.extension.director.impl.TestModuleService; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +public class ExtensionDirectorTest { + + String testFwSrvName = "testFwSrv"; + String testAppSrvName = "testAppSrv"; + String testMdSrvName = "testMdSrv"; + + String testAppProviderName = "testAppProvider"; + String testModuleProviderName = "testModuleProvider"; + String testFrameworkProviderName = "testFrameworkProvider"; + + @Test + public void testInheritanceAndScope() { + + // Expecting: + // 1. SPI extension only be created in ExtensionDirector which matched scope + // 2. Child ExtensionDirector can get extension instance from parent + // 3. Parent ExtensionDirector can't get extension instance from child + + ExtensionDirector fwExtensionDirector = new ExtensionDirector(null, ExtensionScope.FRAMEWORK); + ExtensionDirector appExtensionDirector = new ExtensionDirector(fwExtensionDirector, ExtensionScope.APPLICATION); + ExtensionDirector moduleExtensionDirector = new ExtensionDirector(appExtensionDirector, ExtensionScope.MODULE); + + // test module extension loader + FooFrameworkService testFwSrvFromModule = moduleExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + FooAppService testAppSrvFromModule = moduleExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + FooModuleService testMdSrvFromModule = moduleExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertNotNull(testFwSrvFromModule); + Assertions.assertNotNull(testAppSrvFromModule); + Assertions.assertNotNull(testMdSrvFromModule); + + // test app extension loader + FooFrameworkService testFwSrvFromApp = appExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + FooAppService testAppSrvFromApp = appExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + FooModuleService testMdSrvFromApp = appExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertSame(testFwSrvFromApp, testFwSrvFromModule); + Assertions.assertSame(testAppSrvFromApp, testAppSrvFromModule); + Assertions.assertNull(testMdSrvFromApp); + + // test framework extension loader + FooFrameworkService testFwSrvFromFw = fwExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + FooAppService testAppSrvFromFw = fwExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + FooModuleService testMdSrvFromFw = fwExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertSame(testFwSrvFromFw, testFwSrvFromApp); + Assertions.assertNull(testAppSrvFromFw); + Assertions.assertNull(testMdSrvFromFw); + } + + @Test + public void testPostProcessor() { + + } + + @Test + public void testModelAware() { + // Expecting: + // 1. Module scope SPI can be injected ModuleModel, ApplicationModel, FrameworkModel + // 2. Application scope SPI can be injected ApplicationModel, FrameworkModel, but not ModuleModel + // 3. Framework scope SPI can be injected FrameworkModel, but not ModuleModel, ApplicationModel + + FrameworkModel frameworkModel = new FrameworkModel(); + ApplicationModel applicationModel = new ApplicationModel(frameworkModel); + ModuleModel moduleModel = new ModuleModel(applicationModel); + + ExtensionDirector moduleExtensionDirector = moduleModel.getExtensionDirector(); + ExtensionDirector appExtensionDirector = applicationModel.getExtensionDirector(); + ExtensionDirector fwExtensionDirector = frameworkModel.getExtensionDirector(); + + // check extension director inheritance + Assertions.assertSame(appExtensionDirector, moduleExtensionDirector.getParent()); + Assertions.assertSame(fwExtensionDirector, appExtensionDirector.getParent()); + Assertions.assertSame(null, fwExtensionDirector.getParent()); + + // check module extension aware + TestFrameworkService testFwSrvFromModule = (TestFrameworkService) moduleExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + TestAppService testAppSrvFromModule = (TestAppService) moduleExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + TestModuleService testMdSrvFromModule = (TestModuleService) moduleExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertSame(frameworkModel, testFwSrvFromModule.getFrameworkModel()); + Assertions.assertSame(null, testFwSrvFromModule.getApplicationModel()); + Assertions.assertSame(null, testFwSrvFromModule.getModuleModel()); + + Assertions.assertSame(frameworkModel, testAppSrvFromModule.getFrameworkModel()); + Assertions.assertSame(applicationModel, testAppSrvFromModule.getApplicationModel()); + Assertions.assertSame(null, testAppSrvFromModule.getModuleModel()); + + Assertions.assertSame(frameworkModel, testMdSrvFromModule.getFrameworkModel()); + Assertions.assertSame(applicationModel, testMdSrvFromModule.getApplicationModel()); + Assertions.assertSame(moduleModel, testMdSrvFromModule.getModuleModel()); + + // check app extension aware + TestFrameworkService testFwSrvFromApp = (TestFrameworkService) appExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + TestAppService testAppSrvFromApp = (TestAppService) appExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + TestModuleService testMdSrvFromApp = (TestModuleService) appExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertSame(testFwSrvFromApp, testFwSrvFromModule); + Assertions.assertSame(testAppSrvFromApp, testAppSrvFromModule); + Assertions.assertNull(testMdSrvFromApp); + + // check framework extension aware + FooFrameworkService testFwSrvFromFw = fwExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName); + FooAppService testAppSrvFromFw = fwExtensionDirector.getExtension(FooAppService.class, testAppSrvName); + FooModuleService testMdSrvFromFw = fwExtensionDirector.getExtension(FooModuleService.class, testMdSrvName); + + Assertions.assertSame(testFwSrvFromFw, testFwSrvFromApp); + Assertions.assertNull(testAppSrvFromFw); + Assertions.assertNull(testMdSrvFromFw); + } + + @Test + public void testModelDataIsolation() { +//Model Tree +//├─frameworkModel1 +//│ ├─applicationModel11 +//│ │ ├─moduleModel111 +//│ │ └─moduleModel112 +//│ └─applicationModel12 +//│ └─moduleModel121 +//└─frameworkModel2 +// └─applicationModel21 +// └─moduleModel211 + + FrameworkModel frameworkModel1 = new FrameworkModel(); + ApplicationModel applicationModel11 = new ApplicationModel(frameworkModel1); + ModuleModel moduleModel111 = new ModuleModel(applicationModel11); + ModuleModel moduleModel112 = new ModuleModel(applicationModel11); + + ApplicationModel applicationModel12 = new ApplicationModel(frameworkModel1); + ModuleModel moduleModel121 = new ModuleModel(applicationModel12); + + FrameworkModel frameworkModel2 = new FrameworkModel(); + ApplicationModel applicationModel21 = new ApplicationModel(frameworkModel2); + ModuleModel moduleModel211 = new ModuleModel(applicationModel21); + + // test model references + Collection applicationsOfFw1 = frameworkModel1.getApplicationModels(); + Assertions.assertEquals(2, applicationsOfFw1.size()); + Assertions.assertTrue(applicationsOfFw1.contains(applicationModel11)); + Assertions.assertTrue(applicationsOfFw1.contains(applicationModel12)); + Assertions.assertFalse(applicationsOfFw1.contains(applicationModel21)); + + Collection modulesOfApp11 = applicationModel11.getModuleModels(); + Assertions.assertEquals(2, modulesOfApp11.size()); + Assertions.assertTrue(modulesOfApp11.contains(moduleModel111)); + Assertions.assertTrue(modulesOfApp11.contains(moduleModel112)); + + // test isolation of FrameworkModel + FooFrameworkService frameworkService1 = frameworkModel1.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + FooFrameworkService frameworkService2 = frameworkModel2.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + Assertions.assertNotSame(frameworkService1, frameworkService2); + + // test isolation of ApplicationModel + // applicationModel11 and applicationModel12 are shared frameworkModel1 + FooFrameworkService frameworkService11 = applicationModel11.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + FooFrameworkService frameworkService12 = applicationModel12.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + Assertions.assertSame(frameworkService1, frameworkService11); + Assertions.assertSame(frameworkService1, frameworkService12); + + // applicationModel11 and applicationModel12 are isolated in application scope + FooAppService applicationService11 = applicationModel11.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + FooAppService applicationService12 = applicationModel12.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + Assertions.assertNotSame(applicationService11, applicationService12); + + // applicationModel11 and applicationModel21 are isolated in both framework and application scope + FooFrameworkService frameworkService21 = applicationModel21.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + FooAppService applicationService21 = applicationModel21.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + Assertions.assertNotSame(frameworkService11, frameworkService21); + Assertions.assertNotSame(applicationService11, applicationService21); + + // test isolation of ModuleModel + FooModuleService moduleService111 = moduleModel111.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName); + FooModuleService moduleService112 = moduleModel112.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName); + + // moduleModel111 and moduleModel112 are isolated in module scope + Assertions.assertNotSame(moduleService111, moduleService112); + + // moduleModel111 and moduleModel112 are shared applicationModel11 + FooAppService applicationService111 = moduleModel111.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + FooAppService applicationService112 = moduleModel112.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + Assertions.assertSame(applicationService111, applicationService112); + + // moduleModel111 and moduleModel121 are isolated in application scope, but shared frameworkModel1 + FooAppService applicationService121 = moduleModel121.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + Assertions.assertNotSame(applicationService111, applicationService121); + + FooFrameworkService frameworkService111 = moduleModel111.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + FooFrameworkService frameworkService121 = moduleModel121.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + Assertions.assertSame(frameworkService111, frameworkService121); + + // moduleModel111 and moduleModel211 are isolated in both framework and application scope + FooModuleService moduleService211 = moduleModel211.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName); + FooAppService applicationService211 = moduleModel211.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName); + FooFrameworkService frameworkService211 = moduleModel211.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName); + Assertions.assertNotSame(moduleService111, moduleService211); + Assertions.assertNotSame(applicationService111, applicationService211); + Assertions.assertNotSame(frameworkService111, frameworkService211); + } + + @Test + public void testInjection() { + + // Expect: + // 1. Framework scope extension can be injected to extensions of Framework/Application/Module scope + // 2. Application scope extension can be injected to extensions of Application/Module scope, but not Framework scope + // 3. Module scope extension can be injected to extensions of Module scope, but not Framework/Application scope + + FrameworkModel frameworkModel = new FrameworkModel(); + ApplicationModel applicationModel = new ApplicationModel(frameworkModel); + ModuleModel moduleModel = new ModuleModel(applicationModel); + + // check module service + TestModuleService moduleService = (TestModuleService) moduleModel.getExtensionDirector() + .getExtension(FooModuleService.class, testMdSrvName); + Assertions.assertNotNull(moduleService.getFrameworkService()); + Assertions.assertNotNull(moduleService.getFrameworkProvider()); + Assertions.assertNotNull(moduleService.getAppService()); + Assertions.assertNotNull(moduleService.getAppProvider()); + Assertions.assertNotNull(moduleService.getModuleProvider()); + + // check app service + TestAppService appService = (TestAppService) applicationModel.getExtensionDirector() + .getExtension(FooAppService.class, testAppSrvName); + Assertions.assertNotNull(appService.getFrameworkService()); + Assertions.assertNotNull(appService.getFrameworkProvider()); + Assertions.assertNotNull(appService.getAppProvider()); + Assertions.assertNull(appService.getModuleProvider()); + + // check framework service + TestFrameworkService frameworkService = (TestFrameworkService) frameworkModel.getExtensionDirector() + .getExtension(FooFrameworkService.class, testFwSrvName); + Assertions.assertNotNull(frameworkService.getFrameworkProvider()); + Assertions.assertNull(frameworkService.getAppProvider()); + Assertions.assertNull(frameworkService.getModuleProvider()); + + } +} 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 57736b8bb5..1e474eb139 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 @@ -61,6 +61,7 @@ import org.apache.dubbo.common.extension.injection.impl.InjectExtImpl; import org.apache.dubbo.common.lang.Prioritized; import org.apache.dubbo.common.url.component.ServiceConfigURL; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -70,7 +71,6 @@ import java.util.List; import java.util.Set; import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; import static org.apache.dubbo.common.extension.ExtensionLoader.getLoadingStrategies; import static org.hamcrest.CoreMatchers.allOf; import static org.hamcrest.CoreMatchers.anyOf; @@ -84,6 +84,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; public class ExtensionLoaderTest { + + private ExtensionLoader getExtensionLoader(Class type) { + return ApplicationModel.defaultModel().getExtensionDirector().getExtensionLoader(type); + } + @Test public void test_getExtensionLoader_Null() throws Exception { try { @@ -266,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 @@ -277,7 +281,6 @@ public class ExtensionLoaderTest { assertThat(ext, instanceOf(Ext9Empty.class)); assertEquals("ext9", getExtensionLoader(Ext9Empty.class).getExtensionName(Ext9EmptyImpl.class)); - ExtensionLoader.resetExtensionLoader(Ext9Empty.class); } @Test @@ -299,7 +302,6 @@ public class ExtensionLoaderTest { AddExt2 adaptive = loader.getAdaptiveExtension(); assertTrue(adaptive instanceof AddExt2_ManualAdaptive); - ExtensionLoader.resetExtensionLoader(AddExt2.class); } @Test @@ -338,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 @@ -352,7 +353,6 @@ public class ExtensionLoaderTest { adaptive = loader.getAdaptiveExtension(); assertTrue(adaptive instanceof AddExt3_ManualAdaptive); - ExtensionLoader.resetExtensionLoader(AddExt3.class); } @Test @@ -559,7 +559,7 @@ public class ExtensionLoaderTest { List loadingStrategies = ExtensionLoader.getLoadingStrategies(); ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(false), new DubboInternalLoadingStrategyTest(false)); - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedWithoutOverriddenExt.class); + ExtensionLoader extensionLoader = getExtensionLoader(DuplicatedWithoutOverriddenExt.class); try { extensionLoader.getExtension("duplicated"); fail(); @@ -577,7 +577,7 @@ public class ExtensionLoaderTest { List loadingStrategies = ExtensionLoader.getLoadingStrategies(); ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(true), new DubboInternalLoadingStrategyTest(true)); - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedOverriddenExt.class); + ExtensionLoader extensionLoader = getExtensionLoader(DuplicatedOverriddenExt.class); DuplicatedOverriddenExt duplicatedOverriddenExt = extensionLoader.getExtension("duplicated"); assertEquals("DuplicatedOverriddenExt1", duplicatedOverriddenExt.echo()); //recover the loading strategies diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java new file mode 100644 index 0000000000..e88527123c --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java @@ -0,0 +1,30 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.APPLICATION) +public interface FooAppProvider { + + @Adaptive + void process(URL url); + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java new file mode 100644 index 0000000000..d475092ffb --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java @@ -0,0 +1,28 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.APPLICATION) +public interface FooAppService { + @Adaptive + void process(URL url); +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java new file mode 100644 index 0000000000..194c818279 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java @@ -0,0 +1,30 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface FooFrameworkProvider { + + @Adaptive + void process(URL url); + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java new file mode 100644 index 0000000000..2ff140333a --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java @@ -0,0 +1,28 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.FRAMEWORK) +public interface FooFrameworkService { + @Adaptive + void process(URL url); +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java new file mode 100644 index 0000000000..9d4b81ed8a --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java @@ -0,0 +1,30 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.MODULE) +public interface FooModuleProvider { + + @Adaptive + void process(URL url); + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java new file mode 100644 index 0000000000..87ce080a7e --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java @@ -0,0 +1,30 @@ +/* + * 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.director; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.Adaptive; +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.MODULE) +public interface FooModuleService { + + @Adaptive + void process(URL url); + +} 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 new file mode 100644 index 0000000000..e3171a4131 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/BaseTestService.java @@ -0,0 +1,55 @@ +/* + * 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.director.impl; + +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; +import org.apache.dubbo.rpc.model.ModuleModel; + +public class BaseTestService implements ScopeModelAware { + private FrameworkModel frameworkModel; + private ApplicationModel applicationModel; + private ModuleModel moduleModel; + + @Override + public void setFrameworkModel(FrameworkModel frameworkModel) { + this.frameworkModel = frameworkModel; + } + + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } + + @Override + public void setModuleModel(ModuleModel moduleModel) { + this.moduleModel = moduleModel; + } + + public FrameworkModel getFrameworkModel() { + return frameworkModel; + } + + public ApplicationModel getApplicationModel() { + return applicationModel; + } + + public ModuleModel getModuleModel() { + return moduleModel; + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java new file mode 100644 index 0000000000..cf60246b2c --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.extension.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooAppProvider; + +public class TestAppProvider implements FooAppProvider { + @Override + public void process(URL url) { + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppService.java new file mode 100644 index 0000000000..ed5aec4eda --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppService.java @@ -0,0 +1,72 @@ +/* + * 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.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooAppProvider; +import org.apache.dubbo.common.extension.director.FooAppService; +import org.apache.dubbo.common.extension.director.FooFrameworkProvider; +import org.apache.dubbo.common.extension.director.FooFrameworkService; +import org.apache.dubbo.common.extension.director.FooModuleProvider; + +public class TestAppService extends BaseTestService implements FooAppService { + + private FooFrameworkService frameworkService; + + private FooFrameworkProvider frameworkProvider; + + private FooAppProvider appProvider; + + private FooModuleProvider moduleProvider; + + public FooFrameworkService getFrameworkService() { + return frameworkService; + } + + public void setFrameworkService(FooFrameworkService frameworkService) { + this.frameworkService = frameworkService; + } + + public FooAppProvider getAppProvider() { + return appProvider; + } + + public void setAppProvider(FooAppProvider appProvider) { + this.appProvider = appProvider; + } + + public FooModuleProvider getModuleProvider() { + return moduleProvider; + } + + public void setModuleProvider(FooModuleProvider moduleProvider) { + this.moduleProvider = moduleProvider; + } + + public FooFrameworkProvider getFrameworkProvider() { + return frameworkProvider; + } + + public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) { + this.frameworkProvider = frameworkProvider; + } + + @Override + public void process(URL url) { + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java new file mode 100644 index 0000000000..25dcb66dcf --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.extension.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooFrameworkProvider; + +public class TestFrameworkProvider implements FooFrameworkProvider { + @Override + public void process(URL url) { + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkService.java new file mode 100644 index 0000000000..45b71b1b1b --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkService.java @@ -0,0 +1,61 @@ +/* + * 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.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooAppProvider; +import org.apache.dubbo.common.extension.director.FooFrameworkProvider; +import org.apache.dubbo.common.extension.director.FooFrameworkService; +import org.apache.dubbo.common.extension.director.FooModuleProvider; + +public class TestFrameworkService extends BaseTestService implements FooFrameworkService { + + private FooFrameworkProvider frameworkProvider; + + private FooAppProvider appProvider; + + private FooModuleProvider moduleProvider; + + public FooFrameworkProvider getFrameworkProvider() { + return frameworkProvider; + } + + public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) { + this.frameworkProvider = frameworkProvider; + } + + public FooAppProvider getAppProvider() { + return appProvider; + } + + public void setAppProvider(FooAppProvider appProvider) { + this.appProvider = appProvider; + } + + public FooModuleProvider getModuleProvider() { + return moduleProvider; + } + + public void setModuleProvider(FooModuleProvider moduleProvider) { + this.moduleProvider = moduleProvider; + } + + @Override + public void process(URL url) { + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java new file mode 100644 index 0000000000..604c2919d1 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java @@ -0,0 +1,28 @@ +/* + * 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.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooModuleProvider; + +public class TestModuleProvider implements FooModuleProvider { + + public void process(URL url) { + + } + +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleService.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleService.java new file mode 100644 index 0000000000..d7c0ad79b0 --- /dev/null +++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleService.java @@ -0,0 +1,83 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common.extension.director.impl; + +import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.director.FooAppProvider; +import org.apache.dubbo.common.extension.director.FooAppService; +import org.apache.dubbo.common.extension.director.FooFrameworkProvider; +import org.apache.dubbo.common.extension.director.FooFrameworkService; +import org.apache.dubbo.common.extension.director.FooModuleProvider; +import org.apache.dubbo.common.extension.director.FooModuleService; + +public class TestModuleService extends BaseTestService implements FooModuleService { + + private FooFrameworkService frameworkService; + + private FooFrameworkProvider frameworkProvider; + + private FooAppService appService; + + private FooAppProvider appProvider; + + private FooModuleProvider moduleProvider; + + public FooFrameworkService getFrameworkService() { + return frameworkService; + } + + public void setFrameworkService(FooFrameworkService frameworkService) { + this.frameworkService = frameworkService; + } + + public FooAppProvider getAppProvider() { + return appProvider; + } + + public void setAppProvider(FooAppProvider appProvider) { + this.appProvider = appProvider; + } + + public FooModuleProvider getModuleProvider() { + return moduleProvider; + } + + public void setModuleProvider(FooModuleProvider moduleProvider) { + this.moduleProvider = moduleProvider; + } + + public FooFrameworkProvider getFrameworkProvider() { + return frameworkProvider; + } + + public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) { + this.frameworkProvider = frameworkProvider; + } + + public FooAppService getAppService() { + return appService; + } + + public void setAppService(FooAppService appService) { + this.appService = appService; + } + + @Override + public void process(URL url) { + + } +} diff --git a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java index b15f9c5515..a80fffd62a 100644 --- a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java +++ b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java @@ -25,8 +25,8 @@ import org.apache.dubbo.config.MonitorConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.ProviderConfig; import org.apache.dubbo.config.RegistryConfig; - import org.apache.dubbo.rpc.model.ApplicationModel; + import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,7 +36,6 @@ import java.util.Collection; import static java.util.Arrays.asList; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; import static org.apache.dubbo.config.context.ConfigManager.DUBBO_CONFIG_MODE; -import static org.apache.dubbo.rpc.model.ApplicationModel.getConfigManager; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNull; @@ -50,7 +49,7 @@ import static org.junit.jupiter.api.Assertions.fail; */ public class ConfigManagerTest { - private ConfigManager configManager = getConfigManager(); + private ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager(); @BeforeEach public void init() { @@ -256,15 +255,16 @@ public class ConfigManagerTest { try { // test strict mode ApplicationModel.reset(); - Assertions.assertEquals(ConfigMode.STRICT, getConfigManager().getConfigMode()); + ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager(); + Assertions.assertEquals(ConfigMode.STRICT, configManager.getConfigMode()); System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.STRICT.name()); ApplicationModel.reset(); - Assertions.assertEquals(ConfigMode.STRICT, getConfigManager().getConfigMode()); + Assertions.assertEquals(ConfigMode.STRICT, configManager.getConfigMode()); - getConfigManager().addConfig(applicationConfig1); + configManager.addConfig(applicationConfig1); try { - getConfigManager().addConfig(applicationConfig2); + configManager.addConfig(applicationConfig2); fail("strict mode cannot add two application configs"); } catch (Exception e) { assertEquals(IllegalStateException.class, e.getClass()); @@ -274,21 +274,23 @@ public class ConfigManagerTest { // test override mode System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.OVERRIDE.name()); ApplicationModel.reset(); - Assertions.assertEquals(ConfigMode.OVERRIDE, getConfigManager().getConfigMode()); + configManager = ApplicationModel.defaultModel().getApplicationConfigManager(); + Assertions.assertEquals(ConfigMode.OVERRIDE, configManager.getConfigMode()); - getConfigManager().addConfig(applicationConfig1); - getConfigManager().addConfig(applicationConfig2); - assertEquals(applicationConfig2, getConfigManager().getApplicationOrElseThrow()); + configManager.addConfig(applicationConfig1); + configManager.addConfig(applicationConfig2); + assertEquals(applicationConfig2, configManager.getApplicationOrElseThrow()); // test ignore mode System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.IGNORE.name()); ApplicationModel.reset(); - Assertions.assertEquals(ConfigMode.IGNORE, getConfigManager().getConfigMode()); + configManager = ApplicationModel.defaultModel().getApplicationConfigManager(); + Assertions.assertEquals(ConfigMode.IGNORE, configManager.getConfigMode()); - getConfigManager().addConfig(applicationConfig1); - getConfigManager().addConfig(applicationConfig2); - assertEquals(applicationConfig1, getConfigManager().getApplicationOrElseThrow()); + configManager.addConfig(applicationConfig1); + configManager.addConfig(applicationConfig2); + assertEquals(applicationConfig1, configManager.getApplicationOrElseThrow()); } finally { System.clearProperty(DUBBO_CONFIG_MODE); } diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppProvider b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppProvider new file mode 100644 index 0000000000..667a52d366 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppProvider @@ -0,0 +1 @@ +testAppProvider=org.apache.dubbo.common.extension.director.impl.TestAppProvider diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppService b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppService new file mode 100644 index 0000000000..37fe7c360a --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooAppService @@ -0,0 +1 @@ +testAppSrv=org.apache.dubbo.common.extension.director.impl.TestAppService diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkProvider b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkProvider new file mode 100644 index 0000000000..a1f9f61815 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkProvider @@ -0,0 +1 @@ +testFrameworkProvider=org.apache.dubbo.common.extension.director.impl.TestFrameworkProvider diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkService b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkService new file mode 100644 index 0000000000..f695488f79 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooFrameworkService @@ -0,0 +1 @@ +testFwSrv=org.apache.dubbo.common.extension.director.impl.TestFrameworkService diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleProvider b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleProvider new file mode 100644 index 0000000000..cfa3cd96b8 --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleProvider @@ -0,0 +1 @@ +testModuleProvider=org.apache.dubbo.common.extension.director.impl.TestModuleProvider diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleService b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleService new file mode 100644 index 0000000000..9d3ef3288b --- /dev/null +++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.director.FooModuleService @@ -0,0 +1 @@ +testMdSrv=org.apache.dubbo.common.extension.director.impl.TestModuleService diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java index bc0f0b228e..2a2f35f648 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/common/extension/ExtensionFactory.java @@ -16,10 +16,11 @@ */ package com.alibaba.dubbo.common.extension; +import org.apache.dubbo.common.extension.ExtensionScope; import org.apache.dubbo.common.extension.SPI; @Deprecated -@SPI +@SPI(scope = ExtensionScope.FRAMEWORK) public interface ExtensionFactory extends org.apache.dubbo.common.extension.ExtensionFactory { } diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java index f53e159f09..d8ae4e3776 100644 --- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java +++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/Invocation.java @@ -17,6 +17,8 @@ package com.alibaba.dubbo.rpc; +import org.apache.dubbo.rpc.model.ServiceModel; + import java.util.Collections; import java.util.Map; @@ -74,6 +76,16 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation { return null; } + @Override + default void setServiceModel(ServiceModel serviceModel) { + + } + + @Override + default ServiceModel getServiceModel() { + return null; + } + @Override default Object put(Object key, Object value) { return null; @@ -157,6 +169,16 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation { return new Invoker.CompatibleInvoker(delegate.getInvoker()); } + @Override + public void setServiceModel(ServiceModel serviceModel) { + delegate.setServiceModel(serviceModel); + } + + @Override + public ServiceModel getServiceModel() { + return delegate.getServiceModel(); + } + @Override public Object put(Object key, Object value) { return delegate.put(key, value); diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/ExtensionTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/ExtensionTest.java index 2b7a5c86be..b126d6a784 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/ExtensionTest.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/ExtensionTest.java @@ -27,13 +27,15 @@ public class ExtensionTest { @Test public void testExtensionFactory() { try { - ExtensionFactory factory = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getExtension("myfactory"); - Assertions.assertTrue(factory instanceof ExtensionFactory); - Assertions.assertTrue(factory instanceof com.alibaba.dubbo.common.extension.ExtensionFactory); - Assertions.assertTrue(factory instanceof MyExtensionFactory); + ExtensionInjector myfactory = ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getExtension("myfactory"); + Assertions.assertTrue(myfactory instanceof ExtensionInjector); + Assertions.assertTrue(myfactory instanceof ExtensionFactory); + Assertions.assertTrue(myfactory instanceof com.alibaba.dubbo.common.extension.ExtensionFactory); + Assertions.assertTrue(myfactory instanceof MyExtensionFactory); - ExtensionFactory spring = ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getExtension("spring"); - Assertions.assertTrue(spring instanceof ExtensionFactory); + ExtensionInjector spring = ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getExtension("spring"); + Assertions.assertTrue(spring instanceof ExtensionInjector); + Assertions.assertFalse(spring instanceof ExtensionFactory); Assertions.assertFalse(spring instanceof com.alibaba.dubbo.common.extension.ExtensionFactory); } catch (IllegalArgumentException expected) { fail(); diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java index f9602b44ae..d8bc822a0d 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java @@ -22,6 +22,18 @@ public class MyExtensionFactory implements ExtensionFactory { @Override public T getExtension(Class type, String name) { + if (type == InjectObject.class) { + return (T) new InjectObject(name); + } return null; } + + + public static class InjectObject { + private String name; + + public InjectObject(String name) { + this.name = name; + } + } } diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java index a2cb52e1a8..532f6bde44 100644 --- a/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java +++ b/dubbo-compatible/src/test/java/org/apache/dubbo/service/MockInvocation.java @@ -19,6 +19,7 @@ package org.apache.dubbo.service; import org.apache.dubbo.rpc.AttachmentsAdapter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.model.ServiceModel; import java.util.HashMap; import java.util.Map; @@ -131,6 +132,16 @@ public class MockInvocation implements Invocation { return null; } + @Override + public void setServiceModel(ServiceModel serviceModel) { + + } + + @Override + public ServiceModel getServiceModel() { + return null; + } + @Override public Map getAttributes() { return null; diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml index ad4220b2b7..b8ea09dc7b 100644 --- a/dubbo-config/dubbo-config-api/pom.xml +++ b/dubbo-config/dubbo-config-api/pom.xml @@ -50,6 +50,11 @@ dubbo-remoting-api ${project.parent.version} + + org.apache.dubbo + dubbo-rpc-api + ${project.parent.version} + org.apache.dubbo dubbo-rpc-injvm diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java index 6380a2437f..9e03a23d57 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java @@ -19,7 +19,6 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.lang.ShutdownHookCallbacks; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; -import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.concurrent.atomic.AtomicBoolean; @@ -57,8 +56,7 @@ public class DubboShutdownHook extends Thread { @Override public void run() { - String disableShutdownHookValue = (String) ApplicationModel.getEnvironment().getConfiguration() - .getProperty(ConfigKeys.DUBBO_LIFECYCLE_DISABLE_SHUTDOWN_HOOK, "false"); + String disableShutdownHookValue = System.getProperty(ConfigKeys.DUBBO_LIFECYCLE_DISABLE_SHUTDOWN_HOOK, "false"); if (Boolean.parseBoolean(disableShutdownHookValue)) { if (logger.isWarnEnabled()) { logger.warn("Shutdown hook is disabled, please shutdown dubbo services by qos manually"); 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 aa5bef5fd2..97e52f6659 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.AsyncMethodInfo; import org.apache.dubbo.rpc.model.ConsumerModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; @@ -104,13 +103,15 @@ public class ReferenceConfig extends ReferenceConfigBase { * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two * layers, and eventually will get a ProtocolFilterWrapper or ProtocolListenerWrapper */ - 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; + + private ConsumerModel consumerModel; /** * The interface proxy reference @@ -149,6 +150,14 @@ public class ReferenceConfig extends ReferenceConfigBase { 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. @@ -247,15 +256,12 @@ public class ReferenceConfig extends ReferenceConfigBase { Map referenceParameters = appendConfig(); - ServiceRepository repository = ApplicationModel.getServiceRepository(); + ServiceRepository repository = getApplicationModel().getApplicationServiceRepository(); ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass); - repository.registerConsumer( - serviceMetadata.getServiceKey(), - serviceDescriptor, - this, - null, - serviceMetadata, - createAsyncMethodInfo()); + consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor, this, + getScopeModel(), serviceMetadata, createAsyncMethodInfo()); + + repository.registerConsumer(consumerModel); serviceMetadata.getAttachments().putAll(referenceParameters); @@ -264,7 +270,6 @@ public class ReferenceConfig extends ReferenceConfigBase { serviceMetadata.setTarget(ref); serviceMetadata.addAttribute(PROXY_CLASS_REF, ref); - ConsumerModel consumerModel = repository.lookupReferredService(serviceMetadata.getServiceKey()); consumerModel.setProxyObject(ref); consumerModel.initMethodModels(); @@ -382,10 +387,12 @@ public class ReferenceConfig extends ReferenceConfigBase { URL consumerUrl = new ServiceConfigURL(CONSUMER_PROTOCOL, referenceParameters.get(REGISTER_IP_KEY), 0, referenceParameters.get(INTERFACE_KEY), referenceParameters); + consumerUrl = consumerUrl.setScopeModel(getScopeModel()); + consumerUrl = consumerUrl.setServiceModel(consumerModel); MetadataUtils.publishServiceDefinition(consumerUrl); // create service proxy - return (T) PROXY_FACTORY.getProxy(invoker, ProtocolUtils.isGeneric(generic)); + return (T) proxyFactory.getProxy(invoker, ProtocolUtils.isGeneric(generic)); } /** @@ -395,7 +402,9 @@ public class ReferenceConfig extends ReferenceConfigBase { */ private void createInvokerForLocal(Map referenceParameters) { URL url = new ServiceConfigURL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(referenceParameters); - invoker = REF_PROTOCOL.refer(interfaceClass, url); + url = url.setScopeModel(getScopeModel()); + url = url.setServiceModel(consumerModel); + invoker = protocolSPI.refer(interfaceClass, url); if (logger.isInfoEnabled()) { logger.info("Using in jvm service " + interfaceClass.getName()); } @@ -412,6 +421,8 @@ public class ReferenceConfig extends ReferenceConfigBase { if (StringUtils.isEmpty(url.getPath())) { url = url.setPath(interfaceName); } + url = url.setScopeModel(getScopeModel()); + url = url.setServiceModel(consumerModel); if (UrlUtils.isRegistry(url)) { urls.add(url.putAttribute(REFER_KEY, referenceParameters)); } else { @@ -435,6 +446,8 @@ public class ReferenceConfig extends ReferenceConfigBase { if (monitorUrl != null) { u = u.putAttribute(MONITOR_KEY, monitorUrl); } + u = u.setScopeModel(getScopeModel()); + u = u.setServiceModel(consumerModel); urls.add(u.putAttribute(REFER_KEY, referenceParameters)); } } @@ -453,14 +466,14 @@ public class ReferenceConfig extends ReferenceConfigBase { @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> 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 @@ -515,7 +528,7 @@ public class ReferenceConfig extends ReferenceConfigBase { completeCompoundConfigs(); // init some null configuration. - List configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class) + List configInitializers = this.getExtensionLoader(ConfigInitializer.class) .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null); configInitializers.forEach(e -> e.initReferConfig(this)); @@ -591,7 +604,7 @@ public class ReferenceConfig extends ReferenceConfigBase { } private void postProcessConfig() { - List configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class) + List 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 f527cb1ddb..c10850291c 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,14 @@ 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.ProviderModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.model.ServiceRepository; import org.apache.dubbo.rpc.service.GenericService; @@ -116,13 +117,15 @@ public class ServiceConfig extends ServiceConfigBase { */ 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; + + private ProviderModel providerModel; /** * Whether the provider has been exported @@ -144,6 +147,7 @@ public class ServiceConfig extends ServiceConfigBase { private final List> exporters = new ArrayList>(); private List serviceListeners = new ArrayList<>(); + private WritableMetadataService localMetadataService; public ServiceConfig() { } @@ -152,6 +156,13 @@ public class ServiceConfig extends ServiceConfigBase { 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 +208,7 @@ public class ServiceConfig extends ServiceConfigBase { this.bootstrap.service(this); // load ServiceListeners from extension - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(ServiceListener.class); + ExtensionLoader extensionLoader = this.getExtensionLoader(ServiceListener.class); this.serviceListeners.addAll(extensionLoader.getSupportedExtensionInstances()); } @@ -252,7 +263,7 @@ public class ServiceConfig extends ServiceConfigBase { List exportedURLs = this.getExportedUrls(); exportedURLs.forEach(url -> { if (url.getParameters().containsKey(SERVICE_NAME_MAPPING_KEY)) { - ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(); + ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(getScopeModel()); try { boolean succeeded = serviceNameMapping.map(url); if (succeeded) { @@ -274,8 +285,8 @@ public class ServiceConfig extends ServiceConfigBase { checkProtocol(); // init some null configuration. - List configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class) - .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null); + List configInitializers = this.getExtensionLoader(ConfigInitializer.class) + .getActivateExtension(URL.valueOf("configInitializer://", getScopeModel()), (String[]) null); configInitializers.forEach(e -> e.initServiceConfig(this)); // if protocol is not injvm checkRegistry @@ -360,15 +371,16 @@ public class ServiceConfig extends ServiceConfigBase { @SuppressWarnings({"unchecked", "rawtypes"}) private void doExportUrls() { - ServiceRepository repository = ApplicationModel.getServiceRepository(); + ServiceRepository repository = getApplicationModel().getApplicationServiceRepository(); ServiceDescriptor serviceDescriptor = repository.registerService(getInterfaceClass()); - repository.registerProvider( - getUniqueServiceName(), - ref, - serviceDescriptor, - this, - serviceMetadata - ); + providerModel = new ProviderModel(getUniqueServiceName(), + ref, + serviceDescriptor, + this, + getScopeModel(), + serviceMetadata); + + repository.registerProvider(providerModel); List registryURLs = ConfigValidationUtils.loadRegistries(this, true); @@ -382,7 +394,6 @@ public class ServiceConfig extends ServiceConfigBase { } } - private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List registryURLs) { Map map = buildAttributes(protocolConfig); @@ -535,14 +546,16 @@ public class ServiceConfig extends ServiceConfigBase { String host = findConfigedHosts(protocolConfig, registryURLs, params); Integer port = findConfigedPorts(protocolConfig, name, params); URL url = new ServiceConfigURL(name, null, null, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), params); + url.setScopeModel(getScopeModel()); // 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); } - + url = url.setScopeModel(getScopeModel()); + url = url.setServiceModel(providerModel); return url; } @@ -604,7 +617,7 @@ public class ServiceConfig extends ServiceConfigBase { } else { if (MetadataService.class.getName().equals(url.getServiceInterface())) { - MetadataUtils.saveMetadataURL(url); + localMetadataService.setMetadataServiceURL(url); } if (logger.isInfoEnabled()) { @@ -620,11 +633,11 @@ public class ServiceConfig extends ServiceConfigBase { @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); } @@ -754,7 +767,7 @@ public class ServiceConfig extends ServiceConfigBase { 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; } @@ -819,8 +832,8 @@ public class ServiceConfig extends ServiceConfigBase { } private void postProcessConfig() { - List configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class) - .getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null); + List configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class) + .getActivateExtension(URL.valueOf("configPostProcessor://", getScopeModel()), (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 19d924dc05..47b8029ecf 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,16 +17,19 @@ 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; import org.apache.dubbo.common.logger.LoggerFactory; +import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.CollectionUtils; @@ -57,7 +60,6 @@ import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder; import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder; import org.apache.dubbo.config.bootstrap.builders.ServiceBuilder; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter; import org.apache.dubbo.config.utils.ConfigValidationUtils; import org.apache.dubbo.config.utils.ReferenceConfigCache; import org.apache.dubbo.metadata.MetadataService; @@ -70,9 +72,12 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance; import org.apache.dubbo.registry.client.ServiceInstance; 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; 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; @@ -100,18 +105,16 @@ 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; import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_METADATA_PUBLISH_DELAY; import static org.apache.dubbo.metadata.MetadataConstants.METADATA_PUBLISH_DELAY_KEY; -import static org.apache.dubbo.metadata.WritableMetadataService.getDefaultExtension; +import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.calInstanceRevision; import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType; import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getServiceDiscoveries; import static org.apache.dubbo.remoting.Constants.CLIENT_KEY; @@ -158,7 +161,9 @@ public final class DubboBootstrap { private final ExecutorService executorService = newSingleThreadExecutor(); - private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + private ExecutorRepository executorRepository; + + private final ApplicationModel applicationModel; protected ScheduledFuture asyncMetadataFuture; @@ -192,12 +197,14 @@ public final class DubboBootstrap { protected final List> asyncReferringFutures = new ArrayList<>(); - protected volatile boolean asyncExportFinish = true; + protected boolean asyncExportFinish = true; protected volatile boolean asyncReferFinish = true; protected static boolean ignoreConfigState; + private Module currentModule; + /** * See {@link ApplicationModel} and {@link ExtensionLoader} for why DubboBootstrap is designed to be singleton. */ @@ -205,13 +212,21 @@ public final class DubboBootstrap { if (instance == null) { synchronized (DubboBootstrap.class) { if (instance == null) { - instance = new DubboBootstrap(); + instance = new DubboBootstrap(ApplicationModel.defaultModel()); } } } return instance; } + public static DubboBootstrap newInstance() { + return new DubboBootstrap(new FrameworkModel()); + } + + public static DubboBootstrap newInstance(FrameworkModel frameworkModel) { + return new DubboBootstrap(frameworkModel); + } + /** * Try reset dubbo status for new instance. * @@ -238,8 +253,6 @@ public final class DubboBootstrap { } MetadataReportInstance.reset(); AbstractRegistryFactory.reset(); - ExtensionLoader.destroyAll(); - //ExtensionLoader.resetExtensionLoader(GovernanceRuleRepository.class); } else { instance = null; } @@ -248,18 +261,50 @@ public final class DubboBootstrap { ShutdownHookCallbacks.INSTANCE.clear(); } - private DubboBootstrap() { - configManager = ApplicationModel.getConfigManager(); - environment = ApplicationModel.getEnvironment(); + private DubboBootstrap(FrameworkModel frameworkModel) { + this(new ApplicationModel(frameworkModel)); + } + private DubboBootstrap(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + configManager = applicationModel.getApplicationConfigManager(); + environment = applicationModel.getApplicationEnvironment(); + + executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); DubboShutdownHook.getDubboShutdownHook().register(); ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy); + cache = ReferenceConfigCache.newCache(); + + initInternalBeans(); + } + + /** + * TODO init beans module-self + */ + private void initInternalBeans() { + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + beanFactory.registerBean(this); + beanFactory.registerBean(MetadataReportInstance.class); + beanFactory.registerBean(RemoteMetadataServiceImpl.class); + beanFactory.registerBean(FrameworkStatusReportService.class); + } + + public ApplicationModel getApplicationModel() { + return applicationModel; } public ConfigManager getConfigManager() { return configManager; } + public ExtensionDirector getExtensionDirector() { + return applicationModel.getExtensionDirector(); + } + + public ExtensionLoader getExtensionLoader(Class type) { + return applicationModel.getExtensionLoader(type); + } + public void unRegisterShutdownHook() { DubboShutdownHook.getDubboShutdownHook().unregister(); } @@ -325,6 +370,7 @@ public final class DubboBootstrap { * @return current {@link DubboBootstrap} instance */ public DubboBootstrap application(ApplicationConfig applicationConfig) { + applicationConfig.setScopeModel(applicationModel); configManager.setApplication(applicationConfig); return this; } @@ -362,6 +408,7 @@ public final class DubboBootstrap { * @return current {@link DubboBootstrap} instance */ public DubboBootstrap registry(RegistryConfig registryConfig) { + registryConfig.setScopeModel(applicationModel); configManager.addRegistry(registryConfig); return this; } @@ -400,70 +447,71 @@ public final 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 DubboBootstrap service(Consumer> consumerBuilder) { - return service(DEFAULT_SERVICE_ID, consumerBuilder); + getCurrentModule().service(consumerBuilder); + return this; } public DubboBootstrap service(String id, Consumer> 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 serviceConfigs) { - if (CollectionUtils.isEmpty(serviceConfigs)) { - return this; - } - serviceConfigs.forEach(configManager::addService); + getCurrentModule().services(serviceConfigs); return this; } // {@link Reference} correlative methods public DubboBootstrap reference(Consumer> consumerBuilder) { - return reference(DEFAULT_REFERENCE_ID, consumerBuilder); + getCurrentModule().reference(consumerBuilder); + return this; } public DubboBootstrap reference(String id, Consumer> 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 referenceConfigs) { - if (CollectionUtils.isEmpty(referenceConfigs)) { - return this; - } - - referenceConfigs.forEach(configManager::addReference); + getCurrentModule().references(referenceConfigs); return this; } // {@link ProviderConfig} correlative methods public DubboBootstrap provider(Consumer builderConsumer) { - return provider(DEFAULT_PROVIDER_ID, builderConsumer); + getCurrentModule().provider(builderConsumer); + return this; } public DubboBootstrap provider(String id, Consumer builderConsumer) { - ProviderBuilder builder = createProviderBuilder(id); - builderConsumer.accept(builder); - return provider(builder.build()); + getCurrentModule().provider(id, builderConsumer); + return this; } public DubboBootstrap provider(ProviderConfig providerConfig) { @@ -471,80 +519,75 @@ public final class DubboBootstrap { } public DubboBootstrap providers(List providerConfigs) { - if (CollectionUtils.isEmpty(providerConfigs)) { - return this; - } - - providerConfigs.forEach(configManager::addProvider); + getCurrentModule().providers(providerConfigs); return this; } // {@link ConsumerConfig} correlative methods public DubboBootstrap consumer(Consumer builderConsumer) { - return consumer(DEFAULT_CONSUMER_ID, builderConsumer); - } - - public DubboBootstrap consumer(String id, Consumer builderConsumer) { - ConsumerBuilder builder = createConsumerBuilder(id); - builderConsumer.accept(builder); - return consumer(builder.build()); - } - - public DubboBootstrap consumer(ConsumerConfig consumerConfig) { - return consumers(singletonList(consumerConfig)); - } - - public DubboBootstrap consumers(List consumerConfigs) { - if (CollectionUtils.isEmpty(consumerConfigs)) { - return this; - } - - consumerConfigs.forEach(configManager::addConsumer); + getCurrentModule().consumer(builderConsumer); return this; } + public DubboBootstrap consumer(String id, Consumer builderConsumer) { + getCurrentModule().consumer(id, builderConsumer); + return this; + } + + public DubboBootstrap consumer(ConsumerConfig consumerConfig) { + getCurrentModule().consumer(consumerConfig); + return this; + } + + public DubboBootstrap consumers(List consumerConfigs) { + 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 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; } - public DubboBootstrap cache(ReferenceConfigCache cache) { - this.cache = cache; - return this; - } - public ReferenceConfigCache getCache() { - if (cache == null) { - cache = ReferenceConfigCache.getCache(); - } return cache; } @@ -556,7 +599,7 @@ public final class DubboBootstrap { return; } - ApplicationModel.initFrameworkExts(); + getApplicationModel().initFrameworkExts(); startConfigCenter(); @@ -619,7 +662,7 @@ public final class DubboBootstrap { private void checkDefaultAndValidateConfigs(Class configType) { try { if (shouldAddDefaultConfig(configType)) { - T config = configType.newInstance(); + T config = createConfig(configType); config.refresh(); if (!isNeedValidation(config) || config.isValid()) { configManager.addConfig(config); @@ -721,6 +764,7 @@ public final class DubboBootstrap { Collection configCenters = configManager.getConfigCenters(); if (CollectionUtils.isEmpty(configCenters)) { ConfigCenterConfig configCenterConfig = new ConfigCenterConfig(); + configCenterConfig.setScopeModel(applicationModel); configCenterConfig.refresh(); ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig); if (configCenterConfig.isValid()) { @@ -766,13 +810,14 @@ public final 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); } } @@ -819,10 +864,11 @@ public final class DubboBootstrap { private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) { String protocol = registryConfig.getProtocol(); Integer port = registryConfig.getPort(); - URL url = URL.valueOf(registryConfig.getAddress()); + URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel()); 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<>()); } @@ -928,10 +974,11 @@ public final class DubboBootstrap { private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) { String protocol = registryConfig.getProtocol(); - URL url = URL.valueOf(registryConfig.getAddress()); + URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel()); 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<>()); } @@ -957,7 +1004,7 @@ public final class DubboBootstrap { // since 2.7.8 // Issue : https://github.com/apache/dubbo/issues/6476 StringBuilder metadataAddressBuilder = new StringBuilder(); - URL url = URL.valueOf(address); + URL url = URL.valueOf(address, registryConfig.getScopeModel()); String protocolFromAddress = url.getProtocol(); if (isEmpty(protocolFromAddress)) { // If the protocol from address is missing, is like : @@ -1012,7 +1059,7 @@ public final 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()); @@ -1044,12 +1091,11 @@ public final class DubboBootstrap { // If none config of the type, try load single config if (configManager.getConfigs(cls).isEmpty()) { // load single config - Environment env = ApplicationModel.getEnvironment(); - List> configurationMaps = env.getConfigurationMaps(); + List> configurationMaps = environment.getConfigurationMaps(); 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()); @@ -1061,6 +1107,17 @@ public final class DubboBootstrap { } + private T createConfig(Class 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. *

@@ -1080,7 +1137,6 @@ public final class DubboBootstrap {
      */
     private Set getConfigIds(Class clazz) {
         String prefix = CommonConstants.DUBBO + "." + AbstractConfig.getPluralTagName(clazz) + ".";
-        Environment environment = ApplicationModel.getEnvironment();
         return ConfigurationUtils.getSubIds(environment.getConfigurationMaps(), prefix);
     }
 
@@ -1089,8 +1145,12 @@ public final class DubboBootstrap {
      */
     private void initMetadataService() {
 //        startMetadataCenter();
-        this.metadataService = getDefaultExtension();
-        this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
+        this.metadataService = getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
+        // support injection by super type MetadataService
+        applicationModel.getBeanFactory().registerBean(this.metadataService);
+
+        //this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
+        this.metadataServiceExporter = getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
     }
 
     /**
@@ -1376,7 +1436,8 @@ public final 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);
     }
 
@@ -1389,9 +1450,9 @@ public final class DubboBootstrap {
 
     private void unexportMetadataService() {
         if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
-            try{
+            try {
                 metadataServiceExporter.unexport();
-            }catch (Exception ignored){
+            } catch (Exception ignored) {
                 // ignored
             }
         }
@@ -1433,10 +1494,10 @@ public final class DubboBootstrap {
 
     private void unexportServices() {
         exportedServices.forEach(sc -> {
-            try{
+            try {
                 configManager.removeConfig(sc);
                 sc.unexport();
-            }catch (Exception ignored){
+            } catch (Exception ignored) {
                 // ignored
             }
         });
@@ -1451,10 +1512,6 @@ public final class DubboBootstrap {
     }
 
     private void referServices() {
-        if (cache == null) {
-            cache = ReferenceConfigCache.getCache();
-        }
-
         configManager.getReferences().forEach(rc -> {
             try {
                 // TODO, compatible with  ReferenceConfig.refer()
@@ -1488,11 +1545,7 @@ public final class DubboBootstrap {
     }
 
     private void unreferServices() {
-        try{
-            if (cache == null) {
-                cache = ReferenceConfigCache.getCache();
-            }
-
+        try {
             asyncReferringFutures.forEach(future -> {
                 if (!future.isDone()) {
                     future.cancel(true);
@@ -1500,7 +1553,7 @@ public final class DubboBootstrap {
             });
             asyncReferringFutures.clear();
             cache.destroyAll();
-        }catch (Exception ignored){
+        } catch (Exception ignored) {
         }
     }
 
@@ -1519,10 +1572,10 @@ public final class DubboBootstrap {
             registered = false;
             logger.error("Register instance error", e);
         }
-        if(registered){
+        if (registered) {
             // scheduled task for updating Metadata and ServiceInstance
             asyncMetadataFuture = executorRepository.nextScheduledExecutor().scheduleAtFixedRate(() -> {
-                InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension();
+                InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(applicationModel);
                 localMetadataService.blockUntilUpdated();
                 try {
                     ServiceInstanceMetadataUtils.refreshMetadataAndInstance(serviceInstance);
@@ -1531,16 +1584,45 @@ public final class DubboBootstrap {
                 } finally {
                     localMetadataService.releaseBlock();
                 }
-            }, 0, ConfigurationUtils.get(METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY), TimeUnit.MILLISECONDS);
+            }, 0, ConfigurationUtils.get(applicationModel, METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY), TimeUnit.MILLISECONDS);
         }
     }
 
+    private void doRegisterServiceInstance(ServiceInstance serviceInstance) {
+        // register instance only when at least one service is exported.
+        if (serviceInstance.getPort() > 0) {
+            publishMetadataToRemote(serviceInstance);
+            logger.info("Start registering instance address to registry.");
+            getServiceDiscoveries().forEach(serviceDiscovery ->
+            {
+                ServiceInstance serviceInstanceForRegistry = new DefaultServiceInstance((DefaultServiceInstance) serviceInstance);
+                calInstanceRevision(serviceDiscovery, serviceInstanceForRegistry);
+                if (logger.isDebugEnabled()) {
+                    logger.info("Start registering instance address to registry" + serviceDiscovery.getUrl() + ", instance " + serviceInstanceForRegistry);
+                }
+                // register metadata
+                serviceDiscovery.register(serviceInstanceForRegistry);
+            });
+        }
+    }
+
+    private void publishMetadataToRemote(ServiceInstance serviceInstance) {
+//        InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService)WritableMetadataService.getDefaultExtension();
+//        localMetadataService.blockUntilUpdated();
+        if (logger.isInfoEnabled()) {
+            logger.info("Start publishing metadata to remote center, this only makes sense for applications enabled remote metadata center.");
+        }
+        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
                 }
             });
@@ -1548,7 +1630,7 @@ public final class DubboBootstrap {
     }
 
     private ServiceInstance createServiceInstance(String serviceName) {
-        this.serviceInstance = new DefaultServiceInstance(serviceName);
+        this.serviceInstance = new DefaultServiceInstance(serviceName, applicationModel);
         setMetadataStorageType(serviceInstance, getMetadataType());
         ServiceInstanceMetadataUtils.customizeInstance(this.serviceInstance);
         return this.serviceInstance;
@@ -1587,10 +1669,10 @@ public final 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();
@@ -1621,7 +1703,7 @@ public final class DubboBootstrap {
     }
 
     private void destroyExecutorRepository() {
-        ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
+        getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
     }
 
     private void destroyRegistries() {
@@ -1632,7 +1714,7 @@ public final class DubboBootstrap {
      * Destroy all the protocols.
      */
     private void destroyProtocols() {
-        ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Protocol.class);
+        ExtensionLoader loader = getExtensionLoader(Protocol.class);
         for (String protocolName : loader.getLoadedExtensions()) {
             try {
                 Protocol protocol = loader.getLoadedExtension(protocolName);
@@ -1647,10 +1729,10 @@ public final 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()) {
@@ -1661,13 +1743,12 @@ public final 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() {
@@ -1700,11 +1781,11 @@ public final 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);
             }
         }
     }
@@ -1730,4 +1811,134 @@ public final 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  Module service(Consumer> consumerBuilder) {
+            return service(DEFAULT_SERVICE_ID, consumerBuilder);
+        }
+
+        public  Module service(String id, Consumer> 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 serviceConfigs) {
+            if (CollectionUtils.isEmpty(serviceConfigs)) {
+                return this;
+            }
+            serviceConfigs.forEach(configManager::addService);
+            return this;
+        }
+
+        // {@link Reference} correlative methods
+        public  Module reference(Consumer> consumerBuilder) {
+            return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+        }
+
+        public  Module reference(String id, Consumer> 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 referenceConfigs) {
+            if (CollectionUtils.isEmpty(referenceConfigs)) {
+                return this;
+            }
+
+            referenceConfigs.forEach(configManager::addReference);
+            return this;
+        }
+
+        // {@link ProviderConfig} correlative methods
+        public Module provider(Consumer builderConsumer) {
+            return provider(DEFAULT_PROVIDER_ID, builderConsumer);
+        }
+
+        public Module provider(String id, Consumer 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 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 builderConsumer) {
+            return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+        }
+
+        public Module consumer(String id, Consumer 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 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/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
index f7d1db3168..8dbf9102be 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
@@ -26,10 +26,12 @@ import org.apache.dubbo.config.MethodConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.Collections;
 import java.util.List;
@@ -52,15 +54,24 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
  * @see ConfigManager
  * @since 2.7.5
  */
-public class ConfigurableMetadataServiceExporter implements MetadataServiceExporter {
+public class ConfigurableMetadataServiceExporter implements MetadataServiceExporter, ScopeModelAware {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
-    private final MetadataService metadataService;
+    private MetadataService metadataService;
 
     private volatile ServiceConfig serviceConfig;
+    private ApplicationModel applicationModel;
 
-    public ConfigurableMetadataServiceExporter(MetadataService metadataService) {
+    public ConfigurableMetadataServiceExporter() {
+    }
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
+
+    public void setMetadataService(MetadataService metadataService) {
         this.metadataService = metadataService;
     }
 
@@ -69,14 +80,17 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
 
         if (!isExported()) {
 
+            ApplicationConfig applicationConfig = getApplicationConfig();
             ServiceConfig serviceConfig = new ServiceConfig<>();
-            serviceConfig.setApplication(getApplicationConfig());
+            serviceConfig.setScopeModel(applicationModel.getDefaultModule());
+            serviceConfig.setBootstrap(applicationModel.getBeanFactory().getBean(DubboBootstrap.class));
+            serviceConfig.setApplication(applicationConfig);
             serviceConfig.setRegistry(new RegistryConfig("N/A"));
             serviceConfig.setProtocol(generateMetadataProtocol());
             serviceConfig.setInterface(MetadataService.class);
             serviceConfig.setDelay(0);
             serviceConfig.setRef(metadataService);
-            serviceConfig.setGroup(getApplicationConfig().getName());
+            serviceConfig.setGroup(applicationConfig.getName());
             serviceConfig.setVersion(metadataService.version());
             serviceConfig.setMethods(generateMethodConfig());
 
@@ -138,7 +152,7 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
     }
 
     private ApplicationConfig getApplicationConfig() {
-        return ApplicationModel.getConfigManager().getApplication().get();
+        return applicationModel.getApplicationConfigManager().getApplication().get();
     }
 
     private ProtocolConfig generateMetadataProtocol() {
@@ -149,7 +163,7 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
             if (logger.isInfoEnabled()) {
                 logger.info("Metadata Service Port hasn't been set will use default protocol defined in protocols.");
             }
-            List defaultProtocols = ApplicationModel.getConfigManager().getDefaultProtocols();
+            List defaultProtocols = applicationModel.getApplicationConfigManager().getDefaultProtocols();
 
             ProtocolConfig dubboProtocol = findDubboProtocol(defaultProtocols);
             if (dubboProtocol != null) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
index 8693828bb2..07d8ffaeb3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizer.java
@@ -40,13 +40,14 @@ public class ServiceInstanceHostPortCustomizer implements ServiceInstanceCustomi
             return;
         }
 
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(serviceInstance.getApplicationModel());
 
         String host = null;
         int port = -1;
         Set urls = writableMetadataService.getExportedServiceURLs();
         if (CollectionUtils.isNotEmpty(urls)) {
-            String preferredProtocol = ApplicationModel.getApplicationConfig().getProtocol();
+            ApplicationModel applicationModel = serviceInstance.getApplicationModel();
+            String preferredProtocol = applicationModel.getCurrentConfig().getProtocol();
             if (preferredProtocol != null) {
                 for (URL exportedURL : urls) {
                     if (preferredProtocol.equals(exportedURL.getProtocol())) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
index 47ccae929e..fa5476e1e3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
@@ -24,7 +24,7 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.serialize.Serialization;
 import org.apache.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.common.status.reporter.FrameworkStatusReporter;
+import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
 import org.apache.dubbo.common.threadpool.ThreadPool;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
@@ -62,6 +62,7 @@ import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.cluster.LoadBalance;
 import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.support.MockInvoker;
 
 import java.net.InetAddress;
@@ -108,7 +109,6 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_
 import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
 import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
-import static org.apache.dubbo.common.status.reporter.FrameworkStatusReporter.createRegistrationReport;
 import static org.apache.dubbo.config.Constants.ARCHITECTURE;
 import static org.apache.dubbo.config.Constants.CONTEXTPATH_KEY;
 import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
@@ -213,6 +213,7 @@ public class ConfigValidationUtils {
                         url = URLBuilder.from(url)
                             .addParameter(REGISTRY_KEY, url.getProtocol())
                             .setProtocol(extractRegistryType(url))
+                            .setScopeModel(interfaceConfig.getScopeModel())
                             .build();
                         if ((provider && url.getParameter(REGISTER_KEY, true))
                             || (!provider && url.getParameter(SUBSCRIBE_KEY, true))) {
@@ -222,17 +223,17 @@ public class ConfigValidationUtils {
                 }
             }
         }
-        return genCompatibleRegistries(registryList, provider);
+        return genCompatibleRegistries(interfaceConfig.getApplicationModel(), registryList, provider);
     }
 
-    private static List genCompatibleRegistries(List registryList, boolean provider) {
+    private static List genCompatibleRegistries(ApplicationModel applicationModel, List registryList, boolean provider) {
         List result = new ArrayList<>(registryList.size());
         registryList.forEach(registryURL -> {
             if (provider) {
                 // for registries enabled service discovery, automatically register interface compatible addresses.
                 String registerMode;
                 if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) {
-                    registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_INSTANCE));
+                    registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(applicationModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_INSTANCE));
                     if (!isValidRegisterMode(registerMode)) {
                         registerMode = DEFAULT_REGISTER_MODE_INSTANCE;
                     }
@@ -246,7 +247,7 @@ public class ConfigValidationUtils {
                         result.add(interfaceCompatibleRegistryURL);
                     }
                 } else {
-                    registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_ALL));
+                    registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(applicationModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_ALL));
                     if (!isValidRegisterMode(registerMode)) {
                         registerMode = DEFAULT_REGISTER_MODE_INTERFACE;
                     }
@@ -264,7 +265,8 @@ public class ConfigValidationUtils {
                     }
                 }
 
-                FrameworkStatusReporter.reportRegistrationStatus(createRegistrationReport(registerMode));
+                FrameworkStatusReportService reportService = applicationModel.getBeanFactory().getBean(FrameworkStatusReportService.class);
+                reportService.reportRegistrationStatus(reportService.createRegistrationReport(registerMode));
             } else {
                 result.add(registryURL);
             }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
index 1f6a7733e2..f95e00f8b6 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.config.utils;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.ReferenceConfigBase;
-import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 import org.apache.dubbo.rpc.service.Destroyable;
 
 import java.util.ArrayList;
@@ -28,6 +28,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * A simple util class for cache {@link ReferenceConfigBase}.
@@ -65,6 +66,8 @@ public class ReferenceConfigCache {
         return ret.toString();
     };
 
+    private static final AtomicInteger nameIndex = new AtomicInteger();
+
     static final ConcurrentMap CACHE_HOLDER = new ConcurrentHashMap();
     private final String name;
     private final KeyGenerator generator;
@@ -86,6 +89,10 @@ public class ReferenceConfigCache {
         return getCache(DEFAULT_NAME);
     }
 
+    public static ReferenceConfigCache newCache() {
+        return getCache(DEFAULT_NAME + "#" + nameIndex.incrementAndGet());
+    }
+
     /**
      * Get the cache use specified name and {@link KeyGenerator}.
      * Create cache if not existed yet.
@@ -173,7 +180,7 @@ public class ReferenceConfigCache {
             return;
         }
 
-        ApplicationModel.getConfigManager().removeConfig(rc);
+        ScopeModelUtil.getApplicationModel(rc.getScopeModel()).getApplicationConfigManager().removeConfig(rc);
         rc.destroy();
 
         Map proxiesOftype = proxies.get(type);
@@ -215,7 +222,7 @@ public class ReferenceConfigCache {
 
         referredReferences.forEach((_k, referenceConfig) -> {
             referenceConfig.destroy();
-            ApplicationModel.getConfigManager().removeConfig(referenceConfig);
+            ScopeModelUtil.getApplicationModel(referenceConfig.getScopeModel()).getApplicationConfigManager().removeConfig(referenceConfig);
         });
 
         proxies.forEach((_type, proxiesOfType) -> {
@@ -240,7 +247,7 @@ public class ReferenceConfigCache {
     @Override
     public String toString() {
         return "ReferenceConfigCache(name: " + name
-                + ")";
+            + ")";
     }
 
     public interface KeyGenerator {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index 97184522d7..8278220628 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -331,8 +331,8 @@ public class AbstractConfigTest {
             external.put("dubbo.override.key", "external");
             // @Parameter(key="key2", useKeyAsProperty=true)
             external.put("dubbo.override.key2", "external");
-            ApplicationModel.getEnvironment().initialize();
-            ApplicationModel.getEnvironment().setExternalConfigMap(external);
+            ApplicationModel.defaultModel().getApplicationEnvironment().initialize();
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(external);
 
             SysProps.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
             SysProps.setProperty("dubbo.override.protocol", "system");
@@ -350,7 +350,7 @@ public class AbstractConfigTest {
             Assertions.assertEquals("system", overrideConfig.getKey2());
         } finally {
             SysProps.clear();
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
@@ -375,14 +375,14 @@ public class AbstractConfigTest {
             Assertions.assertEquals("system", overrideConfig.getKey());
         } finally {
             SysProps.clear();
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
     @Test
     public void testRefreshProperties() throws Exception {
         try {
-            ApplicationModel.getEnvironment().setExternalConfigMap(new HashMap<>());
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(new HashMap<>());
             OverrideConfig overrideConfig = new OverrideConfig();
             overrideConfig.setAddress("override-config://127.0.0.1:2181");
             overrideConfig.setProtocol("override-config");
@@ -399,7 +399,7 @@ public class AbstractConfigTest {
             Assertions.assertEquals("override-config://", overrideConfig.getEscape());
             //Assertions.assertEquals("properties", overrideConfig.getUseKeyAsProperty());
         } finally {
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
             ConfigUtils.setProperties(null);
         }
     }
@@ -423,8 +423,8 @@ public class AbstractConfigTest {
             external.put("dubbo.override.key", "external");
             // @Parameter(key="key2", useKeyAsProperty=true)
             external.put("dubbo.override.key2", "external");
-            ApplicationModel.getEnvironment().initialize();
-            ApplicationModel.getEnvironment().setExternalConfigMap(external);
+            ApplicationModel.defaultModel().getApplicationEnvironment().initialize();
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(external);
 
             overrideConfig.refresh();
 
@@ -435,7 +435,7 @@ public class AbstractConfigTest {
             Assertions.assertEquals("external", overrideConfig.getKey());
             Assertions.assertEquals("external", overrideConfig.getKey2());
         } finally {
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
@@ -455,8 +455,8 @@ public class AbstractConfigTest {
             external.put("dubbo.overrides.override-id.key2", "external");
             external.put("dubbo.override.address", "external://127.0.0.1:2181");
             external.put("dubbo.override.exclude", "external");
-            ApplicationModel.getEnvironment().initialize();
-            ApplicationModel.getEnvironment().setExternalConfigMap(external);
+            ApplicationModel.defaultModel().getApplicationEnvironment().initialize();
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(external);
 
             // refresh config
             overrideConfig.refresh();
@@ -467,7 +467,7 @@ public class AbstractConfigTest {
             Assertions.assertEquals("external", overrideConfig.getKey());
             Assertions.assertEquals("external", overrideConfig.getKey2());
         } finally {
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
@@ -483,8 +483,8 @@ public class AbstractConfigTest {
 
             Map external = new HashMap<>();
             external.put("dubbo.override.parameters", "[{key3:value3},{key4:value4},{key2:value5}]");
-            ApplicationModel.getEnvironment().initialize();
-            ApplicationModel.getEnvironment().setExternalConfigMap(external);
+            ApplicationModel.defaultModel().getApplicationEnvironment().initialize();
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(external);
 
             // refresh config
             overrideConfig.refresh();
@@ -501,7 +501,7 @@ public class AbstractConfigTest {
             Assertions.assertEquals("value4", overrideConfig.getParameters().get("key4"));
         } finally {
             SysProps.clear();
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
@@ -514,7 +514,7 @@ public class AbstractConfigTest {
             assertEquals("value00", overrideConfig.getParameters().get("key00"));
         } finally {
             SysProps.clear();
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
         }
     }
 
@@ -537,14 +537,14 @@ public class AbstractConfigTest {
                 e.printStackTrace();
             }
 
-            ApplicationModel.getEnvironment().setExternalConfigMap(external);
+            ApplicationModel.defaultModel().getApplicationEnvironment().setExternalConfigMap(external);
 
             overrideConfig.refresh();
 
             Assertions.assertEquals("value-from-config", overrideConfig.getNotConflictKey());
             Assertions.assertEquals("value-from-env", overrideConfig.getNotConflictKey2());
         } finally {
-            ApplicationModel.getEnvironment().destroy();
+            ApplicationModel.defaultModel().getApplicationEnvironment().destroy();
 
         }
     }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
index 014d7642a4..427a265b22 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -95,7 +96,7 @@ public class ConfigCenterConfigTest {
                 // ignore
             }
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(zkAddr, configCenter.getAddress());
@@ -123,7 +124,7 @@ public class ConfigCenterConfigTest {
                     .configCenter(configCenter)
                     .start();
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(zkAddr, configCenter.getAddress());
@@ -150,7 +151,7 @@ public class ConfigCenterConfigTest {
                     .configCenter(configCenter)
                     .initialize();
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(1234, configCenter.getTimeout());
@@ -179,7 +180,7 @@ public class ConfigCenterConfigTest {
                     .configCenter(configCenter)
                     .initialize();
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(3000L, configCenter.getTimeout());
@@ -207,7 +208,7 @@ public class ConfigCenterConfigTest {
                     .configCenter(configCenter)
                     .start();
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(1234, configCenter.getTimeout());
@@ -237,7 +238,7 @@ public class ConfigCenterConfigTest {
                     .configCenter(configCenter)
                     .start();
 
-            Collection configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection configCenters = ApplicationModel.defaultModel().getApplicationConfigManager().getConfigCenters();
             Assertions.assertEquals(1, configCenters.size());
             Assertions.assertEquals(configCenter, configCenters.iterator().next());
             Assertions.assertEquals(3000L, configCenter.getTimeout());
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
index a4ea9aff84..313fa71003 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -118,7 +119,7 @@ public class ConsumerConfigTest {
                     .consumer(consumerConfig)
                     .initialize();
 
-            Collection consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
             Assertions.assertEquals(1, consumers.size());
             Assertions.assertEquals(consumerConfig, consumers.iterator().next());
             Assertions.assertEquals(false, consumerConfig.isCheck());
@@ -148,7 +149,7 @@ public class ConsumerConfigTest {
                     .consumer(consumerConfig)
                     .initialize();
 
-            Collection consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
             Assertions.assertEquals(1, consumers.size());
             Assertions.assertEquals(consumerConfig, consumers.iterator().next());
             Assertions.assertEquals(false, consumerConfig.isCheck());
@@ -181,7 +182,7 @@ public class ConsumerConfigTest {
                     .consumer(consumerConfig)
                     .initialize();
 
-            Collection consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
             Assertions.assertEquals(1, consumers.size());
             Assertions.assertEquals(consumerConfig, consumers.iterator().next());
             Assertions.assertEquals(true, consumerConfig.isCheck());
@@ -211,7 +212,7 @@ public class ConsumerConfigTest {
                     .consumer(consumerConfig)
                     .initialize();
 
-            Collection consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
             Assertions.assertEquals(1, consumers.size());
             Assertions.assertEquals(consumerConfig, consumers.iterator().next());
             Assertions.assertEquals(false, consumerConfig.isCheck());
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index 9f13ce34e5..fa6441058a 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -18,9 +18,6 @@ package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.config.CompositeConfiguration;
-import org.apache.dubbo.common.config.Configuration;
-import org.apache.dubbo.common.config.Environment;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.ConfigUtils;
 import org.apache.dubbo.common.utils.NetUtils;
@@ -30,87 +27,77 @@ import org.apache.dubbo.config.annotation.Method;
 import org.apache.dubbo.config.annotation.Reference;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
-import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
-
-import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.registry.client.migration.MigrationInvoker;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.listener.ListenerInvokerWrapper;
 import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.curator.test.TestingServer;
-import org.apache.dubbo.rpc.model.ConsumerModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
-import org.apache.dubbo.rpc.model.ServiceRepository;
 import org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker;
 import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
+
+import org.apache.curator.test.TestingServer;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
 import java.io.IOException;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.HashMap;
-import java.util.Collections;
-import java.util.Optional;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 
-
-import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.BROADCAST_CLUSTER;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METRICS_PROTOCOL;
-import static org.apache.dubbo.common.constants.CommonConstants.METRICS_PORT;
-import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
-import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.STARTUP_PROBE;
-import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REFER_THREAD_NUM_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REFER_BACKGROUND_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REFER_ASYNC_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METRICS_PORT;
+import static org.apache.dubbo.common.constants.CommonConstants.METRICS_PROTOCOL;
+import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REFER_ASYNC_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REFER_BACKGROUND_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REFER_THREAD_NUM_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
+import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.STARTUP_PROBE;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCESSOR_KEY;
+import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
 import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
 import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
 import static org.apache.dubbo.common.constants.QosConstants.QOS_PORT;
-import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PUBLISH_INSTANCE_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PUBLISH_INTERFACE_KEY;
-import static org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN;
 import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
-import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
-import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
 import static org.apache.dubbo.rpc.Constants.DEFAULT_STUB_EVENT;
 import static org.apache.dubbo.rpc.Constants.LOCAL_KEY;
+import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
 import static org.apache.dubbo.rpc.Constants.SCOPE_KEY;
 import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
 
 public class ReferenceConfigTest {
     private TestingServer zkServer;
@@ -125,7 +112,10 @@ public class ReferenceConfigTest {
         this.zkServer.start();
         this.zkUrl = "zookeeper://localhost:" + zkServerPort;
         this.registryUrl = "registry://localhost:" + zkServerPort+"?registry=zookeeper";
-        ApplicationModel.getConfigManager();
+
+        // preload
+        ReferenceConfig preloadReferenceConfig = new ReferenceConfig();
+        ApplicationModel.defaultModel().getApplicationConfigManager();
         DubboBootstrap.getInstance();
     }
 
@@ -143,24 +133,6 @@ public class ReferenceConfigTest {
     @Test
     public void testAppendConfig() {
 
-        ReferenceConfig referenceConfig = new ReferenceConfig<>();
-        referenceConfig.setClient("netty");
-        referenceConfig.setGeneric(Boolean.FALSE.toString());
-        referenceConfig.setProtocol("dubbo");
-        referenceConfig.setInit(true);
-        referenceConfig.setLazy(false);
-        referenceConfig.setInjvm(false);
-        referenceConfig.setReconnect("reconnect");
-        referenceConfig.setSticky(false);
-        referenceConfig.setStub(DEFAULT_STUB_EVENT);
-        referenceConfig.setRouter("default");
-        referenceConfig.setReferAsync(true);
-
-        DubboBootstrap.getInstance()
-            .application("application1")
-            .initialize();
-        referenceConfig.setBootstrap(DubboBootstrap.getInstance());
-
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("application1");
         applicationConfig.setVersion("v1");
@@ -192,6 +164,19 @@ public class ReferenceConfigTest {
         applicationConfig.setReadinessProbe("readinessProb");
         applicationConfig.setStartupProbe("startupProbe");
 
+        ReferenceConfig referenceConfig = new ReferenceConfig<>();
+        referenceConfig.setClient("netty");
+        referenceConfig.setGeneric(Boolean.FALSE.toString());
+        referenceConfig.setProtocol("dubbo");
+        referenceConfig.setInit(true);
+        referenceConfig.setLazy(false);
+        referenceConfig.setInjvm(false);
+        referenceConfig.setReconnect("reconnect");
+        referenceConfig.setSticky(false);
+        referenceConfig.setStub(DEFAULT_STUB_EVENT);
+        referenceConfig.setRouter("default");
+        referenceConfig.setReferAsync(true);
+
         MonitorConfig monitorConfig = new MonitorConfig();
         applicationConfig.setMonitor(monitorConfig);
 
@@ -219,7 +204,7 @@ public class ReferenceConfigTest {
         referenceConfig.setConsumer(consumerConfig);
 
         MethodConfig methodConfig = new MethodConfig();
-        methodConfig.setName("method1");
+        methodConfig.setName("sayName");
         methodConfig.setStat(1);
         methodConfig.setRetries(0);
         methodConfig.setExecutes(10);
@@ -230,41 +215,8 @@ public class ReferenceConfigTest {
         methodConfig.setServiceId(DemoService.class.getName());
         methodConfig.setParentPrefix("demo");
 
-
         referenceConfig.setMethods(Collections.singletonList(methodConfig));
 
-        ConfigManager configManager = mock(ConfigManager.class);
-        Environment environment = mock(Environment.class);
-        CompositeConfiguration compositeConfiguration = mock(CompositeConfiguration.class);
-        Configuration dynamicGlobalConfiguration = mock(Configuration.class);
-        ServiceRepository serviceRepository = mock(ServiceRepository.class);
-        ConsumerModel consumerModel = mock(ConsumerModel.class);
-
-        when(configManager.getApplicationOrElseThrow()).thenReturn(applicationConfig);
-        when(configManager.getMetrics()).thenReturn(Optional.of(metricsConfig));
-        when(configManager.getModule()).thenReturn(Optional.of(moduleConfig));
-
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-        applicationModelMockedStatic.when(ApplicationModel::getServiceRepository).thenReturn(serviceRepository);
-        when(environment.getConfiguration()).thenReturn(compositeConfiguration);
-        when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
-        when(compositeConfiguration.convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true))
-            .thenReturn(true);
-
-        MockedStatic metadataReportInstanceMockedStatic =
-            Mockito.mockStatic(MetadataReportInstance.class);
-
-        MetadataReport metadataReport = mock(MetadataReport.class);
-        metadataReportInstanceMockedStatic.when(() -> MetadataReportInstance.getMetadataReport("default"))
-            .thenReturn(metadataReport);
-
-
-        when(serviceRepository.lookupReferredService("org.apache.dubbo.config.api.DemoService"))
-            .thenReturn(consumerModel);
-
-        referenceConfig.refreshed.set(true);
         referenceConfig.setInterface(DemoService.class);
         referenceConfig.getInterfaceClass();
         referenceConfig.setCheck(false);
@@ -276,6 +228,14 @@ public class ReferenceConfigTest {
 
         referenceConfig.setRegistry(registry);
 
+        DubboBootstrap dubboBootstrap = DubboBootstrap.newInstance(FrameworkModel.defaultModel());
+        dubboBootstrap.application(applicationConfig)
+            .reference(referenceConfig)
+            .registry(registry)
+            .metrics(metricsConfig)
+            .module(moduleConfig)
+            .initialize();
+
         referenceConfig.init();
 
         ServiceMetadata serviceMetadata = referenceConfig.getServiceMetadata();
@@ -399,20 +359,20 @@ public class ReferenceConfigTest {
         // verify additional method config
         Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("name"));
         Assertions.assertEquals(methodConfig.getStat().toString(),
-            serviceMetadata.getAttachments().get("method1.stat"));
+            serviceMetadata.getAttachments().get("sayName.stat"));
         Assertions.assertEquals(methodConfig.getRetries().toString(),
-            serviceMetadata.getAttachments().get("method1.retries"));
-        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("method1.reliable"));
+            serviceMetadata.getAttachments().get("sayName.retries"));
+        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("sayName.reliable"));
         Assertions.assertEquals(methodConfig.getExecutes().toString(),
-            serviceMetadata.getAttachments().get("method1.executes"));
+            serviceMetadata.getAttachments().get("sayName.executes"));
         Assertions.assertEquals(methodConfig.getDeprecated().toString(),
-            serviceMetadata.getAttachments().get("method1.deprecated"));
-        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("method1.stick"));
+            serviceMetadata.getAttachments().get("sayName.deprecated"));
+        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("sayName.stick"));
         Assertions.assertEquals(methodConfig.isReturn().toString(),
-            serviceMetadata.getAttachments().get("method1.return"));
-        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("method1.service"));
-        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("method1.service.id"));
-        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("method1.parent.prefix"));
+            serviceMetadata.getAttachments().get("sayName.return"));
+        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("sayName.service"));
+        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("sayName.service.id"));
+        Assertions.assertFalse(serviceMetadata.getAttachments().containsKey("sayName.parent.prefix"));
 
         // verify additional revision and methods parameter
         Assertions.assertEquals(Version.getVersion(referenceConfig.getInterfaceClass(), referenceConfig.getVersion()),
@@ -421,8 +381,7 @@ public class ReferenceConfigTest {
         Assertions.assertEquals(DemoService.class.getMethods().length,
             StringUtils.split((String) serviceMetadata.getAttachments().get(METHODS_KEY), ',').length);
 
-        applicationModelMockedStatic.closeOnDemand();
-        metadataReportInstanceMockedStatic.closeOnDemand();
+        dubboBootstrap.stop();
     }
 
     @Test
@@ -493,11 +452,6 @@ public class ReferenceConfigTest {
         ReferenceConfig referenceConfig = new ReferenceConfig<>();
         referenceConfig.setScope(LOCAL_KEY);
 
-        DubboBootstrap.getInstance()
-            .application("application1")
-            .initialize();
-        referenceConfig.setBootstrap(DubboBootstrap.getInstance());
-
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("application1");
         Map parameters = new HashMap<>();
@@ -505,40 +459,15 @@ public class ReferenceConfigTest {
         parameters.put("key2", "value2");
         applicationConfig.setParameters(parameters);
 
-        ConfigManager configManager = mock(ConfigManager.class);
-        Environment environment = mock(Environment.class);
-        CompositeConfiguration compositeConfiguration = mock(CompositeConfiguration.class);
-        Configuration dynamicGlobalConfiguration = mock(Configuration.class);
-        ServiceRepository serviceRepository = mock(ServiceRepository.class);
-        ConsumerModel consumerModel = mock(ConsumerModel.class);
-
-        when(configManager.getApplicationOrElseThrow()).thenReturn(applicationConfig);
-
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-        applicationModelMockedStatic.when(ApplicationModel::getServiceRepository).thenReturn(serviceRepository);
-        when(environment.getConfiguration()).thenReturn(compositeConfiguration);
-        when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
-        when(compositeConfiguration.convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true))
-            .thenReturn(true);
-
-        MockedStatic metadataReportInstanceMockedStatic =
-            Mockito.mockStatic(MetadataReportInstance.class);
-
-        MetadataReport metadataReport = mock(MetadataReport.class);
-        metadataReportInstanceMockedStatic.when(() -> MetadataReportInstance.getMetadataReport("default"))
-            .thenReturn(metadataReport);
-
-
-        when(serviceRepository.lookupReferredService("org.apache.dubbo.config.api.DemoService"))
-            .thenReturn(consumerModel);
-
-        referenceConfig.refreshed.set(true);
         referenceConfig.setInterface(DemoService.class);
         referenceConfig.getInterfaceClass();
         referenceConfig.setCheck(false);
 
+        DubboBootstrap dubboBootstrap = DubboBootstrap.newInstance(FrameworkModel.defaultModel());
+        dubboBootstrap.application(applicationConfig)
+            .reference(referenceConfig)
+            .initialize();
+
         referenceConfig.init();
         Assertions.assertTrue(referenceConfig.getInvoker() instanceof ListenerInvokerWrapper);
         Assertions.assertTrue(((ListenerInvokerWrapper) referenceConfig.getInvoker()).getInvoker() instanceof InjvmInvoker);
@@ -547,11 +476,9 @@ public class ReferenceConfigTest {
         Assertions.assertEquals("value1", url.getParameter("key1"));
         Assertions.assertEquals("value2", url.getParameter("key2"));
 
-        applicationModelMockedStatic.closeOnDemand();
-        metadataReportInstanceMockedStatic.closeOnDemand();
+        dubboBootstrap.stop();
     }
 
-
     /**
      * Verify the configuration of the registry protocol for remote reference
      */
@@ -565,10 +492,7 @@ public class ReferenceConfigTest {
         referenceConfig.setLazy(false);
         referenceConfig.setInjvm(false);
 
-        DubboBootstrap.getInstance()
-            .application("application1")
-            .initialize();
-        referenceConfig.setBootstrap(DubboBootstrap.getInstance());
+        DubboBootstrap dubboBootstrap = DubboBootstrap.newInstance(FrameworkModel.defaultModel());
 
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("application1");
@@ -577,35 +501,6 @@ public class ReferenceConfigTest {
         parameters.put("key2", "value2");
         applicationConfig.setParameters(parameters);
 
-        ConfigManager configManager = mock(ConfigManager.class);
-        Environment environment = mock(Environment.class);
-        CompositeConfiguration compositeConfiguration = mock(CompositeConfiguration.class);
-        Configuration dynamicGlobalConfiguration = mock(Configuration.class);
-        ServiceRepository serviceRepository = mock(ServiceRepository.class);
-        ConsumerModel consumerModel = mock(ConsumerModel.class);
-
-        when(configManager.getApplicationOrElseThrow()).thenReturn(applicationConfig);
-
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-        applicationModelMockedStatic.when(ApplicationModel::getServiceRepository).thenReturn(serviceRepository);
-        when(environment.getConfiguration()).thenReturn(compositeConfiguration);
-        when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
-        when(compositeConfiguration.convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true))
-            .thenReturn(true);
-
-        MockedStatic metadataReportInstanceMockedStatic =
-            Mockito.mockStatic(MetadataReportInstance.class);
-
-        MetadataReport metadataReport = mock(MetadataReport.class);
-        metadataReportInstanceMockedStatic.when(() -> MetadataReportInstance.getMetadataReport("default"))
-            .thenReturn(metadataReport);
-
-
-        when(serviceRepository.lookupReferredService("org.apache.dubbo.config.api.DemoService"))
-            .thenReturn(consumerModel);
-
         referenceConfig.refreshed.set(true);
         referenceConfig.setInterface(DemoService.class);
         referenceConfig.getInterfaceClass();
@@ -617,11 +512,15 @@ public class ReferenceConfigTest {
 
         referenceConfig.setRegistry(registry);
 
+        dubboBootstrap
+            .application(applicationConfig)
+            .reference(referenceConfig)
+            .initialize();
+
         referenceConfig.init();
         Assertions.assertTrue(referenceConfig.getInvoker() instanceof MigrationInvoker);
 
-        applicationModelMockedStatic.closeOnDemand();
-        metadataReportInstanceMockedStatic.closeOnDemand();
+        dubboBootstrap.destroy();
     }
 
     /**
@@ -637,10 +536,7 @@ public class ReferenceConfigTest {
         referenceConfig.setLazy(false);
         referenceConfig.setInjvm(false);
 
-        DubboBootstrap.getInstance()
-            .application("application1")
-            .initialize();
-        referenceConfig.setBootstrap(DubboBootstrap.getInstance());
+        DubboBootstrap dubboBootstrap = DubboBootstrap.newInstance(FrameworkModel.defaultModel());
 
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("application1");
@@ -649,55 +545,32 @@ public class ReferenceConfigTest {
         parameters.put("key2", "value2");
         applicationConfig.setParameters(parameters);
 
-        ConfigManager configManager = mock(ConfigManager.class);
-        Environment environment = mock(Environment.class);
-        CompositeConfiguration compositeConfiguration = mock(CompositeConfiguration.class);
-        Configuration dynamicGlobalConfiguration = mock(Configuration.class);
-        ServiceRepository serviceRepository = mock(ServiceRepository.class);
-        ConsumerModel consumerModel = mock(ConsumerModel.class);
-
-        when(configManager.getApplicationOrElseThrow()).thenReturn(applicationConfig);
-
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-        applicationModelMockedStatic.when(ApplicationModel::getServiceRepository).thenReturn(serviceRepository);
-        when(environment.getConfiguration()).thenReturn(compositeConfiguration);
-        when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
-        when(compositeConfiguration.convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true))
-            .thenReturn(true);
-
-        MockedStatic metadataReportInstanceMockedStatic =
-            Mockito.mockStatic(MetadataReportInstance.class);
-
-        MetadataReport metadataReport = mock(MetadataReport.class);
-        metadataReportInstanceMockedStatic.when(() -> MetadataReportInstance.getMetadataReport("default"))
-            .thenReturn(metadataReport);
-
-
-        when(serviceRepository.lookupReferredService("org.apache.dubbo.config.api.DemoService"))
-            .thenReturn(consumerModel);
-
         referenceConfig.refreshed.set(true);
         referenceConfig.setInterface(DemoService.class);
         referenceConfig.getInterfaceClass();
         referenceConfig.setCheck(false);
 
         referenceConfig.setUrl(registryUrl);
+
+        dubboBootstrap
+            .application(applicationConfig)
+            .reference(referenceConfig)
+            .initialize();
+
         referenceConfig.init();
         Assertions.assertTrue(referenceConfig.getInvoker() instanceof MigrationInvoker);
+        dubboBootstrap.destroy();
 
-        applicationModelMockedStatic.closeOnDemand();
-        metadataReportInstanceMockedStatic.closeOnDemand();
     }
 
+
     @Test
     @Disabled("Disabled due to Github Actions environment")
     public void testInjvm() throws Exception {
         ApplicationConfig application = new ApplicationConfig();
         application.setName("test-protocol-random-port");
         application.setEnableFileCache(false);
-        ApplicationModel.getConfigManager().setApplication(application);
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(application);
 
         RegistryConfig registry = new RegistryConfig();
         registry.setAddress(zkUrl);
@@ -741,7 +614,7 @@ public class ReferenceConfigTest {
         ApplicationConfig application = new ApplicationConfig();
         application.setName("test-reference-retry");
         application.setEnableFileCache(false);
-        ApplicationModel.getConfigManager().setApplication(application);
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(application);
 
         RegistryConfig registry = new RegistryConfig();
         registry.setAddress(zkUrl);
@@ -834,7 +707,7 @@ public class ReferenceConfigTest {
         configCenterConfig.setAddress("diamond://");
 
         testInitReferences(0, amount, applicationConfig, metadataReportConfig, configCenterConfig);
-        ApplicationModel.getConfigManager().clear();
+        ApplicationModel.defaultModel().getApplicationConfigManager().clear();
         testInitReferences(0, 1, applicationConfig, metadataReportConfig, configCenterConfig);
 
         long t1 = System.currentTimeMillis();
@@ -891,7 +764,7 @@ public class ReferenceConfigTest {
                 referenceConfig.setConfigCenter(configCenterConfig);
                 DubboBootstrap.getInstance().reference(referenceConfig);
 
-                //ApplicationModel.getConfigManager().getConfigCenters();
+                //ApplicationModel.defaultModel().getConfigManager().getConfigCenters();
             }
         } catch (Throwable e) {
             e.printStackTrace();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/RegistryConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/RegistryConfigTest.java
index 76e79bde5b..b895d6daed 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/RegistryConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/RegistryConfigTest.java
@@ -17,10 +17,10 @@
 
 package org.apache.dubbo.config;
 
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
@@ -227,7 +227,7 @@ public class RegistryConfigTest {
         DubboBootstrap.getInstance()
             .application("demo-app")
             .initialize();
-        Collection registries = ApplicationModel.getConfigManager().getRegistries();
+        Collection registries = ApplicationModel.defaultModel().getApplicationConfigManager().getRegistries();
         Assertions.assertEquals(1, registries.size());
         RegistryConfig registryConfig = registries.iterator().next();
         Assertions.assertEquals("zookeeper://localhost:2188", registryConfig.getAddress());
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
index 18a35bd1eb..c4254567f6 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.dubbo.config;
 
-import com.google.common.collect.Lists;
-
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.api.DemoService;
@@ -35,6 +33,7 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.service.GenericService;
 
+import com.google.common.collect.Lists;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -69,10 +68,10 @@ import static org.hamcrest.Matchers.hasEntry;
 import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.mockito.Mockito.withSettings;
 
 public class ServiceConfigTest {
@@ -86,7 +85,7 @@ public class ServiceConfigTest {
 
     @BeforeEach
     public void setUp() throws Exception {
-        ApplicationModel.getConfigManager().clear();
+        ApplicationModel.defaultModel().getApplicationConfigManager().clear();
 
         MockProtocol2.delegate = protocolDelegate;
         MockRegistryFactory2.registry = registryDelegate;
@@ -149,7 +148,7 @@ public class ServiceConfigTest {
 
     @AfterEach
     public void tearDown() {
-        ApplicationModel.getConfigManager().clear();
+        ApplicationModel.defaultModel().getApplicationConfigManager().clear();
     }
 
     @Test
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
new file mode 100644
index 0000000000..19fe85f371
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.config.bootstrap;
+
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+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.SysProps;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.apache.dubbo.registrycenter.RegistryCenter;
+import org.apache.dubbo.registrycenter.ZookeeperSingleRegistryCenter;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class DubboBootstrapMultiInstanceTest {
+
+    private static ZookeeperSingleRegistryCenter registryCenter;
+
+    private static RegistryConfig registryConfig;
+
+    @BeforeAll
+    public static void setup() {
+        registryCenter = new ZookeeperSingleRegistryCenter(NetUtils.getAvailablePort());
+        registryCenter.startup();
+        RegistryCenter.Instance instance = registryCenter.getRegistryCenterInstance().get(0);
+        registryConfig = new RegistryConfig(String.format("%s://%s:%s",
+            instance.getType(),
+            instance.getHostname(),
+            instance.getPort()));
+
+    }
+
+    @AfterAll
+    public static void teardown() {
+        registryCenter.shutdown();
+    }
+
+    @AfterEach
+    protected void afterEach() {
+        SysProps.clear();
+        DubboBootstrap.reset();
+    }
+
+    @Test
+    public void testIsolatedApplications() {
+
+        DubboBootstrap dubboBootstrap1 = DubboBootstrap.newInstance();
+        DubboBootstrap dubboBootstrap2 = DubboBootstrap.newInstance();
+        ApplicationModel applicationModel1 = dubboBootstrap1.getApplicationModel();
+        ApplicationModel applicationModel2 = dubboBootstrap2.getApplicationModel();
+        Assertions.assertNotSame(applicationModel1, applicationModel2);
+        Assertions.assertNotSame(applicationModel1.getFrameworkModel(), applicationModel2.getFrameworkModel());
+        Assertions.assertNotSame(dubboBootstrap1.getConfigManager(), dubboBootstrap2.getConfigManager());
+
+        // bootstrap1: provider app
+        configProviderApp(dubboBootstrap1).start();
+
+        // bootstrap2: consumer app
+        configConsumerApp(dubboBootstrap2).start();
+        testConsumer(dubboBootstrap2);
+
+        DemoService demoServiceFromProvider = dubboBootstrap1.getCache().get(DemoService.class);
+        Assertions.assertNull(demoServiceFromProvider);
+    }
+
+    @Test
+    public void testDefaultProviderApplication() {
+        configProviderApp(DubboBootstrap.getInstance()).start();
+    }
+
+    @Test
+    public void testDefaultConsumerApplication() {
+        SysProps.setProperty("dubbo.consumer.check", "false");
+        try {
+            DubboBootstrap dubboBootstrap = DubboBootstrap.getInstance();
+            configConsumerApp(dubboBootstrap).start();
+            testConsumer(dubboBootstrap);
+        } catch (Exception e) {
+            Assertions.assertTrue(e.toString().contains("No provider available from registry"), StringUtils.toString(e));
+        }
+    }
+
+    @Test
+    public void testDefaultMixedApplication() {
+        DubboBootstrap dubboBootstrap = DubboBootstrap.getInstance();
+        dubboBootstrap.application("mixed-app");
+
+        configProviderApp(dubboBootstrap);
+        configConsumerApp(dubboBootstrap);
+        dubboBootstrap.start();
+        testConsumer(dubboBootstrap);
+    }
+
+    @Test
+    public void testSharedApplications() {
+
+        FrameworkModel frameworkModel = new FrameworkModel();
+        DubboBootstrap dubboBootstrap1 = DubboBootstrap.newInstance(frameworkModel);
+        DubboBootstrap dubboBootstrap2 = DubboBootstrap.newInstance(frameworkModel);
+        ApplicationModel applicationModel1 = dubboBootstrap1.getApplicationModel();
+        ApplicationModel applicationModel2 = dubboBootstrap2.getApplicationModel();
+        Assertions.assertNotSame(applicationModel1, applicationModel2);
+        Assertions.assertSame(applicationModel1.getFrameworkModel(), applicationModel2.getFrameworkModel());
+        Assertions.assertNotSame(dubboBootstrap1.getConfigManager(), dubboBootstrap2.getConfigManager());
+
+    }
+
+    private DubboBootstrap configConsumerApp(DubboBootstrap dubboBootstrap) {
+        ReferenceConfig referenceConfig = new ReferenceConfig<>();
+        referenceConfig.setInterface(DemoService.class);
+
+        if (!dubboBootstrap.getConfigManager().getApplication().isPresent()) {
+            dubboBootstrap.application("consumer-app");
+        }
+        dubboBootstrap.registry(registryConfig)
+            .reference(referenceConfig);
+        return dubboBootstrap;
+    }
+
+    private void testConsumer(DubboBootstrap dubboBootstrap) {
+        DemoService demoService = dubboBootstrap.getCache().get(DemoService.class);
+        String result = demoService.sayName("dubbo");
+        System.out.println("result: " + result);
+        Assertions.assertEquals("say:dubbo", result);
+    }
+
+    private DubboBootstrap configProviderApp(DubboBootstrap dubboBootstrap) {
+        ProtocolConfig protocol1 = new ProtocolConfig();
+        protocol1.setName("dubbo");
+        protocol1.setPort(2001);
+
+        ServiceConfig serviceConfig = new ServiceConfig<>();
+        serviceConfig.setInterface(DemoService.class);
+        serviceConfig.setRef(new DemoServiceImpl());
+
+        if (!dubboBootstrap.getConfigManager().getApplication().isPresent()) {
+            dubboBootstrap.application("provider-app");
+        }
+        dubboBootstrap.registry(registryConfig)
+            .protocol(protocol1)
+            .service(serviceConfig);
+        return dubboBootstrap;
+    }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
index 24915d7753..9c669c1bce 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
@@ -37,7 +37,6 @@ import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.monitor.MonitorService;
 import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.registry.client.metadata.MetadataUtils;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
@@ -161,7 +160,7 @@ public class DubboBootstrapTest {
 
         serviceConfig.refresh();
 
-        //ApplicationModel.getEnvironment().setDynamicConfiguration(new CompositeDynamicConfiguration());
+        //ApplicationModel.defaultModel().getEnvironment().setDynamicConfiguration(new CompositeDynamicConfiguration());
         List urls = ConfigValidationUtils.loadRegistries(serviceConfig, true);
         Assertions.assertEquals(2, urls.size());
         for (URL url : urls) {
@@ -332,7 +331,7 @@ public class DubboBootstrapTest {
 
     private void assertMetadataService(DubboBootstrap bootstrap, int availablePort, boolean shouldReport) {
         Assertions.assertTrue(bootstrap.metadataServiceExporter.isExported());
-        DubboProtocol protocol = DubboProtocol.getDubboProtocol();
+        DubboProtocol protocol = DubboProtocol.getDubboProtocol(bootstrap.getApplicationModel());
         Map> exporters = protocol.getExporterMap();
         Assertions.assertEquals(2, exporters.size());
 
@@ -343,7 +342,7 @@ public class DubboBootstrapTest {
         serviceConfig.setVersion(MetadataService.VERSION);
         assertThat(exporters, hasEntry(is(serviceConfig.getUniqueServiceName() + ":" + availablePort), anything()));
 
-        WritableMetadataService metadataService = MetadataUtils.getLocalMetadataService();
+        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel());
         MetadataInfo metadataInfo = metadataService.getDefaultMetadataInfo();
         Assertions.assertNotNull(metadataInfo);
         if (shouldReport) {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/cache/CacheTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/cache/CacheTest.java
index fd63b8a5a1..e0dab84dce 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/cache/CacheTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/cache/CacheTest.java
@@ -55,7 +55,7 @@ public class CacheTest {
 
     @AfterEach
     public void tearDown() {
-//        ApplicationModel.getConfigManager().clear();
+//        ApplicationModel.defaultModel().getConfigManager().clear();
     }
 
     private void testCache(String type) throws Exception {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
index fee54703e5..5e932c6aa8 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
@@ -136,13 +136,13 @@ public class InvokerSideConfigUrlTest extends UrlTestBase {
     public void setUp() {
         initServConf();
         initRefConf();
-//        ApplicationModel.getConfigManager().clear();
+//        ApplicationModel.defaultModel().getConfigManager().clear();
     }
 
     @AfterEach()
     public void teardown() {
         //RegistryServer.reloadCache();
-//        ApplicationModel.getConfigManager().clear();
+//        ApplicationModel.defaultModel().getConfigManager().clear();
     }
 
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
index 9eb749c1c9..322d6daf51 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
@@ -19,11 +19,11 @@ package org.apache.dubbo.integration.multiple.exportprovider;
 import org.apache.dubbo.common.config.configcenter.ConfigItem;
 import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.ApplicationConfig;
 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.ServiceListener;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.integration.IntegrationTest;
@@ -34,6 +34,8 @@ import org.apache.dubbo.registrycenter.RegistryCenter;
 import org.apache.dubbo.registrycenter.ZookeeperMultipleRegistryCenter;
 import org.apache.dubbo.rpc.ExporterListener;
 import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -218,7 +220,7 @@ public class MultipleRegistryCenterExportProviderIntegrationTest implements Inte
         // registryKey: the registryKey is the default cluster, CommonConstants.DEFAULT_KEY
         // key: The exported interface's name
         // group: the group is "mapping", ServiceNameMapping.DEFAULT_MAPPING_GROUP
-        ConfigItem configItem = MetadataReportInstance.getMetadataReport(CommonConstants.DEFAULT_KEY)
+        ConfigItem configItem = ApplicationModel.defaultModel().getBeanFactory().getBean(MetadataReportInstance.class).getMetadataReport(CommonConstants.DEFAULT_KEY)
             .getConfigItem(serviceConfig.getInterface()
                 , ServiceNameMapping.DEFAULT_MAPPING_GROUP);
         // Check if the exported service (provider) is registered
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
index b7cbf34d56..00d45f4ea3 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListener.java
@@ -35,14 +35,15 @@ public class MultipleRegistryCenterServiceDiscoveryRegistryRegistryServiceListen
     /**
      * Create an {@link ServiceDiscoveryRegistryInfoWrapper} instance.
      */
-    private ServiceDiscoveryRegistryInfoWrapper createServiceDiscoveryRegistryInfoWrapper(ServiceDiscoveryRegistry serviceDiscoveryRegistry) {
-        String host = serviceDiscoveryRegistry.getUrl().getHost();
-        int port = serviceDiscoveryRegistry.getUrl().getPort();
+    private ServiceDiscoveryRegistryInfoWrapper createServiceDiscoveryRegistryInfoWrapper(ServiceDiscoveryRegistry serviceDiscoveryRegistry){
+        URL url = serviceDiscoveryRegistry.getUrl();
+        String host = url.getHost();
+        int port = url.getPort();
         ServiceDiscoveryRegistryInfoWrapper serviceDiscoveryRegistryInfoWrapper = new ServiceDiscoveryRegistryInfoWrapper();
         serviceDiscoveryRegistryInfoWrapper.setHost(host);
         serviceDiscoveryRegistryInfoWrapper.setPort(port);
         serviceDiscoveryRegistryInfoWrapper.setServiceDiscoveryRegistry(serviceDiscoveryRegistry);
-        serviceDiscoveryRegistryInfoWrapper.setInMemoryWritableMetadataService((InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension());
+        serviceDiscoveryRegistryInfoWrapper.setInMemoryWritableMetadataService((InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(url.getScopeModel()));
         serviceDiscoveryRegistryInfoWrapper.setRegistered(true);
         return serviceDiscoveryRegistryInfoWrapper;
     }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
index 1396fcb6c9..cfb9df8fb8 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
@@ -234,7 +234,7 @@ public class SingleRegistryCenterDubboProtocolIntegrationTest implements Integra
         Assertions.assertTrue(services.contains(PROVIDER_APPLICATION_NAME));
 
         // obtain InMemoryWritableMetadataService instance
-        InMemoryWritableMetadataService inMemoryWritableMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension();
+        InMemoryWritableMetadataService inMemoryWritableMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(serviceConfig.getScopeModel());
         // Exported url is right or not in InMemoryWritableMetadataService
         Assertions.assertEquals(inMemoryWritableMetadataService.getExportedURLs().size(), 1);
         // MetadataInfo exists or not in InMemoryWritableMetadataService
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
index 05378e7220..ec806b94f3 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
@@ -19,11 +19,11 @@ package org.apache.dubbo.integration.single.exportprovider;
 import org.apache.dubbo.common.config.configcenter.ConfigItem;
 import org.apache.dubbo.common.constants.CommonConstants;
 import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ReferenceConfig;
 import org.apache.dubbo.config.ApplicationConfig;
 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.ServiceListener;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.integration.IntegrationTest;
@@ -34,6 +34,8 @@ import org.apache.dubbo.registrycenter.RegistryCenter;
 import org.apache.dubbo.registrycenter.ZookeeperMultipleRegistryCenter;
 import org.apache.dubbo.rpc.ExporterListener;
 import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -216,7 +218,7 @@ public class SingleRegistryCenterExportProviderIntegrationTest implements Integr
         // registryKey: the registryKey is the default cluster, CommonConstants.DEFAULT_KEY
         // key: The exported interface's name
         // group: the group is "mapping", ServiceNameMapping.DEFAULT_MAPPING_GROUP
-        ConfigItem configItem = MetadataReportInstance.getMetadataReport(CommonConstants.DEFAULT_KEY)
+        ConfigItem configItem = ApplicationModel.defaultModel().getBeanFactory().getBean(MetadataReportInstance.class).getMetadataReport(CommonConstants.DEFAULT_KEY)
             .getConfigItem(serviceConfig.getInterface()
                 , ServiceNameMapping.DEFAULT_MAPPING_GROUP);
         // Check if the exported service (provider) is registered
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
index 77c04feedb..95fc792e03 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
@@ -43,9 +43,9 @@ public class MetadataServiceExporterTest {
     @BeforeAll
     public static void init() {
         DubboBootstrap.reset();
-        ApplicationModel.getConfigManager().setApplication(new ApplicationConfig("Test"));
-        ApplicationModel.getConfigManager().addRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
-        ApplicationModel.getConfigManager().addProtocol(new ProtocolConfig("injvm"));
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(new ApplicationConfig("Test"));
+        ApplicationModel.defaultModel().getApplicationConfigManager().addRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
+        ApplicationModel.defaultModel().getApplicationConfigManager().addProtocol(new ProtocolConfig("injvm"));
     }
 
     @AfterAll
@@ -56,7 +56,9 @@ public class MetadataServiceExporterTest {
     @Test
     public void test() {
         MetadataService metadataService = Mockito.mock(MetadataService.class);
-        MetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter(metadataService);
+        ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
+        exporter.setMetadataService(metadataService);
+        exporter.setApplicationModel(ApplicationModel.defaultModel());
 
         exporter.export();
         assertTrue(exporter.isExported());
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
index 84ddac5247..6374cdbf8c 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -19,7 +19,7 @@ package org.apache.dubbo.config.spring;
 import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.context.ApplicationContext;
@@ -46,7 +46,7 @@ public class ConfigCenterBean extends ConfigCenterConfig implements ApplicationC
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) {
         this.applicationContext = applicationContext;
-        SpringExtensionFactory.addApplicationContext(applicationContext);
+        SpringExtensionInjector.addApplicationContext(applicationContext);
     }
 
     @Override
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index ca3e85c6cd..94af84abf2 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.config.ServiceConfig;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 import org.apache.dubbo.config.support.Parameter;
 
 import org.springframework.aop.support.AopUtils;
@@ -65,8 +65,8 @@ public class ServiceBean extends ServiceConfig implements InitializingBean
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) {
         this.applicationContext = applicationContext;
-        //TODO remove SpringExtensionFactory.addApplicationContext();
-        SpringExtensionFactory.addApplicationContext(applicationContext);
+        //TODO remove SpringExtensionInjector.addApplicationContext();
+        SpringExtensionInjector.addApplicationContext(applicationContext);
     }
 
     @Override
@@ -126,7 +126,7 @@ public class ServiceBean extends ServiceConfig implements InitializingBean
     @Override
     public void destroy() throws Exception {
         // no need to call unexport() here, see
-        // org.apache.dubbo.config.spring.extension.SpringExtensionFactory.ShutdownHookListener
+        // org.apache.dubbo.config.spring.extension.SpringExtensionInjector.ShutdownHookListener
     }
 
     // merged from dubbox
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
index 61e0f81bed..f51bb35950 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
@@ -16,8 +16,6 @@
  */
 package org.apache.dubbo.config.spring.context;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.apache.dubbo.config.AbstractConfig;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ConsumerConfig;
@@ -33,6 +31,9 @@ import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.spring.ConfigCenterBean;
 import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
 import org.springframework.beans.BeansException;
 import org.springframework.beans.FatalBeanException;
 import org.springframework.beans.factory.BeanFactory;
@@ -73,7 +74,7 @@ public class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin
 
     private void init() {
         if (initialized.compareAndSet(false, true)) {
-            configManager = ApplicationModel.getConfigManager();
+            configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
             referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
             try {
                 prepareDubboConfigBeans();
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
index 79529826d5..0f79d22796 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
@@ -18,10 +18,11 @@ package org.apache.dubbo.config.spring.context;
 
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 import org.apache.dubbo.config.spring.util.DubboBeanUtils;
 import org.apache.dubbo.config.spring.util.EnvironmentUtils;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.springframework.beans.BeansException;
 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -74,15 +75,15 @@ public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegist
         // Extract dubbo props from Spring env and put them to app config
         ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();
         SortedMap dubboProperties = EnvironmentUtils.filterDubboProperties(environment);
-        ApplicationModel.getEnvironment().setAppConfigMap(dubboProperties);
+        ApplicationModel.defaultModel().getApplicationEnvironment().setAppConfigMap(dubboProperties);
 
         // register ConfigManager singleton
-        beanFactory.registerSingleton(ConfigManager.BEAN_NAME, ApplicationModel.getConfigManager());
+        beanFactory.registerSingleton(ConfigManager.BEAN_NAME, ApplicationModel.defaultModel().getApplicationConfigManager());
     }
 
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
         this.applicationContext = applicationContext;
-        SpringExtensionFactory.addApplicationContext(applicationContext);
+        SpringExtensionInjector.addApplicationContext(applicationContext);
     }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
similarity index 87%
rename from dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java
rename to dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
index 27eec782de..c580ab2538 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.config.spring.extension;
 
 import org.apache.dubbo.common.context.Lifecycle;
-import org.apache.dubbo.common.extension.ExtensionFactory;
+import org.apache.dubbo.common.extension.ExtensionInjector;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -31,10 +31,10 @@ import org.springframework.context.ConfigurableApplicationContext;
 import java.util.Set;
 
 /**
- * SpringExtensionFactory
+ * SpringExtensionInjector
  */
-public class SpringExtensionFactory implements ExtensionFactory, Lifecycle {
-    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class);
+public class SpringExtensionInjector implements ExtensionInjector, Lifecycle {
+    private static final Logger logger = LoggerFactory.getLogger(SpringExtensionInjector.class);
 
     private static final Set CONTEXTS = new ConcurrentHashSet();
 
@@ -47,10 +47,6 @@ public class SpringExtensionFactory implements ExtensionFactory, Lifecycle {
         }
     }
 
-    public static void removeApplicationContext(ApplicationContext context) {
-        CONTEXTS.remove(context);
-    }
-
     public static Set getContexts() {
         return CONTEXTS;
     }
@@ -62,9 +58,9 @@ public class SpringExtensionFactory implements ExtensionFactory, Lifecycle {
 
     @Override
     @SuppressWarnings("unchecked")
-    public  T getExtension(Class type, String name) {
+    public  T getInstance(Class type, String name) {
 
-        //SPI should be get from SpiExtensionFactory
+        //SPI should be get from SpiExtensionInjector
         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
             return null;
         }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
index 28323bb731..c28db3741d 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.status.Status;
 import org.apache.dubbo.common.status.StatusChecker;
 import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 
 import org.springframework.context.ApplicationContext;
 
@@ -45,7 +45,7 @@ public class DataSourceStatusChecker implements StatusChecker {
     @Override
     public Status check() {
         Optional context =
-                SpringExtensionFactory.getContexts().stream().filter(Objects::nonNull).findFirst();
+                SpringExtensionInjector.getContexts().stream().filter(Objects::nonNull).findFirst();
 
         if (!context.isPresent()) {
             return new Status(Status.Level.UNKNOWN);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
index c259a78b52..cae92602a1 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.status.Status;
 import org.apache.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.Lifecycle;
@@ -40,7 +40,7 @@ public class SpringStatusChecker implements StatusChecker {
     @Override
     public Status check() {
         ApplicationContext context = null;
-        for (ApplicationContext c : SpringExtensionFactory.getContexts()) {
+        for (ApplicationContext c : SpringExtensionInjector.getContexts()) {
             // [Issue] SpringStatusChecker execute errors on non-XML Spring configuration
             // issue : https://github.com/apache/dubbo/issues/3615
             if(c instanceof GenericWebApplicationContext) { // ignore GenericXmlApplicationContext
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
deleted file mode 100644
index 4ac9db2ed9..0000000000
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
+++ /dev/null
@@ -1 +0,0 @@
-spring=org.apache.dubbo.config.spring.extension.SpringExtensionFactory
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
new file mode 100644
index 0000000000..c5ef410440
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
@@ -0,0 +1 @@
+spring=org.apache.dubbo.config.spring.extension.SpringExtensionInjector
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
index 9a1b3b910b..f829284ad1 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
@@ -53,10 +53,10 @@ import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.service.GenericService;
 
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
@@ -135,10 +135,10 @@ public class ConfigTest {
         try {
             ctx.start();
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // clear config manager
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             DemoService demoService = refer("dubbo://127.0.0.1:20887");
             String hello = demoService.sayName("hello");
@@ -245,10 +245,10 @@ public class ConfigTest {
         try {
             ctx.start();
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // clear config manager
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             DemoService demoService = refer("dubbo://127.0.0.1:20881");
             String hello = demoService.sayName("hello");
@@ -487,10 +487,10 @@ public class ConfigTest {
         try {
             providerContext.start();
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // clear config manager
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(resourcePath + "/init-reference.xml",
                     resourcePath + "/init-reference-properties.xml");
@@ -732,7 +732,7 @@ public class ConfigTest {
         ClassPathXmlApplicationContext providerContext = new ClassPathXmlApplicationContext(resourcePath + "/override-protocol.xml");
         try {
             providerContext.start();
-            ConfigManager configManager = ApplicationModel.getConfigManager();
+            ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
             ProtocolConfig protocol = configManager.getProtocol("dubbo").get();
             assertEquals(20812, protocol.getPort());
         } finally {
@@ -748,7 +748,7 @@ public class ConfigTest {
                 "/override-multi-protocol.xml");
         try {
             providerContext.start();
-            ConfigManager configManager = ApplicationModel.getConfigManager();
+            ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
 
             ProtocolConfig dubboProtocol = configManager.getProtocol("dubbo").get();
             assertEquals(20814, dubboProtocol.getPort().intValue());
@@ -841,7 +841,7 @@ public class ConfigTest {
             // set default value of check
             assertEquals(false, reference.shouldCheck());
 
-            ConsumerConfig defaultConsumer = ApplicationModel.getConfigManager().getDefaultConsumer().get();
+            ConsumerConfig defaultConsumer = ApplicationModel.defaultModel().getApplicationConfigManager().getDefaultConsumer().get();
             assertEquals(1234, defaultConsumer.getTimeout());
             assertEquals(false, defaultConsumer.isCheck());
         } finally {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
index 43be9316b5..2f216c02d8 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
@@ -32,10 +32,11 @@ import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.rpc.Constants;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@@ -88,7 +89,7 @@ public class JavaConfigBeanTest {
         try {
             consumerContext.start();
 
-            ConfigManager configManager = ApplicationModel.getConfigManager();
+            ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
             ApplicationConfig application = configManager.getApplication().get();
             Assertions.assertEquals(false, application.getQosEnable());
             Assertions.assertEquals("Tom", application.getOwner());
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
index e15175d8b4..6e25b8f33e 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
@@ -76,10 +76,10 @@ public class DubboComponentScanRegistrarTest {
         // Test @Transactional is present or not
         Assertions.assertNotNull(findAnnotation(beanClass, Transactional.class));
 
-        ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+        ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
         // reset ConfigManager of provider context
         DubboBootstrap.reset(false);
-        ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
         AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
 
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java
index 666e0f1d31..4c309df641 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfigTest.java
@@ -23,12 +23,12 @@ import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
-
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.ZookeeperMultipleRegistryCenter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
@@ -118,7 +118,7 @@ public class EnableDubboConfigTest {
         RegistryConfig registry2 = context.getBean("registry2", RegistryConfig.class);
         Assertions.assertEquals(2182, registry2.getPort());
 
-        ConfigManager configManager = ApplicationModel.getConfigManager();
+        ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
         Collection protocolConfigs = configManager.getProtocols();
         Assertions.assertEquals(3, protocolConfigs.size());
 
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactoryTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
similarity index 78%
rename from dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactoryTest.java
rename to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
index ca70f1f8d0..71e98d7419 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactoryTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
@@ -16,7 +16,7 @@
  */
 package org.apache.dubbo.config.spring.extension;
 
-import org.apache.dubbo.common.extension.ExtensionFactory;
+import org.apache.dubbo.common.extension.ExtensionInjector;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.api.DemoService;
@@ -34,9 +34,9 @@ import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 
 @Configuration
-public class SpringExtensionFactoryTest {
+public class SpringExtensionInjectorTest {
 
-    private SpringExtensionFactory springExtensionFactory = new SpringExtensionFactory();
+    private SpringExtensionInjector springExtensionFactory = new SpringExtensionInjector();
     private AnnotationConfigApplicationContext context1;
     private AnnotationConfigApplicationContext context2;
 
@@ -44,8 +44,8 @@ public class SpringExtensionFactoryTest {
     public void init() {
         DubboBootstrap.reset();
 
-        // init SpringExtensionFactory
-        ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getExtension("spring");
+        // init SpringExtensionInjector
+        ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getExtension("spring");
 
         context1 = new AnnotationConfigApplicationContext();
         context1.setDisplayName("Context1");
@@ -55,28 +55,28 @@ public class SpringExtensionFactoryTest {
         context2.setDisplayName("Context2");
         context2.register(BeanForContext2.class);
         context2.refresh();
-        SpringExtensionFactory.addApplicationContext(context1);
-        SpringExtensionFactory.addApplicationContext(context2);
+        SpringExtensionInjector.addApplicationContext(context1);
+        SpringExtensionInjector.addApplicationContext(context2);
     }
 
     @AfterEach
     public void destroy() {
         context1.close();
         context2.close();
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
     }
 
     @Test
     public void testGetExtensionBySPI() {
-        Protocol protocol = springExtensionFactory.getExtension(Protocol.class, "protocol");
+        Protocol protocol = springExtensionFactory.getInstance(Protocol.class, "protocol");
         Assertions.assertNull(protocol);
     }
 
     @Test
     public void testGetExtensionByName() {
-        DemoService bean = springExtensionFactory.getExtension(DemoService.class, "bean1");
+        DemoService bean = springExtensionFactory.getInstance(DemoService.class, "bean1");
         Assertions.assertNotNull(bean);
-        HelloService hello = springExtensionFactory.getExtension(HelloService.class, "hello");
+        HelloService hello = springExtensionFactory.getInstance(HelloService.class, "hello");
         Assertions.assertNotNull(hello);
     }
 
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
index 869770bda4..75d6b7ac7b 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
@@ -22,9 +22,10 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
-import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
+import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -72,7 +73,7 @@ public class Issue7003Test {
             Map referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
             Assertions.assertEquals(1, referenceBeanMap.size());
 
-            Collection> references = ApplicationModel.getConfigManager().getReferences();
+            Collection> references = ApplicationModel.defaultModel().getApplicationConfigManager().getReferences();
             Assertions.assertEquals(1, references.size());
 
         } finally {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
index fc9e03a7d4..099f8a709c 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
@@ -20,8 +20,8 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
-import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
+import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.AfterAll;
@@ -62,10 +62,10 @@ public class PropertyConfigurerTest {
         try {
             providerContext.start();
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // reset ConfigManager of provider context
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             try {
                 Thread.sleep(1000);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
index c8edbc32da..2cb92ffc5e 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer2/PropertySourcesConfigurerTest.java
@@ -21,8 +21,8 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.apache.dubbo.config.spring.propertyconfigurer.consumer.DemoBeanFactoryPostProcessor;
-import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
+import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.AfterAll;
@@ -68,10 +68,10 @@ public class PropertySourcesConfigurerTest {
             } catch (InterruptedException e) {
             }
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // reset ConfigManager of provider context
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             // Resolve placeholder by PropertySourcesPlaceholderConfigurer in dubbo-consumer.xml, without import property source.
             AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java
index 4d88db27a9..b5b1a2d32b 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer3/PropertySourcesInJavaConfigTest.java
@@ -21,11 +21,14 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
 import org.apache.dubbo.config.spring.propertyconfigurer.consumer.DemoBeanFactoryPostProcessor;
-import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
+import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
-import org.junit.jupiter.api.*;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
@@ -77,10 +80,10 @@ public class PropertySourcesInJavaConfigTest {
             } catch (InterruptedException e) {
             }
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // reset ConfigManager of provider context
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             // Resolve placeholder by import property sources
             AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class, ImportPropertyConfiguration.class);
@@ -115,10 +118,10 @@ public class PropertySourcesInJavaConfigTest {
             } catch (InterruptedException e) {
             }
 
-            ConcurrentMap> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap> tmp = ApplicationModel.defaultModel().getApplicationServiceRepository().getProviderUrlsWithoutGroup();
             // reset ConfigManager of provider context
             DubboBootstrap.reset(false);
-            ApplicationModel.getServiceRepository().setProviderUrlsWithoutGroup(tmp);
+            ApplicationModel.defaultModel().getApplicationServiceRepository().setProviderUrlsWithoutGroup(tmp);
 
             // Resolve placeholder by custom PropertySourcesPlaceholderConfigurer bean
             AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConsumerConfiguration.class, PropertyBeanConfiguration.class);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
index f93bf06ccd..cd65bb463e 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/reference/javaconfig/JavaConfigReferenceBeanTest.java
@@ -24,17 +24,18 @@ import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.api.DemoService;
 import org.apache.dubbo.config.spring.api.HelloService;
 import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 import org.apache.dubbo.config.spring.impl.HelloServiceImpl;
 import org.apache.dubbo.config.spring.reference.ReferenceBeanBuilder;
 import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
 import org.apache.dubbo.config.spring.registrycenter.ZookeeperMultipleRegistryCenter;
 import org.apache.dubbo.rpc.service.GenericException;
 import org.apache.dubbo.rpc.service.GenericService;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.BeforeEach;
+
 import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -55,17 +56,19 @@ public class JavaConfigReferenceBeanTest {
         multipleRegistryCenter = new ZookeeperMultipleRegistryCenter();
         multipleRegistryCenter.startup();
         DubboBootstrap.reset();
+        SpringExtensionInjector.clearContexts();
     }
 
     @AfterEach
     public void tearDown() {
         DubboBootstrap.reset();
         multipleRegistryCenter.shutdown();
+        SpringExtensionInjector.clearContexts();
     }
 
     @Test
     public void testAnnotationAtField() {
-        Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class,
             AnnotationAtFieldConfiguration.class);
 
@@ -82,7 +85,7 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals(HelloService.class.getName(), referenceBean.getServiceInterface());
 
         context.close();
-        Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
     }
 
     @Test
@@ -110,7 +113,7 @@ public class JavaConfigReferenceBeanTest {
 
     @Test
     public void testAnnotationBean() {
-        Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class,
                 AnnotationBeanConfiguration.class);
 
@@ -127,12 +130,12 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals(HelloService.class.getName(), referenceBean.getServiceInterface());
 
         context.close();
-        Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
     }
 
     @Test
     public void testGenericServiceAnnotationBean() {
-        Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class,
             GenericServiceAnnotationBeanConfiguration.class);
 
@@ -163,12 +166,12 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals("Hello Dubbo", sayHelloResult);
 
         context.close();
-        Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
     }
 
     @Test
     public void testReferenceBean() {
-        Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class,
                 ReferenceBeanConfiguration.class);
 
@@ -188,12 +191,12 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals(DemoService.class.getName(), demoServiceReferenceBean.getServiceInterface());
 
         context.close();
-        Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
     }
 
     @Test
     public void testGenericServiceReferenceBean() {
-        Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
         AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(CommonConfig.class,
             GenericServiceReferenceBeanConfiguration.class);
 
@@ -215,14 +218,14 @@ public class JavaConfigReferenceBeanTest {
         Assertions.assertEquals(HelloService.class.getName(), genericHelloServiceReferenceBean.getServiceInterface());
 
         context.close();
-        Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+        Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
     }
 
     @Test
     public void testRawReferenceBean() {
         AnnotationConfigApplicationContext context = null;
         try {
-            Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
             context = new AnnotationConfigApplicationContext(CommonConfig.class, ReferenceBeanWithoutGenericTypeConfiguration.class);
             Assertions.fail("Should not load application");
 
@@ -234,7 +237,7 @@ public class JavaConfigReferenceBeanTest {
             if (context != null) {
                 context.close();
             }
-            Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
         }
 
     }
@@ -243,7 +246,7 @@ public class JavaConfigReferenceBeanTest {
     public void testInconsistentBean() {
         AnnotationConfigApplicationContext context = null;
         try {
-            Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
             context = new AnnotationConfigApplicationContext(CommonConfig.class, InconsistentBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
@@ -255,7 +258,7 @@ public class JavaConfigReferenceBeanTest {
             if (context != null) {
                 context.close();
             }
-            Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
         }
     }
 
@@ -263,7 +266,7 @@ public class JavaConfigReferenceBeanTest {
     public void testMissingGenericTypeBean() {
         AnnotationConfigApplicationContext context = null;
         try {
-            Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
             context = new AnnotationConfigApplicationContext(CommonConfig.class, MissingGenericTypeAnnotationBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
@@ -274,7 +277,7 @@ public class JavaConfigReferenceBeanTest {
             if (context != null) {
                 context.close();
             }
-            Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
         }
     }
 
@@ -282,7 +285,7 @@ public class JavaConfigReferenceBeanTest {
     public void testMissingInterfaceTypeBean() {
         AnnotationConfigApplicationContext context = null;
         try {
-            Assertions.assertEquals(0, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(0, SpringExtensionInjector.getContexts().size());
             context = new AnnotationConfigApplicationContext(CommonConfig.class, MissingInterfaceTypeAnnotationBeanConfiguration.class);
             Assertions.fail("Should not load application");
         } catch (Exception e) {
@@ -292,7 +295,7 @@ public class JavaConfigReferenceBeanTest {
             if (context != null) {
                 context.close();
             }
-            Assertions.assertEquals(1, SpringExtensionFactory.getContexts().size());
+            Assertions.assertEquals(1, SpringExtensionInjector.getContexts().size());
         }
     }
 
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
index d0b2816015..ea99f13d99 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
@@ -127,7 +127,7 @@ public class DubboNamespaceHandlerTest {
         Map protocolConfigMap = ctx.getBeansOfType(ProtocolConfig.class);
         assertThat(protocolConfigMap.size(), is(2));
 
-        ConfigManager configManager = ApplicationModel.getConfigManager();
+        ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
         Collection protocolConfigs = configManager.getProtocols();
         assertThat(protocolConfigs.size(), is(2));
 
@@ -176,7 +176,7 @@ public class DubboNamespaceHandlerTest {
         ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(resourcePath + "/provider-nested-service.xml");
         ctx.start();
 
-        ConfigManager configManager = ApplicationModel.getConfigManager();
+        ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
         Collection providerConfigs = configManager.getProviders();
         Assertions.assertEquals(2, providerConfigs.size());
 
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/DataSourceStatusCheckerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/DataSourceStatusCheckerTest.java
index b12d2d4d97..36985f63c7 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/DataSourceStatusCheckerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/DataSourceStatusCheckerTest.java
@@ -18,7 +18,7 @@ package org.apache.dubbo.config.spring.status;
 
 import org.apache.dubbo.common.status.Status;
 import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -50,7 +50,7 @@ public class DataSourceStatusCheckerTest {
 
     @BeforeEach
     public void setUp() throws Exception {
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
         initMocks(this);
         this.dataSourceStatusChecker = new DataSourceStatusChecker();
         new ServiceBean().setApplicationContext(applicationContext);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/SpringStatusCheckerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/SpringStatusCheckerTest.java
index 288a0fb3fd..d7e1a6d5c3 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/SpringStatusCheckerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/status/SpringStatusCheckerTest.java
@@ -18,12 +18,11 @@ package org.apache.dubbo.config.spring.status;
 
 import org.apache.dubbo.common.status.Status;
 import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import org.mockito.Mock;
 import org.mockito.Mockito;
@@ -52,7 +51,7 @@ public class SpringStatusCheckerTest {
 
     @AfterEach
     public void tearDown() throws Exception {
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
         Mockito.reset(applicationContext);
     }
 
@@ -65,7 +64,7 @@ public class SpringStatusCheckerTest {
 
     @Test
     public void testWithLifeCycleRunning() {
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
         ApplicationLifeCycle applicationLifeCycle = mock(ApplicationLifeCycle.class);
         new ServiceBean().setApplicationContext(applicationLifeCycle);
         given(applicationLifeCycle.getConfigLocations()).willReturn(new String[]{"test1", "test2"});
@@ -79,7 +78,7 @@ public class SpringStatusCheckerTest {
 
     @Test
     public void testWithoutLifeCycleRunning() {
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
         ApplicationLifeCycle applicationLifeCycle = mock(ApplicationLifeCycle.class);
         new ServiceBean().setApplicationContext(applicationLifeCycle);
         given(applicationLifeCycle.isRunning()).willReturn(false);
@@ -95,9 +94,9 @@ public class SpringStatusCheckerTest {
 
     @Test
     public void testGenericWebApplicationContext() {
-        SpringExtensionFactory.clearContexts();
+        SpringExtensionInjector.clearContexts();
         GenericWebApplicationContext context = new GenericWebApplicationContext();
-        SpringExtensionFactory.addApplicationContext(context);
+        SpringExtensionInjector.addApplicationContext(context);
         SpringStatusChecker checker = new SpringStatusChecker();
         Status status = checker.check();
         Assertions.assertEquals(Status.Level.UNKNOWN, status.getLevel());
diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/src/main/resources/META-INF/native-image/reflect-config.json b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/src/main/resources/META-INF/native-image/reflect-config.json
index 2aeba373cf..e558b5d420 100644
--- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/src/main/resources/META-INF/native-image/reflect-config.json
+++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-consumer/src/main/resources/META-INF/native-image/reflect-config.json
@@ -340,11 +340,11 @@
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
-  "name":"org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory",
+  "name":"org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector",
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
-  "name":"org.apache.dubbo.common.extension.factory.SpiExtensionFactory",
+  "name":"org.apache.dubbo.common.extension.inject.SpiExtensionInjector",
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
diff --git a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/src/main/resources/META-INF/native-image/reflect-config.json b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/src/main/resources/META-INF/native-image/reflect-config.json
index f78191ae12..8ec44e31c5 100644
--- a/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/src/main/resources/META-INF/native-image/reflect-config.json
+++ b/dubbo-demo/dubbo-demo-native/dubbo-demo-native-provider/src/main/resources/META-INF/native-image/reflect-config.json
@@ -442,11 +442,11 @@
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
-  "name":"org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory",
+  "name":"org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector",
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
-  "name":"org.apache.dubbo.common.extension.factory.SpiExtensionFactory",
+  "name":"org.apache.dubbo.common.extension.inject.SpiExtensionInjector",
   "methods":[{"name":"","parameterTypes":[] }]
 },
 {
diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml
index ef5db1cec9..3fd09339de 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -462,7 +462,7 @@
                                 
                                     
-                                        META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
+                                        META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
                                     
                                 
                                 
                                     
-                                        META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
+                                        META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionInjector
                                     
                                 
                                  cachedServices = WritableMetadataService.getDefaultExtension().getCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL));
+            Set cachedServices = metadataService.getCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL));
             if(!isEmpty(cachedServices)) {
                 subscribedServices.addAll(cachedServices);
             }
@@ -71,7 +81,7 @@ public abstract class AbstractServiceNameMapping implements ServiceNameMapping {
             Set mappedServices = get(subscribedURL);
             logger.info(subscribedURL.getServiceInterface() + " mapping to " + mappedServices + " instructed by remote metadata center.");
             subscribedServices.addAll(mappedServices);
-            WritableMetadataService.getDefaultExtension().putCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL), subscribedServices);
+            metadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL), subscribedServices);
         }
         return subscribedServices;
     }
@@ -97,7 +107,7 @@ public abstract class AbstractServiceNameMapping implements ServiceNameMapping {
             }
         }
 
-        WritableMetadataService.getDefaultExtension().putCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL), subscribedServices);
+        metadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(subscribedURL), subscribedServices);
 
         return subscribedServices;
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
index ac88d75cc6..8cfa3de8d0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
@@ -23,8 +23,8 @@ public class MetadataConstants {
     public static final String META_DATA_STORE_TAG = ".metaData";
     public static final String SERVICE_META_DATA_STORE_TAG = ".smd";
     public static final String CONSUMER_META_DATA_STORE_TAG = ".cmd";
-    public static final String METADATA_PUBLISH_DELAY_KEY = "dubbo.application.metadata.delay";
+    public static final String METADATA_PUBLISH_DELAY_KEY = "dubbo.application.metadata.publish.delay";
     public static final int DEFAULT_METADATA_PUBLISH_DELAY = 10000;
-    public static final String METADATA_PROXY_TIMEOUT_KEY = "dubbo.application.metadata.delay";
+    public static final String METADATA_PROXY_TIMEOUT_KEY = "dubbo.application.metadata.proxy.delay";
     public static final int DEFAULT_METADATA_TIMEOUT_VALUE = 5000;
 }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
index 34d3b54e3f..82547f3d83 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
@@ -24,6 +24,7 @@ import java.util.List;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
 
 /**
  * The exporter of {@link MetadataService}
@@ -33,7 +34,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
  * @see #unexport()
  * @since 2.7.5
  */
-@SPI(DEFAULT_METADATA_STORAGE_TYPE)
+@SPI(value = DEFAULT_METADATA_STORAGE_TYPE, scope = APPLICATION)
 public interface MetadataServiceExporter extends Prioritized {
 
     /**
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
index 5c233b3fca..96dca1ae9d 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.metadata;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.model.ScopeModel;
 
 import java.util.Arrays;
 import java.util.HashSet;
@@ -27,6 +28,7 @@ import java.util.Set;
 import static java.util.Collections.emptySet;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
 import static org.apache.dubbo.common.utils.StringUtils.SLASH;
 
 /**
@@ -34,7 +36,7 @@ import static org.apache.dubbo.common.utils.StringUtils.SLASH;
  *
  * @since 2.7.5
  */
-@SPI("metadata")
+@SPI(value = "metadata", scope = APPLICATION)
 public interface ServiceNameMapping {
 
     String DEFAULT_MAPPING_GROUP = "mapping";
@@ -53,6 +55,14 @@ public interface ServiceNameMapping {
         return getExtensionLoader(ServiceNameMapping.class).getDefaultExtension();
     }
 
+    static ServiceNameMapping getDefaultExtension(ScopeModel scopeModel) {
+        if (scopeModel != null) {
+            return scopeModel.getDefaultExtension(ServiceNameMapping.class);
+        } else {
+            return getExtensionLoader(ServiceNameMapping.class).getDefaultExtension();
+        }
+    }
+
     static String buildMappingKey(URL url) {
         return buildGroup(url.getServiceInterface());
     }
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 1dddfc2a2e..bd77ec5203 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,31 +18,22 @@ 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;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.Map;
 import java.util.Set;
 
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
-
 /**
  * Local {@link MetadataService} that extends {@link MetadataService} and provides the modification, which is used for
  * Dubbo's consumers and providers.
  *
  * @since 2.7.5
  */
-@SPI("default")
+@SPI(value = "default", scope = ExtensionScope.APPLICATION)
 public interface WritableMetadataService extends MetadataService {
-    /**
-     * Gets the current Dubbo Service name
-     *
-     * @return non-null
-     */
-    @Override
-    default String serviceName() {
-        return ApplicationModel.getName();
-    }
 
     /**
      * Exports a {@link URL}
@@ -103,7 +94,7 @@ public interface WritableMetadataService extends MetadataService {
      *
      * @return non-null
      */
-    static WritableMetadataService getDefaultExtension() {
-        return getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
+    static WritableMetadataService getDefaultExtension(ScopeModel scopeModel) {
+        return ScopeModelUtil.getExtensionLoader(WritableMetadataService.class, scopeModel).getDefaultExtension();
     }
 }
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 08040ee74c..9484ebd4f1 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
@@ -18,7 +18,6 @@ package org.apache.dubbo.metadata.report;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
@@ -36,26 +35,29 @@ 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 metadataReports = new HashMap<>();
+    private final Map 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);
             url = URLBuilder.from(url)
-                .setProtocol(protocol)
-                .removeParameter(METADATA_REPORT_KEY)
-                .build();
+                    .setProtocol(protocol)
+                    .setScopeModel(config.getScopeModel())
+                    .removeParameter(METADATA_REPORT_KEY)
+                    .build();
         }
-        url = url.addParameterIfAbsent(APPLICATION_KEY, ApplicationModel.getApplicationConfig().getName());
+        url = url.addParameterIfAbsent(APPLICATION_KEY, applicationModel.getCurrentConfig().getName());
         String relatedRegistryId = config.getRegistry() == null ? DEFAULT_KEY : config.getRegistry();
-//        RegistryConfig registryConfig = ApplicationModel.getConfigManager().getRegistry(relatedRegistryId)
+//        RegistryConfig registryConfig = applicationModel.getConfigManager().getRegistry(relatedRegistryId)
 //                .orElseThrow(() -> new IllegalStateException("Registry id " + relatedRegistryId + " does not exist."));
         MetadataReport metadataReport = metadataReportFactory.getMetadataReport(url);
         if (metadataReport != null) {
@@ -64,14 +66,14 @@ public class MetadataReportInstance {
         init.set(true);
     }
 
-    public static Map getMetadataReports(boolean checked) {
+    public Map 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) {
@@ -81,14 +83,14 @@ public class MetadataReportInstance {
     }
 
 
-    private static void checkInit() {
+    private void checkInit() {
         if (!init.get()) {
             throw new IllegalStateException("the metadata report was not initialized.");
         }
     }
 
     public static void reset() {
-        metadataReports.clear();
-        init.set(false);
+//        metadataReports.clear();
+//        init.set(false);
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/ServiceNameMappingTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/ServiceNameMappingTest.java
index 709dc18a12..7a03cd49e0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/ServiceNameMappingTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/ServiceNameMappingTest.java
@@ -64,13 +64,13 @@ public class ServiceNameMappingTest {
 
         applicationName = getClass().getSimpleName();
 
-        ApplicationModel.getConfigManager().setApplication(new ApplicationConfig(applicationName));
+        ApplicationModel.defaultModel().getConfigManager().setApplication(new ApplicationConfig(applicationName));
 
         configuration = new FileSystemDynamicConfiguration();
 
         FileUtils.deleteQuietly(configuration.getRootDirectory());
 
-        ApplicationModel.getEnvironment().setDynamicConfiguration(configuration);
+        ApplicationModel.defaultModel().getEnvironment().setDynamicConfiguration(configuration);
 
         serviceNameMapping = getDefaultExtension();
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
index 37b0d3c173..1d7ae6cffe 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportTest.java
@@ -73,7 +73,7 @@ public class AbstractMetadataReportTest {
         URL url = URL.valueOf("zookeeper://" + NetUtils.getLocalAddress().getHostName() + ":4444/org.apache.dubbo.TestService?version=1.0.0&application=vic");
         abstractMetadataReport = new NewMetadataReport(url);
         // set the simple name of current class as the application name
-        ApplicationModel.getConfigManager().setApplication(new ApplicationConfig(getClass().getSimpleName()));
+        ApplicationModel.defaultModel().getConfigManager().setApplication(new ApplicationConfig(getClass().getSimpleName()));
     }
 
     @AfterEach
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 4015339435..c2cce61328 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;
@@ -30,6 +31,8 @@ import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 import org.apache.dubbo.rpc.support.RpcUtils;
 
 import com.alibaba.fastjson.JSON;
@@ -67,12 +70,19 @@ 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, ScopeModelAware {
 
     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;
+    private ApplicationModel applicationModel;
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
 
     @Override
     public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
@@ -80,7 +90,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 +186,7 @@ public class MetricsFilter implements Filter {
     }
 
     private List getThreadPoolMessage() {
-        DataStore dataStore = ExtensionLoader.getExtensionLoader(DataStore.class).getDefaultExtension();
+        DataStore dataStore = extensionAccessor.getExtensionLoader(DataStore.class).getDefaultExtension();
         Map executors = dataStore.get(EXECUTOR_SERVICE_COMPONENT_KEY);
 
         List threadPoolMtricList = new ArrayList<>();
@@ -241,7 +251,7 @@ public class MetricsFilter implements Filter {
 
             @Override
             public URL getUrl() {
-                return URL.valueOf(protocolName + "://" + NetUtils.getIpByConfig() + ":" + port + "/" + MetricsService.class.getName());
+                return URL.valueOf(protocolName + "://" + NetUtils.getIpByConfig(applicationModel) + ":" + port + "/" + MetricsService.class.getName());
             }
 
             @Override
@@ -257,4 +267,9 @@ public class MetricsFilter implements Filter {
 
         return metricsInvoker;
     }
+
+    @Override
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
 }
diff --git a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java
index 29bb5351c7..3ecad0c567 100644
--- a/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java
+++ b/dubbo-monitor/dubbo-monitor-default/src/test/java/org/apache/dubbo/monitor/dubbo/MetricsFilterTest.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
 
 import com.alibaba.metrics.FastCompass;
@@ -139,6 +140,7 @@ public class MetricsFilterTest {
         IMetricManager metricManager = MetricManager.getIMetricManager();
         metricManager.clear();
         MetricsFilter metricsFilter = new MetricsFilter();
+        metricsFilter.setExtensionAccessor(ApplicationModel.defaultModel());
         Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), "", new Class[]{Integer.class}, new Object[0]);
         RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), port).setLocalAddress(NetUtils.getLocalHost(), 2345);
         URL url = getUrl().addParameter(SIDE_KEY, CONSUMER_SIDE);
@@ -167,6 +169,7 @@ public class MetricsFilterTest {
         IMetricManager metricManager = MetricManager.getIMetricManager();
         metricManager.clear();
         MetricsFilter metricsFilter = new MetricsFilter();
+        metricsFilter.setExtensionAccessor(ApplicationModel.defaultModel());
         Invocation invocation = new RpcInvocation("timeoutException", DemoService.class.getName(), "", null, null);
         RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), port).setLocalAddress(NetUtils.getLocalHost(), 2345);
         URL url = getUrl().addParameter(SIDE_KEY, CONSUMER_SIDE)
@@ -198,6 +201,7 @@ public class MetricsFilterTest {
         IMetricManager metricManager = MetricManager.getIMetricManager();
         metricManager.clear();
         MetricsFilter metricsFilter = new MetricsFilter();
+        metricsFilter.setExtensionAccessor(ApplicationModel.defaultModel());
         Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), "", new Class[0], new Object[0]);
         RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), port).setLocalAddress(NetUtils.getLocalHost(), 2345);
         URL url = getUrl().addParameter(SIDE_KEY, PROVIDER)
@@ -226,6 +230,7 @@ public class MetricsFilterTest {
         IMetricManager metricManager = MetricManager.getIMetricManager();
         metricManager.clear();
         MetricsFilter metricsFilter = new MetricsFilter();
+        metricsFilter.setExtensionAccessor(ApplicationModel.defaultModel());
         Invocation invocation = new RpcInvocation("sayName", DemoService.class.getName(), "", new Class[0], new Object[0]);
         RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), port).setLocalAddress(NetUtils.getLocalHost(), 2345);
         URL url = getUrl().addParameter(SIDE_KEY, PROVIDER)
@@ -274,6 +279,7 @@ public class MetricsFilterTest {
         IMetricManager metricManager = MetricManager.getIMetricManager();
         metricManager.clear();
         MetricsFilter metricsFilter = new MetricsFilter();
+        metricsFilter.setExtensionAccessor(ApplicationModel.defaultModel());
         Invocation sayNameInvocation = new RpcInvocation("sayName", DemoService.class.getName(), "", new Class[0], new Object[0]);
         Invocation echoInvocation = new RpcInvocation("echo", DemoService.class.getName(), "", new Class[]{Integer.class}, new Integer[]{1});
         RpcContext.getServiceContext().setRemoteAddress(NetUtils.getLocalHost(), port).setLocalAddress(NetUtils.getLocalHost(), 2345);
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
index 85c4321925..d194f51e9d 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOffline.java
@@ -34,7 +34,7 @@ import java.util.List;
 public class BaseOffline implements BaseCommand {
     private Logger logger = LoggerFactory.getLogger(OfflineInterface.class);
     public static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    public static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+    public static ServiceRepository serviceRepository = ApplicationModel.defaultModel().getApplicationServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
index cf01ff1b11..350f5397ef 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/BaseOnline.java
@@ -35,7 +35,7 @@ import java.util.List;
 public class BaseOnline implements BaseCommand {
     private static final Logger logger = LoggerFactory.getLogger(Online.class);
     public static RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
-    public static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+    public static ServiceRepository serviceRepository = ApplicationModel.defaultModel().getApplicationServiceRepository();
 
     @Override
     public String execute(CommandContext commandContext, String[] args) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/InvokeTelnet.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/InvokeTelnet.java
index 77908458f6..64c5c15d3f 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/InvokeTelnet.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/InvokeTelnet.java
@@ -87,7 +87,7 @@ public class InvokeTelnet implements BaseCommand {
             selectedProvider = channel.attr(INVOKE_METHOD_PROVIDER_KEY).get();
             invokeMethod = channel.attr(SelectTelnet.SELECT_METHOD_KEY).get();
         } else {
-            for (ProviderModel provider : ApplicationModel.allProviderModels()) {
+            for (ProviderModel provider : ApplicationModel.defaultModel().allProviderModels()) {
                 if (!isServiceMatch(service, provider)) {
                     continue;
                 }
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Live.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Live.java
index d355845d12..696c3a1af2 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Live.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Live.java
@@ -33,7 +33,7 @@ public class Live implements BaseCommand {
     @Override
     public String execute(CommandContext commandContext, String[] args) {
         URL url = URL.valueOf("application://")
-                .addParameter(CommonConstants.QOS_LIVE_PROBE_EXTENSION, ApplicationModel.getApplicationConfig().getLivenessProbe());
+                .addParameter(CommonConstants.QOS_LIVE_PROBE_EXTENSION, ApplicationModel.defaultModel().getCurrentConfig().getLivenessProbe());
         List livenessProbes = ExtensionLoader.getExtensionLoader(LivenessProbe.class)
                 .getActivateExtension(url, CommonConstants.QOS_LIVE_PROBE_EXTENSION);
         if (!livenessProbes.isEmpty()) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
index 99dad44bb6..314a000697 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ls.java
@@ -43,7 +43,7 @@ public class Ls implements BaseCommand {
     public String listProvider() {
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append("As Provider side:" + System.lineSeparator());
-        Collection providerModelList = ApplicationModel.allProviderModels();
+        Collection providerModelList = ApplicationModel.defaultModel().allProviderModels();
 
         TTable tTable = new TTable(new TTable.ColumnDefine[]{
                 new TTable.ColumnDefine(TTable.Align.MIDDLE),
@@ -65,7 +65,7 @@ public class Ls implements BaseCommand {
     public String listConsumer() {
         StringBuilder stringBuilder = new StringBuilder();
         stringBuilder.append("As Consumer side:" + System.lineSeparator());
-        Collection consumerModelList = ApplicationModel.allConsumerModels();
+        Collection consumerModelList = ApplicationModel.defaultModel().allConsumerModels();
 
         TTable tTable = new TTable(new TTable.ColumnDefine[]{
                 new TTable.ColumnDefine(TTable.Align.MIDDLE),
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java
index 109adbc2d8..44bc789330 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Ready.java
@@ -33,7 +33,7 @@ public class Ready implements BaseCommand {
     @Override
     public String execute(CommandContext commandContext, String[] args) {
         URL url = URL.valueOf("application://")
-                .addParameter(CommonConstants.QOS_READY_PROBE_EXTENSION, ApplicationModel.getApplicationConfig().getReadinessProbe());
+                .addParameter(CommonConstants.QOS_READY_PROBE_EXTENSION, ApplicationModel.defaultModel().getCurrentConfig().getReadinessProbe());
         List readinessProbes = ExtensionLoader.getExtensionLoader(ReadinessProbe.class)
                 .getActivateExtension(url, CommonConstants.QOS_READY_PROBE_EXTENSION);
         if (!readinessProbes.isEmpty()) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Startup.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Startup.java
index e9a5b54bc6..2c9fed2254 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Startup.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/command/impl/Startup.java
@@ -33,7 +33,7 @@ public class Startup implements BaseCommand {
     @Override
     public String execute(CommandContext commandContext, String[] args) {
         URL url = URL.valueOf("application://")
-                .addParameter(CommonConstants.QOS_STARTUP_PROBE_EXTENSION, ApplicationModel.getApplicationConfig().getStartupProbe());
+                .addParameter(CommonConstants.QOS_STARTUP_PROBE_EXTENSION, ApplicationModel.defaultModel().getCurrentConfig().getStartupProbe());
         List startupProbes = ExtensionLoader.getExtensionLoader(StartupProbe.class)
                 .getActivateExtension(url, CommonConstants.QOS_STARTUP_PROBE_EXTENSION);
         if (!startupProbes.isEmpty()) {
diff --git a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/probe/impl/ProviderReadinessProbe.java b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/probe/impl/ProviderReadinessProbe.java
index 58251075fe..25ed890146 100644
--- a/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/probe/impl/ProviderReadinessProbe.java
+++ b/dubbo-plugin/dubbo-qos/src/main/java/org/apache/dubbo/qos/probe/impl/ProviderReadinessProbe.java
@@ -27,7 +27,7 @@ import java.util.List;
 
 @Activate
 public class ProviderReadinessProbe implements ReadinessProbe {
-    private static ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+    private static ServiceRepository serviceRepository = ApplicationModel.defaultModel().getApplicationServiceRepository();
 
     @Override
     public boolean check() {
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/InvokeTelnetTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/InvokeTelnetTest.java
index a842b4bd01..59eef2c59a 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/InvokeTelnetTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/InvokeTelnetTest.java
@@ -46,7 +46,7 @@ public class InvokeTelnetTest {
     private Channel mockChannel;
     private CommandContext mockCommandContext;
     private final DefaultAttributeMap defaultAttributeMap = new DefaultAttributeMap();
-    private final ServiceRepository repository = ApplicationModel.getServiceRepository();
+    private ServiceRepository repository;
 
     @BeforeEach
     public void setup() {
@@ -54,6 +54,7 @@ public class InvokeTelnetTest {
         mockChannel = mock(Channel.class);
         mockCommandContext = mock(CommandContext.class);
         given(mockCommandContext.getRemote()).willReturn(mockChannel);
+        repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
     }
 
     @AfterEach
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
index 414f3084e5..2bae3d3cf2 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/LsTest.java
@@ -52,7 +52,7 @@
 //        when(providerUrl.toFullString()).thenReturn("dubbo://localhost:8888/org.apache.dubbo.BarService");
 //        when(providerInvoker.getUrl()).thenReturn(providerUrl);
 //        ApplicationModel.registerProviderInvoker(providerInvoker, registryUrl, providerUrl);
-//        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
+//        for (ProviderInvokerWrapper wrapper : ApplicationModel.defaultModel().getProviderInvokers("org.apache.dubbo.BarService")) {
 //            wrapper.setReg(true);
 //        }
 //
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
index 251d67207b..cdda67770b 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OfflineTest.java
@@ -47,7 +47,7 @@
 //        when(providerUrl.toFullString()).thenReturn("dubbo://localhost:8888/org.apache.dubbo.BarService");
 //        when(providerInvoker.getUrl()).thenReturn(providerUrl);
 //        ApplicationModel.registerProviderInvoker(providerInvoker, registryUrl, providerUrl);
-//        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
+//        for (ProviderInvokerWrapper wrapper : ApplicationModel.defaultModel().getProviderInvokers("org.apache.dubbo.BarService")) {
 //            wrapper.setReg(true);
 //        }
 //
@@ -58,7 +58,7 @@
 //        String output = offline.execute(mock(CommandContext.class), new String[]{"org.apache.dubbo.BarService"});
 //        assertThat(output, containsString("OK"));
 //        Mockito.verify(registry).unregister(providerUrl);
-//        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
+//        for (ProviderInvokerWrapper wrapper : ApplicationModel.defaultModel().getProviderInvokers("org.apache.dubbo.BarService")) {
 //            assertThat(wrapper.isReg(), is(false));
 //        }
 //
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
index b43ade3e15..ef8a037679 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/OnlineTest.java
@@ -53,7 +53,7 @@
 //        Online online = new Online();
 //        String output = online.execute(mock(CommandContext.class), new String[]{"org.apache.dubbo.BarService"});
 //        assertThat(output, equalTo("OK"));
-//        for (ProviderInvokerWrapper wrapper : ApplicationModel.getProviderInvokers("org.apache.dubbo.BarService")) {
+//        for (ProviderInvokerWrapper wrapper : ApplicationModel.defaultModel().getProviderInvokers("org.apache.dubbo.BarService")) {
 //            assertTrue(wrapper.isReg());
 //        }
 //    }
diff --git a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/SelectTelnetTest.java b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/SelectTelnetTest.java
index 03476eb526..867a0cd599 100644
--- a/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/SelectTelnetTest.java
+++ b/dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/SelectTelnetTest.java
@@ -49,7 +49,7 @@ public class SelectTelnetTest {
     private Channel mockChannel;
     private CommandContext mockCommandContext;
 
-    private final ServiceRepository repository = ApplicationModel.getServiceRepository();
+    private final ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
     private final DefaultAttributeMap defaultAttributeMap = new DefaultAttributeMap();
     private List methods;
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java
index 24011399c7..5707b62088 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactory.java
@@ -20,12 +20,14 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
 import org.apache.dubbo.common.extension.SPI;
 
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
+
 /**
  * RegistryFactory. (SPI, Singleton, ThreadSafe)
  *
  * @see org.apache.dubbo.registry.support.AbstractRegistryFactory
  */
-@SPI("dubbo")
+@SPI(value = "dubbo", scope = APPLICATION)
 public interface RegistryFactory {
 
     /**
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java
index e6b59234e7..483c862447 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java
@@ -17,9 +17,11 @@
 package org.apache.dubbo.registry.client;
 
 import org.apache.dubbo.metadata.MetadataInfo;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import com.alibaba.fastjson.JSON;
 
+import java.beans.Transient;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -27,6 +29,7 @@ import java.util.Objects;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
+import static org.apache.dubbo.common.constants.CommonConstants.SCOPE_MODEL;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.ENDPOINTS;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.EXPORTED_SERVICES_REVISION_PROPERTY_NAME;
 
@@ -59,6 +62,7 @@ public class DefaultServiceInstance implements ServiceInstance {
     private transient String registryCluster; // extendParams can be more flexiable, but one single property uses less space
     private transient Map extendParams;
     private transient List endpoints;
+    private transient Map attributes = new HashMap<>();
 
     public DefaultServiceInstance() {
     }
@@ -75,24 +79,28 @@ public class DefaultServiceInstance implements ServiceInstance {
         this.extendParams = other.extendParams;
         this.endpoints = other.endpoints;
         this.address = null;
+        this.attributes = other.attributes;
     }
 
-    public DefaultServiceInstance(String serviceName, String host, Integer port) {
+    public DefaultServiceInstance(String serviceName, String host, Integer port, ApplicationModel applicationModel) {
         if (port == null || port < 1) {
             throw new IllegalArgumentException("The port value is illegal, the value is " + port);
         }
         this.serviceName = serviceName;
         this.host = host;
         this.port = port;
+        setApplicationModel(applicationModel);
+    }
+
+    public DefaultServiceInstance(String serviceName, ApplicationModel applicationModel) {
+        this.serviceName = serviceName;
+        setApplicationModel(applicationModel);
     }
 
     public void setRawAddress(String rawAddress) {
         this.rawAddress = rawAddress;
     }
 
-    public DefaultServiceInstance(String serviceName) {
-        this.serviceName = serviceName;
-    }
 
     public void setServiceName(String serviceName) {
         this.serviceName = serviceName;
@@ -203,6 +211,22 @@ public class DefaultServiceInstance implements ServiceInstance {
         }
     }
 
+    @Override
+    public Map getAttributes() {
+        return attributes;
+    }
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.attributes.put(SCOPE_MODEL, applicationModel);
+    }
+
+    @Override
+    @Transient
+    public ApplicationModel getApplicationModel() {
+        return (ApplicationModel) this.attributes.get(SCOPE_MODEL);
+    }
+
     public void setMetadata(Map metadata) {
         this.metadata = metadata;
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
index 0898fe714a..a379f04049 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/InstanceAddressURL.java
@@ -22,6 +22,8 @@ import org.apache.dubbo.common.url.component.URLParam;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
 import org.apache.dubbo.rpc.RpcContext;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -403,6 +405,16 @@ public class InstanceAddressURL extends URL {
         return this.instance.getMetadata();
     }
 
+    @Override
+    public ScopeModel getScopeModel() {
+        return RpcContext.getServiceContext().getConsumerUrl().getScopeModel();
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return RpcContext.getServiceContext().getConsumerUrl().getServiceModel();
+    }
+
     @Override
     public boolean equals(Object obj) {
         // instance metadata equals
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/RegistryClusterIdentifier.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/RegistryClusterIdentifier.java
index 9d0e4a0c06..f6132eac05 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/RegistryClusterIdentifier.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/RegistryClusterIdentifier.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.registry.client;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUSTER_TYPE_KEY;
 
@@ -30,7 +31,7 @@ public interface RegistryClusterIdentifier {
 
     static RegistryClusterIdentifier getExtension(URL url) {
         ExtensionLoader loader
-                = ExtensionLoader.getExtensionLoader(RegistryClusterIdentifier.class);
+                = ScopeModelUtil.getExtensionLoader(RegistryClusterIdentifier.class, url.getScopeModel());
         return loader.getExtension(url.getParameter(REGISTRY_CLUSTER_TYPE_KEY, "default"));
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/SelfHostMetaServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/SelfHostMetaServiceDiscovery.java
index 43bb16777f..30fc1d815a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/SelfHostMetaServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/SelfHostMetaServiceDiscovery.java
@@ -33,6 +33,8 @@ import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedLi
 import org.apache.dubbo.registry.client.metadata.MetadataUtils;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import com.alibaba.fastjson.JSONObject;
 
@@ -47,7 +49,7 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 
-public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
+public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery, ScopeModelAware {
 
     private volatile boolean isDestroy;
 
@@ -96,6 +98,15 @@ public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
      * Value - a revision calculate from {@link List} of {@link ServiceInstance}
      */
     private final ConcurrentHashMap serviceInstanceRevisionMap = new ConcurrentHashMap<>();
+    private ApplicationModel applicationModel;
+    private WritableMetadataService metadataService;
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        metadataService = WritableMetadataService.getDefaultExtension(applicationModel);
+
+    }
 
     @Override
     public void initialize(URL registryURL) throws Exception {
@@ -106,7 +117,6 @@ public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
         // Echo check: test if consumer is offline, remove MetadataChangeListener,
         // reduce the probability of failure when metadata update
         echoCheckExecutor.scheduleAtFixedRate(() -> {
-            WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
             Map listenerMap = metadataService.getInstanceMetadataChangedListenerMap();
             Iterator> iterator = listenerMap.entrySet().iterator();
 
@@ -139,7 +149,6 @@ public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
     }
 
     private void updateMetadata(ServiceInstance serviceInstance) {
-        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
         String metadataString = JSONObject.toJSONString(serviceInstance.getMetadata());
         String metadataRevision = RevisionResolver.calRevision(metadataString);
 
@@ -196,7 +205,6 @@ public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
         this.serviceInstance = null;
 
         // notify empty message to consumer
-        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
         metadataService.exportInstanceMetadata("");
         metadataService.getInstanceMetadataChangedListenerMap().forEach((consumerId, listener) -> listener.onEvent(""));
         metadataService.getInstanceMetadataChangedListenerMap().clear();
@@ -225,7 +233,7 @@ public abstract class SelfHostMetaServiceDiscovery implements ServiceDiscovery {
             // refer from MetadataUtils, this proxy is different from the one used to refer exportedURL
             MetadataService metadataService = MetadataUtils.getMetadataServiceProxy(serviceInstance);
 
-            String consumerId = ApplicationModel.getName() + NetUtils.getLocalHost();
+            String consumerId = ScopeModelUtil.getApplicationModel(registryURL.getScopeModel()).getApplicationName() + NetUtils.getLocalHost();
             String metadata = metadataService.getAndListenInstanceMetadata(
                     consumerId, metadataString -> {
                         if(logger.isDebugEnabled()) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
index d97f66b89a..5569835a2d 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscovery.java
@@ -35,13 +35,14 @@ import java.util.stream.Stream;
 import static java.util.Collections.unmodifiableList;
 import static java.util.Collections.unmodifiableMap;
 import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_DELAY_NOTIFICATION_KEY;
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
 
 /**
  * The common operations of Service Discovery
  *
  * @since 2.7.5
  */
-@SPI("zookeeper")
+@SPI(value = "zookeeper", scope = APPLICATION)
 public interface ServiceDiscovery extends Prioritized {
 
     // ==================================== Lifecycle ==================================== //
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index 5d3f3c8f71..cfcb3a851a 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -87,7 +87,7 @@ public class ServiceDiscoveryRegistry implements Registry {
     public ServiceDiscoveryRegistry(URL registryURL) {
         this.registryURL = registryURL;
         this.serviceDiscovery = createServiceDiscovery(registryURL);
-        this.writableMetadataService = WritableMetadataService.getDefaultExtension();
+        this.writableMetadataService = WritableMetadataService.getDefaultExtension(registryURL.getScopeModel());
     }
 
     // Currently for test purpose
@@ -208,7 +208,7 @@ public class ServiceDiscoveryRegistry implements Registry {
 
         Set subscribedServices = Collections.emptySet();
         try {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(registryURL.getScopeModel());
             subscribedServices = serviceNameMapping.getAndListenServices(registryURL, url, new DefaultMappingListener(url, subscribedServices, listener));
         } catch (Exception e) {
             logger.warn("Cannot find app mapping for service " + url.getServiceInterface() + ", will not migrate.", e);
@@ -369,14 +369,14 @@ public class ServiceDiscoveryRegistry implements Registry {
             }
 
             if (CollectionUtils.isEmpty(tempOldApps) && newApps.size() > 0) {
-                WritableMetadataService.getDefaultExtension().putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps);
+                writableMetadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps);
                 subscribeURLs(url, listener, newApps);
                 return;
             }
 
             for (String newAppName : newApps) {
                 if (!tempOldApps.contains(newAppName)) {
-                    WritableMetadataService.getDefaultExtension().putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps);
+                    writableMetadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(url), newApps);
                     subscribeURLs(url, listener, newApps);
                     return;
                 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
index 5792693be8..6e125198ef 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java
@@ -50,6 +50,7 @@ import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
 import static org.apache.dubbo.registry.Constants.CONFIGURATORS_SUFFIX;
+import static org.apache.dubbo.rpc.model.ScopeModelUtil.getApplicationModel;
 
 public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
     private static final Logger logger = LoggerFactory.getLogger(ServiceDiscoveryRegistryDirectory.class);
@@ -59,15 +60,19 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
      * The initial value is null and the midway may be assigned to null, please use the local variable reference
      */
     private volatile Map> urlInvokerMap;
-    private final static ConsumerConfigurationListener CONSUMER_CONFIGURATION_LISTENER = new ConsumerConfigurationListener();
+    private final ConsumerConfigurationListener consumerConfigurationListener;
     private volatile ReferenceConfigurationListener referenceConfigurationListener;
     private volatile boolean enableConfigurationListen = true;
     private volatile List originalUrls = null;
     private volatile Map overrideQueryMap;
     private volatile Map consumerFirstQueryMap;
+    private final ApplicationModel applicationModel;
 
     public ServiceDiscoveryRegistryDirectory(Class serviceType, URL url) {
         super(serviceType, url);
+        applicationModel = getApplicationModel(url.getScopeModel());
+        consumerConfigurationListener = new ConsumerConfigurationListener(applicationModel);
+
         Set providerFirstParams = ExtensionLoader.getExtensionLoader(ProviderFirstParams.class).getSupportedExtensionInstances();
         if (CollectionUtils.isEmpty(providerFirstParams)) {
             consumerFirstQueryMap = queryMap;
@@ -82,14 +87,15 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
                 }
             }
         }
+
     }
 
     @Override
     public void subscribe(URL url) {
-        if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
+        if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
             enableConfigurationListen = true;
-            CONSUMER_CONFIGURATION_LISTENER.addNotifyListener(this);
-            referenceConfigurationListener = new ReferenceConfigurationListener(this, url);
+            consumerConfigurationListener.addNotifyListener(this);
+            referenceConfigurationListener = new ReferenceConfigurationListener(this.applicationModel, this, url);
         } else {
             enableConfigurationListen = false;
         }
@@ -100,8 +106,8 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
     public void unSubscribe(URL url) {
         super.unSubscribe(url);
         this.originalUrls = null;
-        if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
-            CONSUMER_CONFIGURATION_LISTENER.removeNotifyListener(this);
+        if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
+            consumerConfigurationListener.removeNotifyListener(this);
             referenceConfigurationListener.stop();
         }
     }
@@ -160,7 +166,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
     private void overrideDirectoryUrl() {
         // merge override parameters
         this.overrideDirectoryUrl = directoryUrl;
-        List localAppDynamicConfigurators = CONSUMER_CONFIGURATION_LISTENER.getConfigurators(); // local reference
+        List localAppDynamicConfigurators = consumerConfigurationListener.getConfigurators(); // local reference
         doOverrideUrl(localAppDynamicConfigurators);
         if (referenceConfigurationListener != null) {
             List localDynamicConfigurators = referenceConfigurationListener.getConfigurators(); // local reference
@@ -181,7 +187,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
 
     private InstanceAddressURL overrideWithConfigurator(InstanceAddressURL providerUrl) {
         // override url with configurator from "app-name.configurators"
-        providerUrl = overrideWithConfigurators(CONSUMER_CONFIGURATION_LISTENER.getConfigurators(), providerUrl);
+        providerUrl = overrideWithConfigurators(consumerConfigurationListener.getConfigurators(), providerUrl);
 
         // override url with configurator from configurators from "service-name.configurators"
         if (referenceConfigurationListener != null) {
@@ -404,11 +410,12 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
         logger.info(oldUrlInvokerMap.size() + " deprecated invokers deleted.");
     }
 
-    private static class ReferenceConfigurationListener extends AbstractConfiguratorListener {
+    private class ReferenceConfigurationListener extends AbstractConfiguratorListener {
         private final ServiceDiscoveryRegistryDirectory directory;
         private final URL url;
 
-        ReferenceConfigurationListener(ServiceDiscoveryRegistryDirectory directory, URL url) {
+        ReferenceConfigurationListener(ApplicationModel applicationModel, ServiceDiscoveryRegistryDirectory directory, URL url) {
+            super(applicationModel);
             this.directory = directory;
             this.url = url;
             this.initWith(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX);
@@ -430,15 +437,16 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
         }
     }
 
-    private static class ConsumerConfigurationListener extends AbstractConfiguratorListener {
+    private class ConsumerConfigurationListener extends AbstractConfiguratorListener {
         private final List> listeners = new ArrayList<>();
 
-        ConsumerConfigurationListener() {
+        ConsumerConfigurationListener(ApplicationModel applicationModel) {
+            super(applicationModel);
         }
 
         void addNotifyListener(ServiceDiscoveryRegistryDirectory listener) {
             if (listeners.size() == 0) {
-                this.initWith(ApplicationModel.getApplication() + CONFIGURATORS_SUFFIX);
+                this.initWith(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX);
             }
             this.listeners.add(listener);
         }
@@ -446,7 +454,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory {
         void removeNotifyListener(ServiceDiscoveryRegistryDirectory listener) {
             this.listeners.remove(listener);
             if (listeners.size() == 0) {
-                this.stopListen(ApplicationModel.getApplication() + CONFIGURATORS_SUFFIX);
+                this.stopListen(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX);
             }
         }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
index 4b05749218..ff8c0be581 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import java.io.Serializable;
 import java.util.Map;
 import java.util.SortedMap;
@@ -88,6 +90,12 @@ public interface ServiceInstance extends Serializable {
 
     Map getAllParams();
 
+    Map getAttributes();
+
+    void setApplicationModel(ApplicationModel applicationModel);
+
+    ApplicationModel getApplicationModel();
+
     /**
      * Get the value of metadata by the specified name
      *
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
index 99cffc122e..e91b1660c3 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstanceCustomizer.java
@@ -19,13 +19,15 @@ package org.apache.dubbo.registry.client;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.lang.Prioritized;
 
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
+
 /**
  * The interface to customize {@link ServiceInstance the service instance}
  *
  * @see ServiceInstance#getMetadata()
  * @since 2.7.5
  */
-@SPI
+@SPI(scope = APPLICATION)
 public interface ServiceInstanceCustomizer extends Prioritized {
 
     /**
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
index f3fdd54e0c..158634897c 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java
@@ -335,7 +335,7 @@ public class ServiceInstancesChangedListener {
                 logger.debug("Instance " + instance.getAddress() + " is using metadata type " + metadataType);
             }
             if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
-                RemoteMetadataServiceImpl remoteMetadataService = MetadataUtils.getRemoteMetadataService();
+                RemoteMetadataServiceImpl remoteMetadataService = MetadataUtils.getRemoteMetadataService(instance.getApplicationModel());
                 metadataInfo = remoteMetadataService.getMetadata(instance);
             } else {
                 // change the instance used to communicate to avoid all requests route to the same instance
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 018d665562..a0735bf8b9 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.List;
@@ -36,50 +37,54 @@ import java.util.Set;
 
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
-import static org.apache.dubbo.rpc.model.ApplicationModel.getName;
 
-public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
+public class MetadataServiceNameMapping extends AbstractServiceNameMapping implements ScopeModelAware {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     private static final List IGNORED_SERVICE_INTERFACES = Collections.singletonList(MetadataService.class.getName());
 
     private static final int CAS_RETRY_TIMES = 6;
+    protected MetadataReportInstance metadataReportInstance;
+
+    public MetadataServiceNameMapping() {
+        metadataReportInstance = ApplicationModel.defaultModel().getBeanFactory().getBean(MetadataReportInstance.class);
+    }
 
     @Override
     public boolean map(URL url) {
-        if (CollectionUtils.isEmpty(ApplicationModel.getConfigManager().getMetadataConfigs())) {
-            return false;
-        }
-        String serviceInterface = url.getServiceInterface();
-        if (IGNORED_SERVICE_INTERFACES.contains(serviceInterface)) {
-            return false;
-        }
-        String registryCluster = getRegistryCluster(url);
-        MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
-
-        if (metadataReport.registerServiceAppMapping(serviceInterface, getName(), url)) {
-            // MetadataReport support directly register service-app mapping
-            return true;
-        }
-
-        int currentRetryTimes = 1;
-        boolean succeeded = false;
-        String newConfigContent = getName();
-        do {
-            ConfigItem configItem = metadataReport.getConfigItem(serviceInterface, DEFAULT_MAPPING_GROUP);
-            String oldConfigContent = configItem.getContent();
-            if (StringUtils.isNotEmpty(oldConfigContent)) {
-                boolean contains = StringUtils.isContains(oldConfigContent, getName());
-                if (contains) {
-                    break;
-                }
-                newConfigContent = oldConfigContent + COMMA_SEPARATOR + getName();
+            if (CollectionUtils.isEmpty(applicationModel.getApplicationConfigManager().getMetadataConfigs())) {
+                return false;
             }
-            succeeded = metadataReport.registerServiceAppMapping(serviceInterface, DEFAULT_MAPPING_GROUP, newConfigContent, configItem.getTicket());
-        } while (!succeeded && currentRetryTimes++ <= CAS_RETRY_TIMES);
+            String serviceInterface = url.getServiceInterface();
+            if (IGNORED_SERVICE_INTERFACES.contains(serviceInterface)) {
+                return false;
+            }
+            String registryCluster = getRegistryCluster(url);
+            MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
 
-        if (!succeeded) {
+            String appName = applicationModel.getApplicationName();
+            if (metadataReport.registerServiceAppMapping(serviceInterface, appName, url)) {
+                // MetadataReport support directly register service-app mapping
+                return true;
+            }
+
+            int currentRetryTimes = 1;
+            boolean succeeded = false;
+            String newConfigContent = appName;
+            do {
+                ConfigItem configItem = metadataReport.getConfigItem(serviceInterface, DEFAULT_MAPPING_GROUP);
+                String oldConfigContent = configItem.getContent();
+                if (StringUtils.isNotEmpty(oldConfigContent)) {
+                    boolean contains = StringUtils.isContains(oldConfigContent, appName);
+                    if (contains) {
+                        break;
+                    }
+                    newConfigContent = oldConfigContent + COMMA_SEPARATOR + appName;
+                }
+                succeeded = metadataReport.registerServiceAppMapping(serviceInterface, DEFAULT_MAPPING_GROUP, newConfigContent, configItem.getTicket());
+            } while (!succeeded && currentRetryTimes++ <= CAS_RETRY_TIMES);
+            if (!succeeded) {
             throw new RuntimeException();
         }
 
@@ -90,7 +95,7 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
     public Set get(URL url) {
         String serviceInterface = url.getServiceInterface();
         String registryCluster = getRegistryCluster(url);
-        MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
+        MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
         return metadataReport.getServiceAppMapping(serviceInterface, url);
     }
 
@@ -98,10 +103,16 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping {
     public Set getAndListen(URL url, MappingListener mappingListener) {
         String serviceInterface = url.getServiceInterface();
         String registryCluster = getRegistryCluster(url);
-        MetadataReport metadataReport = MetadataReportInstance.getMetadataReport(registryCluster);
+        MetadataReport metadataReport = metadataReportInstance.getMetadataReport(registryCluster);
         return metadataReport.getServiceAppMapping(serviceInterface, mappingListener, url);
     }
 
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        super.setApplicationModel(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/MetadataServiceURLParamsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
index 2d7cb63fc0..d584c74855 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLParamsMetadataCustomizer.java
@@ -23,7 +23,6 @@ import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
 import java.util.Map;
 
 import static org.apache.dubbo.common.utils.StringUtils.isBlank;
-import static org.apache.dubbo.metadata.WritableMetadataService.getDefaultExtension;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.METADATA_SERVICE_URL_PARAMS_PROPERTY_NAME;
 import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.getMetadataServiceParameter;
 
@@ -50,7 +49,7 @@ public class MetadataServiceURLParamsMetadataCustomizer implements ServiceInstan
     }
 
     private String resolveMetadataPropertyValue(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(serviceInstance.getApplicationModel());
         return getMetadataServiceParameter(writableMetadataService.getMetadataServiceURL());
     }
 }
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 57d0a35059..ec53332572 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
@@ -27,6 +27,8 @@ import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.List;
 import java.util.Map;
@@ -39,8 +41,6 @@ import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
 
 public class MetadataUtils {
 
-    private static final Object REMOTE_LOCK = new Object();
-
     public static ConcurrentMap metadataServiceProxies = new ConcurrentHashMap<>();
 
     public static ConcurrentMap> metadataServiceInvokers = new ConcurrentHashMap<>();
@@ -49,34 +49,16 @@ public class MetadataUtils {
 
     private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
 
-    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());
-                }
-            }
-        }
-        return remoteMetadataService;
+    public static RemoteMetadataServiceImpl getRemoteMetadataService(ScopeModel scopeModel) {
+        return scopeModel.getBeanFactory().getBean(RemoteMetadataServiceImpl.class);
     }
 
     public static void publishServiceDefinition(URL url) {
         // store in local
-        WritableMetadataService.getDefaultExtension().publishServiceDefinition(url);
+        WritableMetadataService.getDefaultExtension(url.getScopeModel()).publishServiceDefinition(url);
         // send to remote
         if (REMOTE_METADATA_STORAGE_TYPE.equalsIgnoreCase(url.getParameter(METADATA_KEY))) {
-            getRemoteMetadataService().publishServiceDefinition(url);
+            getRemoteMetadataService(ScopeModelUtil.getApplicationModel(url.getScopeModel())).publishServiceDefinition(url);
         }
     }
 
@@ -125,8 +107,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/ProtocolPortsMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
index 12099ceb15..ec17ae00a0 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizer.java
@@ -36,7 +36,7 @@ public class ProtocolPortsMetadataCustomizer implements ServiceInstanceCustomize
 
     @Override
     public void customize(ServiceInstance serviceInstance) {
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(serviceInstance.getApplicationModel());
 
         Map protocols = new HashMap<>();
         writableMetadataService.getExportedServiceURLs()
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
index b3d6efb158..155a778529 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizer.java
@@ -58,10 +58,11 @@ public class ServiceInstanceMetadataCustomizer implements ServiceInstanceCustomi
 
     @Override
     public void customize(ServiceInstance serviceInstance) {
-        ExtensionLoader loader = ExtensionLoader.getExtensionLoader(MetadataParamsFilter.class);
+        ApplicationModel applicationModel = serviceInstance.getApplicationModel();
+        ExtensionLoader loader = applicationModel.getExtensionLoader(MetadataParamsFilter.class);
 
         InMemoryWritableMetadataService localMetadataService
-                = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension();
+                = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(applicationModel);
         // pick the first interface metadata available.
         // FIXME, check the same key in different urls have the same value
         Map metadataInfos = localMetadataService.getMetadataInfos();
@@ -80,10 +81,10 @@ public class ServiceInstanceMetadataCustomizer implements ServiceInstanceCustomi
         // load instance params users want to load.
         // TODO, duplicate snippet in ApplicationConfig
         Map extraParameters = Collections.emptyMap();
-        Set adapters = ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
+        Set adapters = applicationModel.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
         if (CollectionUtils.isNotEmpty(adapters)) {
             Map inputParameters = new HashMap<>();
-            inputParameters.put(APPLICATION_KEY, ApplicationModel.getName());
+            inputParameters.put(APPLICATION_KEY, applicationModel.getApplicationName());
             for (InfraAdapter adapter : adapters) {
                 extraParameters = adapter.getExtraAttributes(inputParameters);
             }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
index 5c0e8ea3d8..ddf4bd2238 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
@@ -222,7 +222,7 @@ public class ServiceInstanceMetadataUtils {
         if (registryCluster == null) {
             registryCluster = DEFAULT_KEY;
         }
-        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService writableMetadataService = WritableMetadataService.getDefaultExtension(instance.getApplicationModel());
         MetadataInfo metadataInfo = writableMetadataService.getMetadataInfos().get(registryCluster);
         if (metadataInfo == null) {
             metadataInfo = ((InMemoryWritableMetadataService) writableMetadataService).getDefaultMetadataInfo();
@@ -294,8 +294,8 @@ public class ServiceInstanceMetadataUtils {
 
     private static void reportMetadataToRemote(ServiceInstance serviceInstance) {
         if (REMOTE_METADATA_STORAGE_TYPE.equalsIgnoreCase(getMetadataStorageType(serviceInstance))) {
-            RemoteMetadataServiceImpl remoteMetadataService = MetadataUtils.getRemoteMetadataService();
-            remoteMetadataService.publishMetadata(serviceInstance.getServiceName());
+            RemoteMetadataServiceImpl remoteMetadataService = MetadataUtils.getRemoteMetadataService(serviceInstance.getApplicationModel());
+            remoteMetadataService.publishMetadata(serviceInstance.getApplicationModel().getApplicationName());
         }
     }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
index a7dda4b75f..e4071241db 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/StandardMetadataServiceURLBuilder.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -48,12 +49,19 @@ import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataU
  * @see MetadataService
  * @since 2.7.5
  */
-public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuilder {
+public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuilder, ScopeModelAware {
 
     private final Logger logger = LoggerFactory.getLogger(getClass());
 
     public static final String NAME = "standard";
 
+    private ApplicationModel applicationModel;
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
+
     /**
      * Build the {@link URL urls} from {@link ServiceInstance#getMetadata() the metadata} of {@link ServiceInstance}
      *
@@ -88,7 +96,7 @@ public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuil
                 .setPort(port)
                 .setProtocol(protocol)
                 .setPath(MetadataService.class.getName())
-                .addParameter(TIMEOUT_KEY, ConfigurationUtils.get(METADATA_PROXY_TIMEOUT_KEY, DEFAULT_METADATA_TIMEOUT_VALUE))
+                .addParameter(TIMEOUT_KEY, ConfigurationUtils.get(applicationModel, METADATA_PROXY_TIMEOUT_KEY, DEFAULT_METADATA_TIMEOUT_VALUE))
                 .addParameter(SIDE_KEY, CONSUMER);
 
         // add parameters
@@ -100,7 +108,7 @@ public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuil
     }
 
     private URL generateUrlWithoutMetadata(String serviceName, String host, Integer instancePort) {
-        Integer port = ApplicationModel.getApplicationConfig().getMetadataServicePort();
+        Integer port = ApplicationModel.defaultModel().getCurrentConfig().getMetadataServicePort();
         if (port == null || port < 1) {
             logger.warn("Metadata Service Port is not provided, since DNS is not able to negotiate the metadata port " +
                     "between Provider and Consumer, will try to use instance port as the default metadata port.");
@@ -120,7 +128,7 @@ public class StandardMetadataServiceURLBuilder implements MetadataServiceURLBuil
                 .setPort(port)
                 .setProtocol(DUBBO_PROTOCOL)
                 .setPath(MetadataService.class.getName())
-                .addParameter(TIMEOUT_KEY, ConfigurationUtils.get(METADATA_PROXY_TIMEOUT_KEY, DEFAULT_METADATA_TIMEOUT_VALUE))
+                .addParameter(TIMEOUT_KEY, ConfigurationUtils.get(applicationModel, METADATA_PROXY_TIMEOUT_KEY, DEFAULT_METADATA_TIMEOUT_VALUE))
                 .addParameter(Constants.RECONNECT_KEY, false)
                 .addParameter(SIDE_KEY, CONSUMER)
                 .addParameter(GROUP_KEY, serviceName)
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/InMemoryWritableMetadataService.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/InMemoryWritableMetadataService.java
index ddbb16398f..4cd2618406 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/InMemoryWritableMetadataService.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/store/InMemoryWritableMetadataService.java
@@ -32,6 +32,7 @@ import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
 import org.apache.dubbo.registry.client.RegistryClusterIdentifier;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
 
 import com.google.gson.Gson;
@@ -74,7 +75,7 @@ import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
  * @see WritableMetadataService
  * @since 2.7.5
  */
-public class InMemoryWritableMetadataService implements WritableMetadataService {
+public class InMemoryWritableMetadataService implements WritableMetadataService, ScopeModelAware {
 
     Logger logger = LoggerFactory.getLogger(getClass());
 
@@ -113,11 +114,27 @@ public class InMemoryWritableMetadataService implements WritableMetadataService
     ConcurrentNavigableMap> subscribedServiceURLs = new ConcurrentSkipListMap<>();
 
     ConcurrentNavigableMap serviceDefinitions = new ConcurrentSkipListMap<>();
+    private ApplicationModel applicationModel;
 
     public InMemoryWritableMetadataService() {
         this.metadataInfos = new ConcurrentHashMap<>();
     }
 
+    /**
+     * Gets the current Dubbo Service name
+     *
+     * @return non-null
+     */
+    @Override
+    public String serviceName() {
+        return ApplicationModel.ofNullable(applicationModel).getApplicationName();
+    }
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
+
     @Override
     public SortedSet getSubscribedURLs() {
         return getAllUnmodifiableServiceURLs(subscribedServiceURLs);
@@ -167,7 +184,7 @@ public class InMemoryWritableMetadataService implements WritableMetadataService
         try {
             String[] clusters = getRegistryCluster(url).split(",");
             for (String cluster : clusters) {
-                MetadataInfo metadataInfo = metadataInfos.computeIfAbsent(cluster, k -> new MetadataInfo(ApplicationModel.getName()));
+                MetadataInfo metadataInfo = metadataInfos.computeIfAbsent(cluster, k -> new MetadataInfo(applicationModel.getApplicationName()));
                 metadataInfo.addService(new ServiceInfo(url));
             }
             metadataSemaphore.release();
@@ -298,7 +315,7 @@ public class InMemoryWritableMetadataService implements WritableMetadataService
 
     public void blockUntilUpdated() {
         try {
-            metadataSemaphore.tryAcquire(ConfigurationUtils.get(METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY) * 100L, TimeUnit.MILLISECONDS);
+            metadataSemaphore.tryAcquire(ConfigurationUtils.get(applicationModel, METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY) * 100L, TimeUnit.MILLISECONDS);
             metadataSemaphore.drainPermits();
             updateLock.writeLock().lock();
         } catch (InterruptedException e) {
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 a0736748b5..41806caebb 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 getMetadataReports() {
-        return MetadataReportInstance.getMetadataReports(false);
+        return metadataReportInstance.getMetadataReports(false);
     }
 
     public void publishMetadata(String serviceName) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/DefaultMigrationAddressComparator.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/DefaultMigrationAddressComparator.java
index 299602e151..d37aa502d6 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/DefaultMigrationAddressComparator.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/DefaultMigrationAddressComparator.java
@@ -68,7 +68,7 @@ public class DefaultMigrationAddressComparator implements MigrationAddressCompar
         if (configedThreshold != null && configedThreshold >= 0) {
             rawThreshold = String.valueOf(configedThreshold);
         }
-        rawThreshold = StringUtils.isNotEmpty(rawThreshold) ? rawThreshold : ConfigurationUtils.getCachedDynamicProperty(MIGRATION_THRESHOLD, DEFAULT_THRESHOLD_STRING);
+        rawThreshold = StringUtils.isNotEmpty(rawThreshold) ? rawThreshold : ConfigurationUtils.getCachedDynamicProperty(newInvoker.getUrl().getScopeModel(), MIGRATION_THRESHOLD, DEFAULT_THRESHOLD_STRING);
         float threshold;
         try {
             threshold = Float.parseFloat(rawThreshold);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java
index 42ea7b75f4..e724467648 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java
@@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL;
 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.status.reporter.FrameworkStatusReporter;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.registry.Registry;
@@ -34,7 +33,6 @@ import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.cluster.ClusterInvoker;
 import org.apache.dubbo.rpc.cluster.Directory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
 
 import java.util.Map;
@@ -44,7 +42,6 @@ import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.ThreadLocalRandom;
 import java.util.concurrent.TimeUnit;
 
-import static org.apache.dubbo.common.status.reporter.FrameworkStatusReporter.createConsumptionReport;
 import static org.apache.dubbo.registry.client.migration.model.MigrationStep.APPLICATION_FIRST;
 import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
 
@@ -58,6 +55,7 @@ public class MigrationInvoker implements MigrationClusterInvoker {
     private Class type;
     private RegistryProtocol registryProtocol;
     private MigrationRuleListener migrationRuleListener;
+    private ConsumerModel consumerModel;
 
     private volatile ClusterInvoker invoker;
     private volatile ClusterInvoker serviceDiscoveryInvoker;
@@ -91,8 +89,8 @@ public class MigrationInvoker implements MigrationClusterInvoker {
         this.type = type;
         this.url = url;
         this.consumerUrl = consumerUrl;
+        this.consumerModel = (ConsumerModel) consumerUrl.getServiceModel();
 
-        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(consumerUrl.getServiceKey());
         if (consumerModel != null) {
             Object object = consumerModel.getServiceMetadata().getAttribute("currentClusterInvoker");
             Map> invokerMap;
@@ -315,7 +313,6 @@ public class MigrationInvoker implements MigrationClusterInvoker {
         if (serviceDiscoveryInvoker != null) {
             serviceDiscoveryInvoker.destroy();
         }
-        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(consumerUrl.getServiceKey());
         if (consumerModel != null) {
             Object object = consumerModel.getServiceMetadata().getAttribute("currentClusterInvoker");
             Map> invokerMap;
@@ -426,9 +423,10 @@ public class MigrationInvoker implements MigrationClusterInvoker {
         }
         setListener(serviceDiscoveryInvoker, () -> {
             latch.countDown();
-            FrameworkStatusReporter.reportConsumptionStatus(
-                createConsumptionReport(consumerUrl.getServiceInterface(), consumerUrl.getVersion(), consumerUrl.getGroup(), "app")
-            );
+            //TODO FrameworkStatusReporter
+//            FrameworkStatusReporter.reportConsumptionStatus(
+//                createConsumptionReport(consumerUrl.getServiceInterface(), consumerUrl.getVersion(), consumerUrl.getGroup(), "app")
+//            );
             if (step == APPLICATION_FIRST) {
                 calcPreferredInvoker(rule);
             }
@@ -449,9 +447,10 @@ public class MigrationInvoker implements MigrationClusterInvoker {
         }
         setListener(invoker, () -> {
             latch.countDown();
-            FrameworkStatusReporter.reportConsumptionStatus(
-                createConsumptionReport(consumerUrl.getServiceInterface(), consumerUrl.getVersion(), consumerUrl.getGroup(), "interface")
-            );
+            //TODO FrameworkStatusReporter
+//            FrameworkStatusReporter.reportConsumptionStatus(
+//                createConsumptionReport(consumerUrl.getServiceInterface(), consumerUrl.getVersion(), consumerUrl.getGroup(), "interface")
+//            );
             if (step == APPLICATION_FIRST) {
                 calcPreferredInvoker(rule);
             }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleHandler.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleHandler.java
index c7248db20e..3e987f57ad 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleHandler.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleHandler.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.registry.client.migration;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.status.reporter.FrameworkStatusReporter;
 import org.apache.dubbo.registry.client.migration.model.MigrationRule;
 import org.apache.dubbo.registry.client.migration.model.MigrationStep;
 
@@ -98,11 +97,12 @@ public class MigrationRuleHandler {
     }
 
     private void report(MigrationStep step, MigrationStep originStep, String success) {
-        if (FrameworkStatusReporter.hasReporter()) {
-            FrameworkStatusReporter.reportMigrationStepStatus(
-                    FrameworkStatusReporter.createMigrationStepReport(consumerURL.getServiceInterface(), consumerURL.getVersion(),
-                            consumerURL.getGroup(), String.valueOf(originStep), String.valueOf(step), success));
-        }
+        //TODO FrameworkStatusReporter
+//        if (FrameworkStatusReporter.hasReporter()) {
+//            FrameworkStatusReporter.reportMigrationStepStatus(
+//                    FrameworkStatusReporter.createMigrationStepReport(consumerURL.getServiceInterface(), consumerURL.getVersion(),
+//                            consumerURL.getGroup(), String.valueOf(originStep), String.valueOf(step), success));
+//        }
     }
 
     private void setMigrationRule(MigrationRule rule) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java
index 7c76b38c7e..2a5dbf2dca 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationRuleListener.java
@@ -33,6 +33,7 @@ import org.apache.dubbo.registry.integration.RegistryProtocolListener;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.cluster.ClusterInvoker;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 
 import java.util.Map;
 import java.util.Objects;
@@ -59,11 +60,11 @@ import static org.apache.dubbo.common.constants.RegistryConstants.INIT;
  * - Rule change, invoker behaviour is changed according to the newly received rule.
  */
 @Activate
-public class MigrationRuleListener implements RegistryProtocolListener, ConfigurationListener {
+public class MigrationRuleListener implements RegistryProtocolListener, ConfigurationListener, ScopeModelAware {
     private static final Logger logger = LoggerFactory.getLogger(MigrationRuleListener.class);
     private static final String DUBBO_SERVICEDISCOVERY_MIGRATION = "DUBBO_SERVICEDISCOVERY_MIGRATION";
     private static final String MIGRATION_DELAY_KEY = "dubbo.application.migration.delay";
-    private final String RULE_KEY = ApplicationModel.getName() + ".migration";
+    private String ruleKey;
 
     protected final Map handlers = new ConcurrentHashMap<>();
     protected final LinkedBlockingQueue ruleQueue = new LinkedBlockingQueue<>();
@@ -78,15 +79,26 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur
 
     private volatile String rawRule;
     private volatile MigrationRule rule;
+    private ApplicationModel applicationModel;
 
     public MigrationRuleListener() {
-        this.configuration = ApplicationModel.getEnvironment().getDynamicConfiguration().orElse(null);
+    }
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        init();
+    }
+
+    private void init() {
+        this.ruleKey = applicationModel.getApplicationName() + ".migration";
+        this.configuration = applicationModel.getApplicationEnvironment().getDynamicConfiguration().orElse(null);
 
         if (this.configuration != null) {
-            logger.info("Listening for migration rules on dataId " + RULE_KEY + ", group " + DUBBO_SERVICEDISCOVERY_MIGRATION);
-            configuration.addListener(RULE_KEY, DUBBO_SERVICEDISCOVERY_MIGRATION, this);
+            logger.info("Listening for migration rules on dataId " + ruleKey + ", group " + DUBBO_SERVICEDISCOVERY_MIGRATION);
+            configuration.addListener(ruleKey, DUBBO_SERVICEDISCOVERY_MIGRATION, this);
 
-            String rawRule = configuration.getConfig(RULE_KEY, DUBBO_SERVICEDISCOVERY_MIGRATION);
+            String rawRule = configuration.getConfig(ruleKey, DUBBO_SERVICEDISCOVERY_MIGRATION);
             if (StringUtils.isEmpty(rawRule)) {
                 rawRule = INIT;
             }
@@ -98,7 +110,7 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur
             setRawRule(INIT);
         }
 
-        String localRawRule = ApplicationModel.getEnvironment().getLocalMigrationRule();
+        String localRawRule = applicationModel.getApplicationEnvironment().getLocalMigrationRule();
         if (!StringUtils.isEmpty(localRawRule)) {
             localRuleMigrationFuture = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboMigrationRuleDelayWorker", true))
                 .schedule(() -> {
@@ -111,7 +123,7 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur
 
     private int getDelay() {
         int delay = 60000;
-        String delayStr = ConfigurationUtils.getProperty(MIGRATION_DELAY_KEY);
+        String delayStr = ConfigurationUtils.getProperty(applicationModel, MIGRATION_DELAY_KEY);
         if (StringUtils.isEmpty(delayStr)) {
             return delay;
         }
@@ -229,7 +241,7 @@ public class MigrationRuleListener implements RegistryProtocolListener, Configur
     @Override
     public void onDestroy() {
         if (configuration != null) {
-            configuration.removeListener(RULE_KEY, this);
+            configuration.removeListener(ruleKey, this);
         }
         if (ruleMigrationFuture != null) {
             ruleMigrationFuture.cancel(true);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/model/MigrationRule.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/model/MigrationRule.java
index b09c435866..27a51fc890 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/model/MigrationRule.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/model/MigrationRule.java
@@ -151,7 +151,7 @@ public class MigrationRule {
         }
 
         if (applications != null) {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(consumerURL.getScopeModel());
             Set services = serviceNameMapping.getServices(consumerURL);
             if (CollectionUtils.isNotEmpty(services)) {
                 for (String service : services) {
@@ -171,7 +171,7 @@ public class MigrationRule {
             step = MigrationStep.APPLICATION_FIRST;
             step = Enum.valueOf(MigrationStep.class,
                 consumerURL.getParameter(MIGRATION_STEP_KEY,
-                    ConfigurationUtils.getCachedDynamicProperty(DUBBO_SERVICEDISCOVERY_MIGRATION, step.name())));
+                    ConfigurationUtils.getCachedDynamicProperty(consumerURL.getScopeModel(), DUBBO_SERVICEDISCOVERY_MIGRATION, step.name())));
         }
 
         return step;
@@ -192,7 +192,7 @@ public class MigrationRule {
         }
 
         if (applications != null) {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(consumerURL.getScopeModel());
             Set services = serviceNameMapping.getServices(consumerURL);
             if (CollectionUtils.isNotEmpty(services)) {
                 for (String service : services) {
@@ -232,7 +232,7 @@ public class MigrationRule {
         }
 
         if (applications != null) {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(consumerURL.getScopeModel());
             Set services = serviceNameMapping.getServices(consumerURL);
             if (CollectionUtils.isNotEmpty(services)) {
                 for (String service : services) {
@@ -268,7 +268,7 @@ public class MigrationRule {
         }
 
         if (applications != null) {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(consumerURL.getScopeModel());
             Set services = serviceNameMapping.getServices(consumerURL);
             if (CollectionUtils.isNotEmpty(services)) {
                 for (String service : services) {
@@ -308,7 +308,7 @@ public class MigrationRule {
         }
 
         if (applications != null) {
-            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
+            ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension(consumerURL.getScopeModel());
             Set services = serviceNameMapping.getServices(consumerURL);
             if (CollectionUtils.isNotEmpty(services)) {
                 for (String service : services) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
index 1e2d0fd5b7..87abfc71ac 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
@@ -21,13 +21,13 @@ import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
 import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
 import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
-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;
 import org.apache.dubbo.rpc.cluster.Configurator;
 import org.apache.dubbo.rpc.cluster.configurator.parser.ConfigParser;
 import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -48,12 +48,21 @@ public abstract class AbstractConfiguratorListener implements ConfigurationListe
     private static final Logger logger = LoggerFactory.getLogger(AbstractConfiguratorListener.class);
 
     protected List configurators = Collections.emptyList();
-    protected GovernanceRuleRepository ruleRepository = ExtensionLoader.getExtensionLoader(
-            GovernanceRuleRepository.class).getDefaultExtension();
+    protected GovernanceRuleRepository ruleRepository;
 
     protected Set securityKey = new HashSet<>();
+    protected ApplicationModel applicationModel;
 
-    {
+    public AbstractConfiguratorListener(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+
+        ruleRepository = applicationModel.getExtensionLoader(
+            GovernanceRuleRepository.class).getDefaultExtension();
+
+        initSecurityKey();
+    }
+
+    private void initSecurityKey() {
         // accessLogKey and FileRouterFactory key
         securityKey.add(ACCESS_LOG_KEY);
         securityKey.add(ROUTER_KEY);
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java
index 2643f3314d..674747474f 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/InterfaceCompatibleRegistryProtocol.java
@@ -60,7 +60,7 @@ public class InterfaceCompatibleRegistryProtocol extends RegistryProtocol {
 
     @Override
     public  ClusterInvoker getServiceDiscoveryInvoker(Cluster cluster, Registry registry, Class type, URL url) {
-        registry = registryFactory.getRegistry(super.getRegistryUrl(url));
+        registry = getRegistry(super.getRegistryUrl(url));
         DynamicDirectory directory = new ServiceDiscoveryRegistryDirectory<>(type, url);
         return doCreateInvoker(directory, cluster, registry, type);
     }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
index 82058af37e..4fa1f7680f 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
@@ -78,6 +78,7 @@ import static org.apache.dubbo.registry.integration.InterfaceCompatibleRegistryP
 import static org.apache.dubbo.remoting.Constants.CHECK_KEY;
 import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
+import static org.apache.dubbo.rpc.model.ScopeModelUtil.getApplicationModel;
 
 
 /**
@@ -86,7 +87,7 @@ import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
 public class RegistryDirectory extends DynamicDirectory {
     private static final Logger logger = LoggerFactory.getLogger(RegistryDirectory.class);
 
-    private static final ConsumerConfigurationListener CONSUMER_CONFIGURATION_LISTENER = new ConsumerConfigurationListener();
+    private final ConsumerConfigurationListener consumerConfigurationListener;
     private ReferenceConfigurationListener referenceConfigurationListener;
 
     /**
@@ -99,23 +100,26 @@ public class RegistryDirectory extends DynamicDirectory {
      * The initial value is null and the midway may be assigned to null, please use the local variable reference
      */
     protected volatile Set cachedInvokerUrls;
+    private final ApplicationModel applicationModel;
 
     public RegistryDirectory(Class serviceType, URL url) {
         super(serviceType, url);
+        applicationModel = getApplicationModel(url.getScopeModel());
+        consumerConfigurationListener = new ConsumerConfigurationListener(applicationModel);
     }
 
     @Override
     public void subscribe(URL url) {
         setSubscribeUrl(url);
-        CONSUMER_CONFIGURATION_LISTENER.addNotifyListener(this);
-        referenceConfigurationListener = new ReferenceConfigurationListener(this, url);
+        consumerConfigurationListener.addNotifyListener(this);
+        referenceConfigurationListener = new ReferenceConfigurationListener(applicationModel, this, url);
         registry.subscribe(url, this);
     }
 
     @Override
     public void unSubscribe(URL url) {
         setSubscribeUrl(null);
-        CONSUMER_CONFIGURATION_LISTENER.removeNotifyListener(this);
+        consumerConfigurationListener.removeNotifyListener(this);
         referenceConfigurationListener.stop();
         registry.unsubscribe(url, this);
     }
@@ -412,7 +416,7 @@ public class RegistryDirectory extends DynamicDirectory {
         providerUrl = overrideWithConfigurators(this.configurators, providerUrl);
 
         // override url with configurator from "app-name.configurators"
-        providerUrl = overrideWithConfigurators(CONSUMER_CONFIGURATION_LISTENER.getConfigurators(), providerUrl);
+        providerUrl = overrideWithConfigurators(consumerConfigurationListener.getConfigurators(), providerUrl);
 
         // override url with configurator from configurators from "service-name.configurators"
         if (referenceConfigurationListener != null) {
@@ -599,7 +603,7 @@ public class RegistryDirectory extends DynamicDirectory {
         this.overrideDirectoryUrl = directoryUrl;
         List localConfigurators = this.configurators; // local reference
         doOverrideUrl(localConfigurators);
-        List localAppDynamicConfigurators = CONSUMER_CONFIGURATION_LISTENER.getConfigurators(); // local reference
+        List localAppDynamicConfigurators = consumerConfigurationListener.getConfigurators(); // local reference
         doOverrideUrl(localAppDynamicConfigurators);
         if (referenceConfigurationListener != null) {
             List localDynamicConfigurators = referenceConfigurationListener.getConfigurators(); // local reference
@@ -619,7 +623,8 @@ public class RegistryDirectory extends DynamicDirectory {
         private RegistryDirectory directory;
         private URL url;
 
-        ReferenceConfigurationListener(RegistryDirectory directory, URL url) {
+        ReferenceConfigurationListener(ApplicationModel applicationModel, RegistryDirectory directory, URL url) {
+            super(applicationModel);
             this.directory = directory;
             this.url = url;
             this.initWith(DynamicConfiguration.getRuleKey(url) + CONFIGURATORS_SUFFIX);
@@ -639,8 +644,9 @@ public class RegistryDirectory extends DynamicDirectory {
     private static class ConsumerConfigurationListener extends AbstractConfiguratorListener {
         List listeners = new ArrayList<>();
 
-        ConsumerConfigurationListener() {
-            this.initWith(ApplicationModel.getName() + CONFIGURATORS_SUFFIX);
+        ConsumerConfigurationListener(ApplicationModel applicationModel) {
+            super(applicationModel);
+            this.initWith(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX);
         }
 
         void addNotifyListener(RegistryDirectory listener) {
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index a4af51b51d..dea9fd8c30 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.registry.integration;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
-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.timer.HashedWheelTimer;
@@ -50,7 +49,11 @@ import org.apache.dubbo.rpc.cluster.Constants;
 import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository;
 import org.apache.dubbo.rpc.cluster.support.MergeableCluster;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 import org.apache.dubbo.rpc.protocol.InvokerWrapper;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
 
@@ -91,11 +94,11 @@ import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
 import static org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
 import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
 import static org.apache.dubbo.common.utils.UrlUtils.classifyUrls;
 import static org.apache.dubbo.registry.Constants.CONFIGURATORS_SUFFIX;
 import static org.apache.dubbo.registry.Constants.DEFAULT_REGISTRY_RETRY_PERIOD;
+import static org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN;
 import static org.apache.dubbo.registry.Constants.PROVIDER_PROTOCOL;
 import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
 import static org.apache.dubbo.registry.Constants.REGISTER_KEY;
@@ -118,11 +121,12 @@ import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.WARMUP_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.WEIGHT_KEY;
+import static org.apache.dubbo.rpc.model.ScopeModelUtil.getApplicationModel;
 
 /**
  * TODO, replace RegistryProtocol completely in the future.
  */
-public class RegistryProtocol implements Protocol {
+public class RegistryProtocol implements Protocol, ScopeModelAware {
     public static final String[] DEFAULT_REGISTER_PROVIDER_KEYS = {
         APPLICATION_KEY, CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, CONNECTIONS_KEY, DEPRECATED_KEY,
         GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY,
@@ -134,18 +138,17 @@ public class RegistryProtocol implements Protocol {
     };
 
     private final static Logger logger = LoggerFactory.getLogger(RegistryProtocol.class);
-    private final Map overrideListeners = new ConcurrentHashMap<>();
     private final Map serviceConfigurationListeners = new ConcurrentHashMap<>();
-    private final ProviderConfigurationListener providerConfigurationListener = new ProviderConfigurationListener();
     //To solve the problem of RMI repeated exposure port conflicts, the services that have been exposed are no longer exposed.
     //provider url <--> exporter
     private final ConcurrentMap> bounds = new ConcurrentHashMap<>();
     protected Protocol protocol;
-    protected RegistryFactory registryFactory;
     protected ProxyFactory proxyFactory;
+    //protected RegistryFactory registryFactory;
 
     private ConcurrentMap reExportFailedTasks = new ConcurrentHashMap<>();
     private HashedWheelTimer retryTimer = new HashedWheelTimer(new NamedThreadFactory("DubboReexportTimer", true), DEFAULT_REGISTRY_RETRY_PERIOD, TimeUnit.MILLISECONDS, 128);
+    private FrameworkModel frameworkModel;
 
     //Filter the parameters that do not need to be output in url(Starting with .)
     private static String[] getFilteredKeys(URL url) {
@@ -159,13 +162,19 @@ public class RegistryProtocol implements Protocol {
         }
     }
 
+    @Override
+    public void setFrameworkModel(FrameworkModel frameworkModel) {
+        this.frameworkModel = frameworkModel;
+    }
+
     public void setProtocol(Protocol protocol) {
         this.protocol = protocol;
     }
 
-    public void setRegistryFactory(RegistryFactory registryFactory) {
-        this.registryFactory = registryFactory;
-    }
+    // Cannot inject registryFactory (application scope) into protocol (framework scope)
+//    public void setRegistryFactory(RegistryFactory registryFactory) {
+//        this.registryFactory = registryFactory;
+//    }
 
     public void setProxyFactory(ProxyFactory proxyFactory) {
         this.proxyFactory = proxyFactory;
@@ -177,7 +186,16 @@ public class RegistryProtocol implements Protocol {
     }
 
     public Map getOverrideListeners() {
-        return overrideListeners;
+        Map map = new HashMap<>();
+        List applicationModels = frameworkModel.getApplicationModels();
+        if (applicationModels.size() == 1) {
+            return applicationModels.get(0).getBeanFactory().getBean(ProviderConfigurationListener.class).getOverrideListeners();
+        } else {
+            for (ApplicationModel applicationModel : applicationModels) {
+                map.putAll(applicationModel.getBeanFactory().getBean(ProviderConfigurationListener.class).getOverrideListeners());
+            }
+        }
+        return map;
     }
 
     private void register(Registry registry, URL registeredProviderUrl) {
@@ -185,7 +203,7 @@ public class RegistryProtocol implements Protocol {
     }
 
     private void registerStatedUrl(URL registryUrl, URL registeredProviderUrl, boolean registered) {
-        ProviderModel model = ApplicationModel.getProviderModel(registeredProviderUrl.getServiceKey());
+        ProviderModel model = (ProviderModel) registeredProviderUrl.getServiceModel();
         model.addStatedUrl(new ProviderModel.RegisterStatedURL(
             registeredProviderUrl,
             registryUrl,
@@ -204,7 +222,8 @@ public class RegistryProtocol implements Protocol {
         //  subscription information to cover.
         final URL overrideSubscribeUrl = getSubscribedOverrideUrl(providerUrl);
         final OverrideListener overrideSubscribeListener = new OverrideListener(overrideSubscribeUrl, originInvoker);
-        overrideListeners.put(overrideSubscribeUrl, overrideSubscribeListener);
+        Map overrideListeners = getProviderConfigurationListener(providerUrl).getOverrideListeners();
+        overrideListeners.put(registryUrl, overrideSubscribeListener);
 
         providerUrl = overrideUrlWithConfig(providerUrl, overrideSubscribeListener);
         //export invoker
@@ -236,7 +255,8 @@ public class RegistryProtocol implements Protocol {
     }
 
     private  void notifyExport(ExporterChangeableWrapper exporter) {
-        List listeners = ExtensionLoader.getExtensionLoader(RegistryProtocolListener.class)
+        ScopeModel scopeModel = exporter.getRegisterUrl().getScopeModel();
+        List listeners = ScopeModelUtil.getExtensionLoader(RegistryProtocolListener.class, scopeModel)
             .getActivateExtension(exporter.getOriginInvoker().getUrl(), "registry.protocol.listener");
         if (CollectionUtils.isNotEmpty(listeners)) {
             for (RegistryProtocolListener listener : listeners) {
@@ -246,8 +266,11 @@ public class RegistryProtocol implements Protocol {
     }
 
     private URL overrideUrlWithConfig(URL providerUrl, OverrideListener listener) {
+        ApplicationModel applicationModel = getApplicationModel(providerUrl.getScopeModel());
+        ProviderConfigurationListener providerConfigurationListener = getProviderConfigurationListener(providerUrl);
         providerUrl = providerConfigurationListener.overrideUrl(providerUrl);
-        ServiceConfigurationListener serviceConfigurationListener = new ServiceConfigurationListener(providerUrl, listener);
+
+        ServiceConfigurationListener serviceConfigurationListener = new ServiceConfigurationListener(applicationModel, providerUrl, listener);
         serviceConfigurationListeners.put(providerUrl.getServiceKey(), serviceConfigurationListener);
         return serviceConfigurationListener.overrideUrl(providerUrl);
     }
@@ -339,7 +362,8 @@ public class RegistryProtocol implements Protocol {
     }
 
     private ProviderModel.RegisterStatedURL getStatedUrl(URL registryUrl, URL providerUrl) {
-        ProviderModel providerModel = ApplicationModel.getServiceRepository()
+        ApplicationModel applicationModel = getApplicationModel(registryUrl.getScopeModel());
+        ProviderModel providerModel = applicationModel.getApplicationServiceRepository()
             .lookupExportedService(providerUrl.getServiceKey());
 
         List statedUrls = providerModel.getStatedUrl();
@@ -356,6 +380,7 @@ public class RegistryProtocol implements Protocol {
      * @return
      */
     protected Registry getRegistry(final URL registryUrl) {
+        RegistryFactory registryFactory = ScopeModelUtil.getExtensionLoader(RegistryFactory.class, registryUrl.getScopeModel()).getAdaptiveExtension();
         return registryFactory.getRegistry(registryUrl);
     }
 
@@ -435,7 +460,7 @@ public class RegistryProtocol implements Protocol {
     @SuppressWarnings("unchecked")
     public  Invoker refer(Class type, URL url) throws RpcException {
         url = getRegistryUrl(url);
-        Registry registry = registryFactory.getRegistry(url);
+        Registry registry = getRegistry(url);
         if (RegistryService.class.equals(type)) {
             return proxyFactory.getInvoker((T) registry, type, url);
         }
@@ -520,6 +545,8 @@ public class RegistryProtocol implements Protocol {
         URL urlToRegistry = new ServiceConfigURL(
             parameters.get(PROTOCOL_KEY) == null ? DUBBO : parameters.get(PROTOCOL_KEY),
             parameters.remove(REGISTER_IP_KEY), 0, getPath(parameters, type), parameters);
+        urlToRegistry = urlToRegistry.setScopeModel(directory.getConsumerUrl().getScopeModel());
+        urlToRegistry = urlToRegistry.setServiceModel(directory.getConsumerUrl().getServiceModel());
         if (directory.isShouldRegister()) {
             directory.setRegisteredConsumerUrl(urlToRegistry);
             registry.register(directory.getRegisteredConsumerUrl());
@@ -545,7 +572,7 @@ public class RegistryProtocol implements Protocol {
     }
 
     protected List findRegistryProtocolListeners(URL url) {
-        return ExtensionLoader.getExtensionLoader(RegistryProtocolListener.class)
+        return ScopeModelUtil.getExtensionLoader(RegistryProtocolListener.class, url.getScopeModel())
             .getActivateExtension(url, "registry.protocol.listener");
     }
 
@@ -560,11 +587,23 @@ public class RegistryProtocol implements Protocol {
 
     @Override
     public void destroy() {
-        List listeners = ExtensionLoader.getExtensionLoader(RegistryProtocolListener.class)
-            .getLoadedExtensionInstances();
-        if (CollectionUtils.isNotEmpty(listeners)) {
-            for (RegistryProtocolListener listener : listeners) {
-                listener.onDestroy();
+        for (ApplicationModel applicationModel : frameworkModel.getApplicationModels()) {
+            List listeners = applicationModel.getExtensionLoader(RegistryProtocolListener.class)
+                .getLoadedExtensionInstances();
+            if (CollectionUtils.isNotEmpty(listeners)) {
+                for (RegistryProtocolListener listener : listeners) {
+                    listener.onDestroy();
+                }
+            }
+        }
+
+        for (ApplicationModel applicationModel : frameworkModel.getApplicationModels()) {
+            if (applicationModel.isInit()) {
+                if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
+                    applicationModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
+                        .removeListener(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX,
+                            getProviderConfigurationListener(applicationModel));
+                }
             }
         }
 
@@ -573,11 +612,6 @@ public class RegistryProtocol implements Protocol {
             exporter.unexport();
         }
         bounds.clear();
-
-        if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
-            ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
-                .removeListener(ApplicationModel.getName() + CONFIGURATORS_SUFFIX, providerConfigurationListener);
-        }
     }
 
     @Override
@@ -695,7 +729,7 @@ public class RegistryProtocol implements Protocol {
             URL currentUrl = exporter.getInvoker().getUrl();
             //Merged with this configuration
             URL newUrl = getConfiguredInvokerUrl(configurators, originUrl);
-            newUrl = getConfiguredInvokerUrl(providerConfigurationListener.getConfigurators(), newUrl);
+            newUrl = getConfiguredInvokerUrl(getProviderConfigurationListener(originUrl).getConfigurators(), newUrl);
             newUrl = getConfiguredInvokerUrl(serviceConfigurationListeners.get(originUrl.getServiceKey())
                 .getConfigurators(), newUrl);
             if (!currentUrl.equals(newUrl)) {
@@ -725,14 +759,25 @@ public class RegistryProtocol implements Protocol {
         }
     }
 
+    private ProviderConfigurationListener getProviderConfigurationListener(URL url) {
+        ApplicationModel applicationModel = getApplicationModel(url.getScopeModel());
+        return getProviderConfigurationListener(applicationModel);
+    }
+
+    private ProviderConfigurationListener getProviderConfigurationListener(ApplicationModel applicationModel) {
+        return applicationModel.getBeanFactory().registerBeanIfAbsent(ProviderConfigurationListener.class,
+            type -> new ProviderConfigurationListener(applicationModel) );
+    }
+
     private class ServiceConfigurationListener extends AbstractConfiguratorListener {
         private URL providerUrl;
         private OverrideListener notifyListener;
 
-        public ServiceConfigurationListener(URL providerUrl, OverrideListener notifyListener) {
+        public ServiceConfigurationListener(ApplicationModel applicationModel, URL providerUrl, OverrideListener notifyListener) {
+            super(applicationModel);
             this.providerUrl = providerUrl;
             this.notifyListener = notifyListener;
-            if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
+            if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) {
                 this.initWith(DynamicConfiguration.getRuleKey(providerUrl) + CONFIGURATORS_SUFFIX);
             }
         }
@@ -749,9 +794,12 @@ public class RegistryProtocol implements Protocol {
 
     private class ProviderConfigurationListener extends AbstractConfiguratorListener {
 
-        public ProviderConfigurationListener() {
-            if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
-                this.initWith(ApplicationModel.getName() + CONFIGURATORS_SUFFIX);
+        private final Map overrideListeners = new ConcurrentHashMap<>();
+
+        public ProviderConfigurationListener(ApplicationModel applicationModel) {
+            super(applicationModel);
+            if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) {
+                this.initWith(applicationModel.getApplicationName() + CONFIGURATORS_SUFFIX);
             }
         }
 
@@ -770,6 +818,10 @@ public class RegistryProtocol implements Protocol {
         protected void notifyOverrides() {
             overrideListeners.values().forEach(listener -> ((OverrideListener) listener).doOverrideIfNecessary());
         }
+
+        public Map getOverrideListeners() {
+            return overrideListeners;
+        }
     }
 
     /**
@@ -818,12 +870,14 @@ public class RegistryProtocol implements Protocol {
             }
             try {
                 if (subscribeUrl != null) {
-                    NotifyListener listener = RegistryProtocol.this.overrideListeners.remove(subscribeUrl);
+                    Map overrideListeners = getProviderConfigurationListener(subscribeUrl).getOverrideListeners();
+                    NotifyListener listener = overrideListeners.remove(registerUrl);
                     registry.unsubscribe(subscribeUrl, listener);
-                    if (ApplicationModel.getEnvironment().getConfiguration().convert(Boolean.class, org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN, true)) {
-                        ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
+                    ApplicationModel applicationModel = getApplicationModel(registerUrl.getScopeModel());
+                    if (applicationModel.getApplicationEnvironment().getConfiguration().convert(Boolean.class, ENABLE_CONFIGURATION_LISTEN, true)) {
+                        applicationModel.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension()
                             .removeListener(subscribeUrl.getServiceKey() + CONFIGURATORS_SUFFIX,
-                                serviceConfigurationListeners.get(subscribeUrl.getServiceKey()));
+                                serviceConfigurationListeners.remove(subscribeUrl.getServiceKey()));
                     }
                 }
             } catch (Throwable t) {
@@ -832,7 +886,7 @@ public class RegistryProtocol implements Protocol {
 
             executor.submit(() -> {
                 try {
-                    int timeout = ConfigurationUtils.getServerShutdownTimeout();
+                    int timeout = ConfigurationUtils.getServerShutdownTimeout(subscribeUrl.getScopeModel());
                     if (timeout > 0) {
                         logger.info("Waiting " + timeout + "ms for registry to notify all consumers before unexport. " +
                             "Usually, this is called when you use dubbo API");
@@ -858,19 +912,4 @@ public class RegistryProtocol implements Protocol {
         }
     }
 
-    // for unit test
-    private static RegistryProtocol INSTANCE;
-
-    // for unit test
-    public RegistryProtocol() {
-        INSTANCE = this;
-    }
-
-    // for unit test
-    public static RegistryProtocol getRegistryProtocol() {
-        if (INSTANCE == null) {
-            ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(REGISTRY_PROTOCOL); // load
-        }
-        return INSTANCE;
-    }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocolListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocolListener.java
index 41c57db96f..eafc84e7fc 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocolListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocolListener.java
@@ -21,11 +21,13 @@ import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.cluster.ClusterInvoker;
 
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
+
 /**
  * RegistryProtocol listener is introduced to provide a chance to user to customize or change export and refer behavior
  * of RegistryProtocol. For example: re-export or re-refer on the fly when certain condition meets.
  */
-@SPI
+@SPI(scope = APPLICATION)
 public interface RegistryProtocolListener {
     /**
      * Notify RegistryProtocol's listeners when a service is registered
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
index 169b51e3fb..89710e1c93 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/AbstractRegistryFactory.java
@@ -37,9 +37,9 @@ import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.stream.Collectors;
 
+import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
 
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java
index bd8c0621fd..c356cea38b 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java
@@ -33,6 +33,8 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.ProviderFirstParams;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -67,32 +69,29 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry {
     private static final Logger logger = LoggerFactory.getLogger(CacheableFailbackRegistry.class);
     private static String[] VARIABLE_KEYS = new String[]{ENCODED_TIMESTAMP_KEY, ENCODED_PID_KEY};
 
-    protected final static Map stringAddress = new ConcurrentHashMap<>();
-    protected final static Map stringParam = new ConcurrentHashMap<>();
-    private static final ScheduledExecutorService cacheRemovalScheduler;
-    private static final int cacheRemovalTaskIntervalInMillis;
-    private static final int cacheClearWaitingThresholdInMillis;
-    private final static Map waitForRemove = new ConcurrentHashMap<>();
-    private static final Semaphore semaphore = new Semaphore(1);
+    protected Map stringAddress = new ConcurrentHashMap<>();
+    protected Map stringParam = new ConcurrentHashMap<>();
+    private ScheduledExecutorService cacheRemovalScheduler;
+    private int cacheRemovalTaskIntervalInMillis;
+    private int cacheClearWaitingThresholdInMillis;
+    private Map waitForRemove = new ConcurrentHashMap<>();
+    private Semaphore semaphore = new Semaphore(1);
 
     private final Map extraParameters;
     protected final Map> stringUrls = new HashMap<>();
 
-    static {
-        ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
-        cacheRemovalScheduler = executorRepository.nextScheduledExecutor();
-        cacheRemovalTaskIntervalInMillis = getIntConfig(CACHE_CLEAR_TASK_INTERVAL, 2 * 60 * 1000);
-        cacheClearWaitingThresholdInMillis = getIntConfig(CACHE_CLEAR_WAITING_THRESHOLD, 5 * 60 * 1000);
-    }
-
     public CacheableFailbackRegistry(URL url) {
         super(url);
         extraParameters = new HashMap<>(8);
         extraParameters.put(CHECK_KEY, String.valueOf(false));
+
+        cacheRemovalScheduler = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getExtensionLoader(ExecutorRepository.class).getDefaultExtension().nextScheduledExecutor();
+        cacheRemovalTaskIntervalInMillis = getIntConfig(url.getScopeModel(), CACHE_CLEAR_TASK_INTERVAL, 2 * 60 * 1000);
+        cacheClearWaitingThresholdInMillis = getIntConfig(url.getScopeModel(), CACHE_CLEAR_WAITING_THRESHOLD, 5 * 60 * 1000);
     }
 
-    protected static int getIntConfig(String key, int def) {
-        String str = ConfigurationUtils.getProperty(key);
+    protected static int getIntConfig(ScopeModel scopeModel, String key, int def) {
+        String str = ConfigurationUtils.getProperty(scopeModel, key);
         int result = def;
         if (StringUtils.isNotEmpty(str)) {
             try {
@@ -314,7 +313,7 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry {
     protected abstract boolean isMatch(URL subscribeUrl, URL providerUrl);
 
 
-    private static class RemovalTask implements Runnable {
+    private class RemovalTask implements Runnable {
         @Override
         public void run() {
             logger.info("Clearing cached URLs, waiting to clear size " + waitForRemove.size());
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java
index 7369c27832..8f073b446e 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/DefaultServiceInstanceTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
@@ -40,7 +42,7 @@ public class DefaultServiceInstanceTest {
     public DefaultServiceInstance instance;
 
     public static DefaultServiceInstance createInstance() {
-        DefaultServiceInstance instance = new DefaultServiceInstance("A", "127.0.0.1", 20880);
+        DefaultServiceInstance instance = new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
         Map metadata = instance.getMetadata();
         metadata.put(METADATA_STORAGE_TYPE_PROPERTY_NAME, "remote");
         metadata.put(EXPORTED_SERVICES_REVISION_PROPERTY_NAME, "111");
@@ -50,7 +52,6 @@ public class DefaultServiceInstanceTest {
         protocolPorts.put("rest", 8080);
         protocolPorts.put("dubbo", 20880);
         setEndpoints(instance, protocolPorts);
-
         return instance;
     }
 
@@ -93,7 +94,7 @@ public class DefaultServiceInstanceTest {
         assertEquals("value", allParams2.get("key"));
 
         // test equals
-        DefaultServiceInstance instance2 = new DefaultServiceInstance("A", "127.0.0.1", 20880);
+        DefaultServiceInstance instance2 = new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
         instance2.setMetadata(new HashMap<>(instance.getMetadata()));
         instance2.getMetadata().put(EXPORTED_SERVICES_REVISION_PROPERTY_NAME, "222");
         // assert instances with different revision and extend params are equal
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InstanceAddressURLTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InstanceAddressURLTest.java
index 9ce1f03679..6b3a0dac4f 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InstanceAddressURLTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/InstanceAddressURLTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.metadata.MetadataInfo;
 import org.apache.dubbo.registry.ProviderFirstParams;
 import org.apache.dubbo.rpc.RpcServiceContext;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -64,7 +65,7 @@ public class InstanceAddressURLTest {
         "&version=1.0.0&timeout=9000&a.timeout=8888&dubbo.tag=consumer&protocol=dubbo");
 
     private DefaultServiceInstance createInstance() {
-        DefaultServiceInstance instance = new DefaultServiceInstance("demo-provider", "127.0.0.1", 8080);
+        DefaultServiceInstance instance = new DefaultServiceInstance("demo-provider", "127.0.0.1", 8080, ApplicationModel.defaultModel());
         Map metadata = instance.getMetadata();
         metadata.put("key1", "value1");
         metadata.put("key2", "value2");
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
index 2f5e047eb5..f8378d42aa 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.client.event.listener.MockServiceInstancesChangedListener;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
@@ -97,63 +98,65 @@ public class ServiceDiscoveryRegistryTest {
         when(serviceDiscovery.createListener(any())).thenReturn(instanceListener);
         when(serviceDiscovery.getInstances(any())).thenReturn(Collections.emptyList());
 
-        spiedMetadataService  = spy(WritableMetadataService.getDefaultExtension());
+        spiedMetadataService = spy(WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel()));
         serviceDiscoveryRegistry = new ServiceDiscoveryRegistry(registryURL, serviceDiscovery, spiedMetadataService);
     }
 
     /**
      * Test subscribe
-     *  - Normal case
-     *  - Exception case
-     *    - check=true
-     *    - check=false
+     * - Normal case
+     * - Exception case
+     * - check=true
+     * - check=false
      */
     @Test
     public void testDoSubscribe() {
-        try (MockedStatic mockStaticMapping = Mockito.mockStatic(ServiceNameMapping.class, withSettings().defaultAnswer(CALLS_REAL_METHODS))) {
-            mockStaticMapping.when(ServiceNameMapping::getDefaultExtension).thenReturn(mapping);
-            // Exception case, no interface-app mapping found
-            when(mapping.getAndListenServices(any(), any(), any())).thenReturn(Collections.emptySet());
-            // when check = false
-            try {
-                serviceDiscoveryRegistry.doSubscribe(url, testServiceListener);
-            } finally {
-                spiedMetadataService.unsubscribeURL(url);
-            }
-            // when check = true
-            URL checkURL = url.addParameter(CHECK_KEY, true);
-            Exception exceptionShouldHappen = null;
-            try {
-                serviceDiscoveryRegistry.doSubscribe(checkURL, testServiceListener);
-            } catch (IllegalStateException e) {
-                exceptionShouldHappen = e;
-            } finally {
-                spiedMetadataService.unsubscribeURL(checkURL);
-            }
-            if (exceptionShouldHappen == null) {
-                fail();
-            }
+        ApplicationModel applicationModel = spy(ApplicationModel.defaultModel());
+        when(applicationModel.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping);
+        // Exception case, no interface-app mapping found
+        when(mapping.getAndListenServices(any(), any(), any())).thenReturn(Collections.emptySet());
+        // when check = false
+        try {
+            registryURL = registryURL.setScopeModel(applicationModel);
+            serviceDiscoveryRegistry = new ServiceDiscoveryRegistry(registryURL, serviceDiscovery, spiedMetadataService);
+            serviceDiscoveryRegistry.doSubscribe(url, testServiceListener);
+        } finally {
+            registryURL = registryURL.setScopeModel(null);
+            spiedMetadataService.unsubscribeURL(url);
+        }
+        // when check = true
+        URL checkURL = url.addParameter(CHECK_KEY, true);
+        Exception exceptionShouldHappen = null;
+        try {
+            serviceDiscoveryRegistry.doSubscribe(checkURL, testServiceListener);
+        } catch (IllegalStateException e) {
+            exceptionShouldHappen = e;
+        } finally {
+            spiedMetadataService.unsubscribeURL(checkURL);
+        }
+        if (exceptionShouldHappen == null) {
+            fail();
+        }
 
-            // Normal case
-            Set singleApp = new HashSet<>();
-            singleApp.add(APP_NAME1);
-            when(mapping.getAndListenServices(any(), any(), any())).thenReturn(singleApp);
-            try {
-                serviceDiscoveryRegistry.doSubscribe(checkURL, testServiceListener);
-            } finally {
-                spiedMetadataService.unsubscribeURL(checkURL);
-            }
+        // Normal case
+        Set singleApp = new HashSet<>();
+        singleApp.add(APP_NAME1);
+        when(mapping.getAndListenServices(any(), any(), any())).thenReturn(singleApp);
+        try {
+            serviceDiscoveryRegistry.doSubscribe(checkURL, testServiceListener);
+        } finally {
+            spiedMetadataService.unsubscribeURL(checkURL);
         }
     }
 
     /**
      * Test instance listener registration
-     *  - one app
-     *  - multi apps
-     *  - repeat same multi apps, instance listener shared
-     *  - protocol included in key
-     *  - instance listener gets notified
-     *  - instance listener and service listener rightly mapped
+     * - one app
+     * - multi apps
+     * - repeat same multi apps, instance listener shared
+     * - protocol included in key
+     * - instance listener gets notified
+     * - instance listener and service listener rightly mapped
      */
     @Test
     public void testSubscribeURLs() {
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
index c002c1af5c..48a81e7060 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryTest.java
@@ -16,7 +16,10 @@
  */
 package org.apache.dubbo.registry.client;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.Page;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
@@ -46,7 +49,9 @@ public class ServiceDiscoveryTest {
             setServiceDiscovery(new InMemoryServiceDiscovery());
         }
         // test start()
-        serviceDiscovery.initialize(null);
+        URL registryUrl = URL.valueOf("");
+        registryUrl = registryUrl.setScopeModel(ApplicationModel.defaultModel());
+        serviceDiscovery.initialize(registryUrl);
     }
 
     @AfterEach
@@ -64,7 +69,7 @@ public class ServiceDiscoveryTest {
     public void testRegisterAndUpdateAndUnregister() {
 
         // register
-        DefaultServiceInstance serviceInstance = new DefaultServiceInstance("A", "127.0.0.1", 8080);
+        DefaultServiceInstance serviceInstance = new DefaultServiceInstance("A", "127.0.0.1", 8080, ApplicationModel.defaultModel());
         serviceDiscovery.register(serviceInstance);
 
         List serviceInstances = serviceDiscovery.getInstances("A");
@@ -94,9 +99,9 @@ public class ServiceDiscoveryTest {
 
     @Test
     public void testGetServices() {
-        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8080));
-        serviceDiscovery.register(new DefaultServiceInstance("B", "127.0.0.1", 8080));
-        serviceDiscovery.register(new DefaultServiceInstance("C", "127.0.0.1", 8080));
+        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())));
+        serviceDiscovery.register(new DefaultServiceInstance("B", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())));
+        serviceDiscovery.register(new DefaultServiceInstance("C", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())));
         assertEquals(new HashSet<>(asList("A", "B", "C")), serviceDiscovery.getServices());
     }
 
@@ -104,17 +109,17 @@ public class ServiceDiscoveryTest {
     public void testGetInstances() {
 
         List instances = asList(
-                new DefaultServiceInstance("A", "127.0.0.1", 8080),
-                new DefaultServiceInstance("A", "127.0.0.1", 8081),
-                new DefaultServiceInstance("A", "127.0.0.1", 8082)
+                new DefaultServiceInstance("A", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())),
+                new DefaultServiceInstance("A", "127.0.0.1", 8081, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())),
+                new DefaultServiceInstance("A", "127.0.0.1", 8082, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()))
         );
 
         instances.forEach(serviceDiscovery::register);
 
         // Duplicated
-        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8080));
+        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())));
         // Duplicated
-        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8081));
+        serviceDiscovery.register(new DefaultServiceInstance("A", "127.0.0.1", 8081, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())));
 
         // offset starts 0
         int offset = 0;
@@ -187,12 +192,12 @@ public class ServiceDiscoveryTest {
     public void testGetInstancesWithHealthy() {
 
         List instances = new LinkedList<>(asList(
-                new DefaultServiceInstance("A", "127.0.0.1", 8080),
-                new DefaultServiceInstance("A", "127.0.0.1", 8081)
+                new DefaultServiceInstance("A", "127.0.0.1", 8080, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel())),
+                new DefaultServiceInstance("A", "127.0.0.1", 8081, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()))
         ));
 
 
-        DefaultServiceInstance serviceInstance = new DefaultServiceInstance("A", "127.0.0.1", 8082);
+        DefaultServiceInstance serviceInstance = new DefaultServiceInstance("A", "127.0.0.1", 8082, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()));
         serviceInstance.setHealthy(false);
         instances.add(serviceInstance);
 
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
index 41b96e9d9c..353c93ba6a 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java
@@ -18,15 +18,17 @@ package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.configcenter.ConfigItem;
+import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.context.ConfigManager;
 import org.apache.dubbo.metadata.report.MetadataReport;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
 
+import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 import org.mockito.invocation.InvocationOnMock;
 import org.mockito.stubbing.Answer;
@@ -42,6 +44,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.when;
 
 public class MetadataServiceNameMappingTest {
@@ -50,61 +53,73 @@ public class MetadataServiceNameMappingTest {
     private URL url;
     private ConfigManager configManager;
     private MetadataReport metadataReport;
+    private ApplicationModel applicationModel;
 
     @BeforeEach
     public void setUp() {
-        mapping = new MetadataServiceNameMapping();
-        url = URL.valueOf("dubbo://127.0.0.1:20880/TestService?version=1.0.0");
+        applicationModel = new ApplicationModel(FrameworkModel.defaultModel());
         configManager = mock(ConfigManager.class);
         metadataReport = mock(MetadataReport.class);
+        mapping = new MetadataServiceNameMapping();
+        mapping.setApplicationModel(applicationModel);
+        url = URL.valueOf("dubbo://127.0.0.1:20880/TestService?version=1.0.0");
+    }
+
+    @AfterEach
+    public void teardown() {
+        applicationModel.destroy();
     }
 
     @Test
     public void testMap() {
-        try (MockedStatic mockedApplicationModel = Mockito.mockStatic(ApplicationModel.class)) {
-            when(configManager.getMetadataConfigs()).thenReturn(Collections.emptyList());
-            mockedApplicationModel.when(ApplicationModel::getConfigManager).thenReturn(configManager);
+        ApplicationModel mockedApplicationModel = spy(ApplicationModel.defaultModel());
 
-            // metadata report config not found
-            boolean result = mapping.map(url);
-            assertFalse(result);
+        when(configManager.getMetadataConfigs()).thenReturn(Collections.emptyList());
+        Mockito.when(mockedApplicationModel.getApplicationConfigManager()).thenReturn(configManager);
+        Mockito.when(mockedApplicationModel.getCurrentConfig()).thenReturn(new ApplicationConfig("test"));
 
-            try (MockedStatic mockedMetadataHolder = Mockito.mockStatic(MetadataReportInstance.class)) {
-                when(configManager.getMetadataConfigs()).thenReturn(Arrays.asList(new MetadataReportConfig()));
-                mockedMetadataHolder.when(() -> MetadataReportInstance.getMetadataReport(any())).thenReturn(metadataReport);
-                when(metadataReport.registerServiceAppMapping(any(), any(), any())).thenReturn(true);
+        // metadata report config not found
+        mapping.setApplicationModel(mockedApplicationModel);
+        boolean result = mapping.map(url);
+        assertFalse(result);
 
-                // metadata report directly
-                result = mapping.map(url);
-                assertTrue(result);
+        when(configManager.getMetadataConfigs()).thenReturn(Arrays.asList(new MetadataReportConfig()));
+        MetadataReportInstance reportInstance = mock(MetadataReportInstance.class);
+        Mockito.when(reportInstance.getMetadataReport(any())).thenReturn(metadataReport);
+        mapping.metadataReportInstance = reportInstance;
 
-                // metadata report using cas and retry, succeeded after retried 5 times
-                when(metadataReport.registerServiceAppMapping(any(), any(), any())).thenReturn(false);
-                when(metadataReport.getConfigItem(any(), any())).thenReturn(new ConfigItem());
-                when(metadataReport.registerServiceAppMapping(any(), any(), any(), any())).thenAnswer(new Answer() {
-                    private int counter = 0;
-                    @Override
-                    public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable {
-                        if (++counter == 5) {
-                            return true;
-                        }
-                        return false;
-                    }
-                });
-                assertTrue(mapping.map(url));
+        when(metadataReport.registerServiceAppMapping(any(), any(), any())).thenReturn(true);
 
-                // metadata report using cas and retry, failed after 6 times retry
-                when(metadataReport.registerServiceAppMapping(any(), any(), any(), any())).thenReturn(false);
-                Exception exceptionExpected = null;
-                try {
-                    mapping.map(url);
-                } catch (RuntimeException e) {
-                    exceptionExpected = e;
-                }
-                if (exceptionExpected == null) {
-                    fail();
+        // metadata report directly
+        result = mapping.map(url);
+        assertTrue(result);
+
+        // metadata report using cas and retry, succeeded after retried 5 times
+        when(metadataReport.registerServiceAppMapping(any(), any(), any())).thenReturn(false);
+        when(metadataReport.getConfigItem(any(), any())).thenReturn(new ConfigItem());
+        when(metadataReport.registerServiceAppMapping(any(), any(), any(), any())).thenAnswer(new Answer() {
+            private int counter = 0;
+
+            @Override
+            public Boolean answer(InvocationOnMock invocationOnMock) throws Throwable {
+                if (++counter == 5) {
+                    return true;
                 }
+                return false;
             }
+        });
+        assertTrue(mapping.map(url));
+
+        // metadata report using cas and retry, failed after 6 times retry
+        when(metadataReport.registerServiceAppMapping(any(), any(), any(), any())).thenReturn(false);
+        Exception exceptionExpected = null;
+        try {
+            mapping.map(url);
+        } catch (RuntimeException e) {
+            exceptionExpected = e;
+        }
+        if (exceptionExpected == null) {
+            fail();
         }
     }
 
@@ -115,13 +130,14 @@ public class MetadataServiceNameMappingTest {
     public void testGet() {
         Set set = new HashSet<>();
         set.add("app1");
-        try (MockedStatic mockedMetadataHolder = Mockito.mockStatic(MetadataReportInstance.class)) {
-            mockedMetadataHolder.when(() -> MetadataReportInstance.getMetadataReport(any())).thenReturn(metadataReport);
-            when(metadataReport.getServiceAppMapping(any(), any())).thenReturn(set);
 
-            Set result = mapping.get(url);
-            assertEquals(set, result);
-        }
+        MetadataReportInstance reportInstance = mock(MetadataReportInstance.class);
+        Mockito.when(reportInstance.getMetadataReport(any())).thenReturn(metadataReport);
+        when(metadataReport.getServiceAppMapping(any(), any())).thenReturn(set);
+
+        mapping.metadataReportInstance = reportInstance;
+        Set result = mapping.get(url);
+        assertEquals(set, result);
     }
 
     /**
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java
index cf6492709b..c8032b8b45 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceURLBuilderTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 /**
  * {@link MetadataServiceURLBuilder} Test
@@ -26,7 +27,7 @@ import org.apache.dubbo.registry.client.ServiceInstance;
  */
 public class MetadataServiceURLBuilderTest {
 
-    static ServiceInstance serviceInstance = new DefaultServiceInstance("127.0.0.1", "test", 8080);
+    static ServiceInstance serviceInstance = new DefaultServiceInstance("127.0.0.1", "test", 8080, ApplicationModel.defaultModel());
 
     static {
         serviceInstance.getMetadata().put("dubbo.metadata-service.urls", "[ \"dubbo://192.168.0.102:20881/com.alibaba.cloud.dubbo.service.DubboMetadataService?anyhost=true&application=spring-cloud-alibaba-dubbo-provider&bind.ip=192.168.0.102&bind.port=20881&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=spring-cloud-alibaba-dubbo-provider&interface=com.alibaba.cloud.dubbo.service.DubboMetadataService&methods=getAllServiceKeys,getServiceRestMetadata,getExportedURLs,getAllExportedURLs&pid=17134&qos.enable=false®ister=true&release=2.7.3&revision=1.0.0&side=provider×tamp=1564826098503&version=1.0.0\" ]");
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
index 1346a46aac..a402b96e37 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ProtocolPortsMetadataCustomizerTest.java
@@ -53,7 +53,7 @@ public class ProtocolPortsMetadataCustomizerTest {
     private InMemoryWritableMetadataService metadataService;
 
     public static DefaultServiceInstance createInstance() {
-        return new DefaultServiceInstance("A", "127.0.0.1", 20880);
+        return new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
     }
 
     @BeforeAll
@@ -86,7 +86,7 @@ public class ProtocolPortsMetadataCustomizerTest {
     public void test() {
         ProtocolPortsMetadataCustomizer customizer = new ProtocolPortsMetadataCustomizer();
         try (MockedStatic mockMetadataService = Mockito.mockStatic(WritableMetadataService.class)) {
-            mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension()).thenReturn(metadataService);
+            mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())).thenReturn(metadataService);
             customizer.customize(instance);
             String endpoints = instance.getMetadata().get(ENDPOINTS);
             assertNotNull(endpoints);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
index 8094a59603..a33831f0b8 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataCustomizerTest.java
@@ -48,7 +48,7 @@ public class ServiceInstanceMetadataCustomizerTest {
     private InMemoryWritableMetadataService metadataService;
 
     public static DefaultServiceInstance createInstance() {
-        return new DefaultServiceInstance("A", "127.0.0.1", 20880);
+        return new DefaultServiceInstance("A", "127.0.0.1", 20880, ApplicationModel.defaultModel());
     }
 
     @BeforeAll
@@ -81,8 +81,8 @@ public class ServiceInstanceMetadataCustomizerTest {
         ServiceInstanceMetadataCustomizer customizer = new ServiceInstanceMetadataCustomizer();
         try (MockedStatic mockedUtils = Mockito.mockStatic(ConfigurationUtils.class)) {
             try (MockedStatic mockMetadataService = Mockito.mockStatic(WritableMetadataService.class)) {
-                mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension()).thenReturn(metadataService);
-                mockedUtils.when(() -> ConfigurationUtils.getProperty(DUBBO_LABELS)).thenReturn("k1=v1;k2=v2");
+                mockMetadataService.when(() -> WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())).thenReturn(metadataService);
+                mockedUtils.when(() -> ConfigurationUtils.getProperty(ApplicationModel.defaultModel(), DUBBO_LABELS)).thenReturn("k1=v1;k2=v2");
 //            mockedUtils.when(() -> ConfigurationUtils.getProperty(DUBBO_ENV_KEYS)).thenReturn("ENV_KEY1;ENV_KEY1");
 //            mockedUtils.when(() -> ConfigurationUtils.getProperty(ENV_KEY1)).thenReturn("");
 
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java
index 33fb2868f2..9f0395db02 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/SpringCloudMetadataServiceURLBuilderTest.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.registry.client.metadata;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import org.junit.jupiter.api.Test;
 
@@ -37,7 +38,7 @@ public class SpringCloudMetadataServiceURLBuilderTest {
 
     @Test
     public void testBuild() {
-        List urls = builder.build(new DefaultServiceInstance("127.0.0.1", "test", 8080));
+        List urls = builder.build(new DefaultServiceInstance("127.0.0.1", "test", 8080, ApplicationModel.defaultModel()));
         assertEquals(0, urls.size());
 
         urls = builder.build(serviceInstance);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
index 76fcf848a7..f1ad1fb481 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/store/InMemoryMetadataServiceTest.java
@@ -69,6 +69,7 @@ public class InMemoryMetadataServiceTest {
     @Test
     public void testExport() {
         InMemoryWritableMetadataService metadataService = new InMemoryWritableMetadataService();
+        metadataService.setApplicationModel(ApplicationModel.defaultModel());
         // export normal url
         URL url = URL.valueOf("dubbo://30.225.21.30:20880/org.apache.dubbo.registry.service.DemoService?" +
             "REGISTRY_CLUSTER=registry1&anyhost=true&application=demo-provider2&delay=5000&deprecated=false&dubbo=2.0.2" +
@@ -155,6 +156,7 @@ public class InMemoryMetadataServiceTest {
     @Test
     public void testUnExport() {
         InMemoryWritableMetadataService metadataService = new InMemoryWritableMetadataService();
+        metadataService.setApplicationModel(ApplicationModel.defaultModel());
         // export normal url
         URL url = URL.valueOf("dubbo://30.225.21.30:20880/org.apache.dubbo.registry.service.DemoService?" +
             "REGISTRY_CLUSTER=registry1&anyhost=true&application=demo-provider2&delay=5000&deprecated=false&dubbo=2.0.2" +
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationInvokerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationInvokerTest.java
index 0bdf4e8825..3a4cc359cd 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationInvokerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationInvokerTest.java
@@ -39,9 +39,10 @@ import java.util.List;
 public class MigrationInvokerTest {
     @BeforeEach
     public void before() {
+        ApplicationModel.reset();
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("Test");
-        ApplicationModel.getConfigManager().setApplication(applicationConfig);
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
     }
 
     @AfterEach
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationRuleListenerTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationRuleListenerTest.java
index 10e870376b..16395d9492 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationRuleListenerTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/MigrationRuleListenerTest.java
@@ -78,11 +78,12 @@ public class MigrationRuleListenerTest {
     public void test() throws InterruptedException {
         DynamicConfiguration dynamicConfiguration = Mockito.mock(DynamicConfiguration.class);
 
-        ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
-        ApplicationModel.getEnvironment().setLocalMigrationRule(localRule);
+        ApplicationModel.reset();
+        ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration);
+        ApplicationModel.defaultModel().getApplicationEnvironment().setLocalMigrationRule(localRule);
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("demo-consumer");
-        ApplicationModel.getConfigManager().setApplication(applicationConfig);
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
 
         URL consumerURL = Mockito.mock(URL.class);
         Mockito.when(consumerURL.getServiceKey()).thenReturn("Test");
@@ -95,6 +96,7 @@ public class MigrationRuleListenerTest {
 
         MigrationInvoker migrationInvoker = Mockito.mock(MigrationInvoker.class);
         migrationRuleListener.getHandlers().put(migrationInvoker, handler);
+        migrationRuleListener.setApplicationModel(ApplicationModel.defaultModel());
 
         Thread.sleep(2000);
         Mockito.verify(handler, Mockito.timeout(5000)).doMigrate(Mockito.any());
@@ -124,6 +126,7 @@ public class MigrationRuleListenerTest {
         MigrationRuleHandler handler = Mockito.mock(MigrationRuleHandler.class, Mockito.withSettings().verboseLogging());
 
         MigrationRuleListener migrationRuleListener = new MigrationRuleListener();
+        migrationRuleListener.setApplicationModel(ApplicationModel.defaultModel());
         MigrationInvoker migrationInvoker = Mockito.mock(MigrationInvoker.class);
         migrationRuleListener.getHandlers().put(migrationInvoker, handler);
         migrationRuleListener.onRefer(null, migrationInvoker, consumerURL, null);
@@ -169,6 +172,7 @@ public class MigrationRuleListenerTest {
         // Both local rule and remote rule are here
         // Local rule with one delayed task started to apply
         MigrationRuleListener migrationRuleListener = new MigrationRuleListener();
+        migrationRuleListener.setApplicationModel(ApplicationModel.defaultModel());
         Assertions.assertNotNull(migrationRuleListener.localRuleMigrationFuture);
         Assertions.assertNull(migrationRuleListener.ruleMigrationFuture);
         MigrationInvoker migrationInvoker = Mockito.mock(MigrationInvoker.class);
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
index 31a254abd4..844ab38d15 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java
@@ -18,10 +18,12 @@ package org.apache.dubbo.registry.client.migration.model;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.metadata.ServiceNameMapping;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
 
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatchers;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
 import java.util.Collections;
@@ -32,81 +34,84 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_CLUST
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.CALLS_REAL_METHODS;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.withSettings;
 
 public class MigrationRuleTest {
     private static ServiceNameMapping mapping = mock(ServiceNameMapping.class);
 
     @Test
     public void test_parse() {
-        try (MockedStatic mockStaticMapping = Mockito.mockStatic(ServiceNameMapping.class, withSettings().defaultAnswer(CALLS_REAL_METHODS))) {
-            mockStaticMapping.when(ServiceNameMapping::getDefaultExtension).thenReturn(mapping);
-            when(mapping.getServices(any())).thenReturn(Collections.emptySet());
+        when(mapping.getServices(any())).thenReturn(Collections.emptySet());
 
-            String rule = "key: demo-consumer\n" +
-                "step: APPLICATION_FIRST\n" +
-                "threshold: 1.0\n" +
-                "proportion: 60\n" +
-                "delay: 60\n" +
-                "force: false\n" +
-                "interfaces:\n" +
-                "  - serviceKey: DemoService:1.0.0\n" +
-                "    threshold: 0.5\n" +
-                "    proportion: 30\n" +
-                "    delay: 30\n" +
-                "    force: true\n" +
-                "    step: APPLICATION_FIRST\n" +
-                "  - serviceKey: GreetingService:1.0.0\n" +
-                "    step: FORCE_APPLICATION\n" +
-                "applications:\n" +
-                "  - serviceKey: TestApplication\n" +
-                "    threshold: 0.3\n" +
-                "    proportion: 20\n" +
-                "    delay: 10\n" +
-                "    force: false\n" +
-                "    step: FORCE_INTERFACE\n";
+        String rule = "key: demo-consumer\n" +
+            "step: APPLICATION_FIRST\n" +
+            "threshold: 1.0\n" +
+            "proportion: 60\n" +
+            "delay: 60\n" +
+            "force: false\n" +
+            "interfaces:\n" +
+            "  - serviceKey: DemoService:1.0.0\n" +
+            "    threshold: 0.5\n" +
+            "    proportion: 30\n" +
+            "    delay: 30\n" +
+            "    force: true\n" +
+            "    step: APPLICATION_FIRST\n" +
+            "  - serviceKey: GreetingService:1.0.0\n" +
+            "    step: FORCE_APPLICATION\n" +
+            "applications:\n" +
+            "  - serviceKey: TestApplication\n" +
+            "    threshold: 0.3\n" +
+            "    proportion: 20\n" +
+            "    delay: 10\n" +
+            "    force: false\n" +
+            "    step: FORCE_INTERFACE\n";
 
-            MigrationRule migrationRule = MigrationRule.parse(rule);
-            assertEquals("demo-consumer", migrationRule.getKey());
-            assertEquals(MigrationStep.APPLICATION_FIRST, migrationRule.getStep());
-            assertEquals(1.0f, migrationRule.getThreshold());
-            assertEquals(60, migrationRule.getProportion());
-            assertEquals(60, migrationRule.getDelay());
-            assertEquals(false, migrationRule.getForce());
+        MigrationRule migrationRule = MigrationRule.parse(rule);
+        assertEquals("demo-consumer", migrationRule.getKey());
+        assertEquals(MigrationStep.APPLICATION_FIRST, migrationRule.getStep());
+        assertEquals(1.0f, migrationRule.getThreshold());
+        assertEquals(60, migrationRule.getProportion());
+        assertEquals(60, migrationRule.getDelay());
+        assertEquals(false, migrationRule.getForce());
 
-            URL url = Mockito.mock(URL.class);
-            Mockito.when(url.getDisplayServiceKey()).thenReturn("DemoService:1.0.0");
-            Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
-            Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
+        URL url = Mockito.mock(URL.class);
+        ModuleModel defaultModule = Mockito.spy(ApplicationModel.defaultModel().getDefaultModule());
+        Mockito.when(defaultModule.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping);
 
-            assertEquals(migrationRule.getInterfaces().size(), 2);
+        Mockito.when(url.getScopeModel()).thenReturn(defaultModule);
+        Mockito.when(url.getDisplayServiceKey()).thenReturn("DemoService:1.0.0");
+        Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
+        Mockito.when(url.getParameter(ArgumentMatchers.eq(REGISTRY_CLUSTER_TYPE_KEY), anyString())).thenReturn("default");
 
-            assertEquals(0.5f, migrationRule.getThreshold(url));
-            assertEquals(30, migrationRule.getProportion(url));
-            assertEquals(30, migrationRule.getDelay(url));
-            assertEquals(true, migrationRule.getForce(url));
-            assertEquals(MigrationStep.APPLICATION_FIRST, migrationRule.getStep(url));
+        assertEquals(migrationRule.getInterfaces().size(), 2);
 
-            Mockito.when(url.getDisplayServiceKey()).thenReturn("GreetingService:1.0.0");
-            assertEquals(1.0f, migrationRule.getThreshold(url));
-            assertEquals(60, migrationRule.getProportion(url));
-            assertEquals(60, migrationRule.getDelay(url));
-            assertEquals(false, migrationRule.getForce(url));
-            assertEquals(MigrationStep.FORCE_APPLICATION, migrationRule.getStep(url));
+        assertEquals(0.5f, migrationRule.getThreshold(url));
+        assertEquals(30, migrationRule.getProportion(url));
+        assertEquals(30, migrationRule.getDelay(url));
+        assertEquals(true, migrationRule.getForce(url));
+        assertEquals(MigrationStep.APPLICATION_FIRST, migrationRule.getStep(url));
 
-            Mockito.when(url.getDisplayServiceKey()).thenReturn("GreetingService:1.0.1");
-            Mockito.when(url.getServiceInterface()).thenReturn("GreetingService");
-            Set services =  new HashSet<>();
-            services.add("TestApplication");
-            when(mapping.getServices(any())).thenReturn(services);
-            assertEquals(0.3f, migrationRule.getThreshold(url));
-            assertEquals(20, migrationRule.getProportion(url));
-            assertEquals(10, migrationRule.getDelay(url));
-            assertEquals(false, migrationRule.getForce(url));
-            assertEquals(MigrationStep.FORCE_INTERFACE, migrationRule.getStep(url));
-        }
+        Mockito.when(url.getDisplayServiceKey()).thenReturn("GreetingService:1.0.0");
+        assertEquals(1.0f, migrationRule.getThreshold(url));
+        assertEquals(60, migrationRule.getProportion(url));
+        assertEquals(60, migrationRule.getDelay(url));
+        assertEquals(false, migrationRule.getForce(url));
+        assertEquals(MigrationStep.FORCE_APPLICATION, migrationRule.getStep(url));
+
+        Mockito.when(url.getDisplayServiceKey()).thenReturn("GreetingService:1.0.1");
+        Mockito.when(url.getServiceInterface()).thenReturn("GreetingService");
+        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(defaultModule);
+        metadataService.putCachedMapping(ServiceNameMapping.buildMappingKey(url), Collections.singleton("TestApplication"));
+
+        Set services = new HashSet<>();
+        services.add("TestApplication");
+        when(mapping.getServices(any())).thenReturn(services);
+        assertEquals(0.3f, migrationRule.getThreshold(url));
+        assertEquals(20, migrationRule.getProportion(url));
+        assertEquals(10, migrationRule.getDelay(url));
+        assertEquals(false, migrationRule.getForce(url));
+        assertEquals(MigrationStep.FORCE_INTERFACE, migrationRule.getStep(url));
+        metadataService.removeCachedMapping("GreetingService");
     }
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/integration/RegistryProtocolTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/integration/RegistryProtocolTest.java
index 9f1e6358da..14e42e97b8 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/integration/RegistryProtocolTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/integration/RegistryProtocolTest.java
@@ -35,10 +35,10 @@ import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
 import org.apache.dubbo.rpc.cluster.support.MergeableCluster;
 import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterWrapper;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
-import org.mockito.MockedStatic;
 import org.mockito.Mockito;
 
 import java.io.IOException;
@@ -47,10 +47,10 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
 import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMERS_CATEGORY;
 import static org.apache.dubbo.registry.Constants.ENABLE_CONFIGURATION_LISTEN;
@@ -59,16 +59,16 @@ import static org.apache.dubbo.remoting.Constants.CHECK_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.CONSUMER_URL_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
 import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.when;
 
 public class RegistryProtocolTest {
 
     @AfterEach
     public void tearDown() throws IOException {
         Mockito.framework().clearInlineMocks();
+        ApplicationModel.defaultModel().destroy();
     }
 
     /**
@@ -92,10 +92,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -117,7 +113,14 @@ public class RegistryProtocolTest {
         Registry registry = mock(Registry.class);
 
         RegistryProtocol registryProtocol = new RegistryProtocol();
-        registryProtocol.setRegistryFactory(registryFactory);
+
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryFactory.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getAdaptiveExtension()).thenReturn(registryFactory);
+        url = url.setScopeModel(applicationModel);
+
 
         when(registryFactory.getRegistry(registryProtocol.getRegistryUrl(url))).thenReturn(registry);
 
@@ -135,8 +138,6 @@ public class RegistryProtocolTest {
         Assertions.assertEquals(parameters.get(REGISTER_IP_KEY), consumerUrl.getHost());
         Assertions.assertFalse(consumerUrl.getAttributes().containsKey(REFER_KEY));
         Assertions.assertEquals("value1", consumerUrl.getAttribute("key1"));
-
-        applicationModelMockedStatic.closeOnDemand();
     }
 
     /**
@@ -160,10 +161,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -182,10 +179,16 @@ public class RegistryProtocolTest {
         URL url = serviceConfigURL.addAttributes(attributes);
 
         RegistryFactory registryFactory = mock(RegistryFactory.class);
-        Registry registry = mock(Registry.class);
 
         RegistryProtocol registryProtocol = new RegistryProtocol();
-        registryProtocol.setRegistryFactory(registryFactory);
+        Registry registry = mock(Registry.class);
+
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryFactory.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getAdaptiveExtension()).thenReturn(registryFactory);
+        url = url.setScopeModel(applicationModel);
 
         when(registryFactory.getRegistry(registryProtocol.getRegistryUrl(url))).thenReturn(registry);
 
@@ -204,7 +207,6 @@ public class RegistryProtocolTest {
         Assertions.assertFalse(consumerUrl.getAttributes().containsKey(REFER_KEY));
         Assertions.assertEquals("value1", consumerUrl.getAttribute("key1"));
 
-        applicationModelMockedStatic.closeOnDemand();
     }
 
     /**
@@ -232,10 +234,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -255,7 +253,12 @@ public class RegistryProtocolTest {
         Registry registry = mock(Registry.class);
 
         RegistryProtocol registryProtocol = new RegistryProtocol();
-        registryProtocol.setRegistryFactory(registryFactory);
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryFactory.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getAdaptiveExtension()).thenReturn(registryFactory);
+        url = url.setScopeModel(applicationModel);
 
         when(registryFactory.getRegistry(registryProtocol.getRegistryUrl(url))).thenReturn(registry);
 
@@ -265,8 +268,6 @@ public class RegistryProtocolTest {
         Assertions.assertTrue(((MigrationInvoker) invoker).getCluster() instanceof MockClusterWrapper);
         Assertions.assertTrue(
             ((MockClusterWrapper) ((MigrationInvoker) invoker).getCluster()).getCluster() instanceof FailoverCluster);
-
-        applicationModelMockedStatic.closeOnDemand();
     }
 
     /**
@@ -292,10 +293,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -317,7 +314,12 @@ public class RegistryProtocolTest {
         Registry registry = mock(Registry.class);
 
         RegistryProtocol registryProtocol = new RegistryProtocol();
-        registryProtocol.setRegistryFactory(registryFactory);
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryFactory.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getAdaptiveExtension()).thenReturn(registryFactory);
+        url = url.setScopeModel(applicationModel);
 
         when(registryFactory.getRegistry(registryProtocol.getRegistryUrl(url))).thenReturn(registry);
 
@@ -330,7 +332,6 @@ public class RegistryProtocolTest {
         Assertions.assertTrue(
             ((MockClusterWrapper) ((MigrationInvoker) invoker).getCluster()).getCluster() instanceof MergeableCluster);
 
-        applicationModelMockedStatic.closeOnDemand();
     }
 
     /**
@@ -356,10 +357,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -377,7 +374,6 @@ public class RegistryProtocolTest {
         attributes.put(REFER_KEY, refer);
         URL url = serviceConfigURL.addAttributes(attributes);
 
-        RegistryProtocol registryProtocol = new RegistryProtocol();
         MigrationInvoker clusterInvoker = mock(MigrationInvoker.class);
 
         Map consumerAttribute = new HashMap<>(url.getAttributes());
@@ -393,19 +389,18 @@ public class RegistryProtocolTest {
         MigrationRuleListener migrationRuleListener = mock(MigrationRuleListener.class);
         List registryProtocolListeners = new ArrayList<>();
         registryProtocolListeners.add(migrationRuleListener);
-        MockedStatic extensionLoaderMockedStatic = mockStatic(ExtensionLoader.class);
-        ExtensionLoader extensionLoaderForRegistryProtocolListener = mock(ExtensionLoader.class);
-        when(ExtensionLoader.getExtensionLoader(RegistryProtocolListener.class))
-            .thenReturn(extensionLoaderForRegistryProtocolListener);
-        when(extensionLoaderForRegistryProtocolListener.getActivateExtension(url, "registry.protocol.listener"))
+
+        RegistryProtocol registryProtocol = new RegistryProtocol();
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryProtocolListener.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getActivateExtension(url, "registry.protocol.listener"))
             .thenReturn(registryProtocolListeners);
+        url = url.setScopeModel(applicationModel);
 
         registryProtocol.interceptInvoker(clusterInvoker, url, consumerUrl, url);
         verify(migrationRuleListener, times(1)).onRefer(registryProtocol, clusterInvoker, consumerUrl, url);
-
-        extensionLoaderMockedStatic.closeOnDemand();
-        applicationModelMockedStatic.closeOnDemand();
-
     }
 
 
@@ -433,10 +428,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -472,7 +463,6 @@ public class RegistryProtocolTest {
         registryProtocol.interceptInvoker(clusterInvoker, url, consumerUrl, url);
 
         Assertions.assertEquals(1, CountRegistryProtocolListener.getReferCounter().get());
-        applicationModelMockedStatic.closeOnDemand();
     }
 
     /**
@@ -496,10 +486,6 @@ public class RegistryProtocolTest {
         when(environment.getConfiguration()).thenReturn(compositeConfiguration);
         when(environment.getDynamicGlobalConfiguration()).thenReturn(dynamicGlobalConfiguration);
 
-        MockedStatic applicationModelMockedStatic = Mockito.mockStatic(ApplicationModel.class);
-        applicationModelMockedStatic.when(ApplicationModel::getConfigManager).thenReturn(configManager);
-        applicationModelMockedStatic.when(ApplicationModel::getEnvironment).thenReturn(environment);
-
         Map parameters = new HashMap<>();
         parameters.put(INTERFACE_KEY, DemoService.class.getName());
         parameters.put("registry", "zookeeper");
@@ -520,8 +506,14 @@ public class RegistryProtocolTest {
         RegistryFactory registryFactory = mock(RegistryFactory.class);
         Registry registry = mock(Registry.class);
 
+        ApplicationModel applicationModel = Mockito.spy(ApplicationModel.defaultModel());
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("application1"));
+        ExtensionLoader extensionLoaderMock = mock(ExtensionLoader.class);
+        Mockito.when(applicationModel.getExtensionLoader(RegistryFactory.class)).thenReturn(extensionLoaderMock);
+        Mockito.when(extensionLoaderMock.getAdaptiveExtension()).thenReturn(registryFactory);
+        url = url.setScopeModel(applicationModel);
+
         RegistryProtocol registryProtocol = new RegistryProtocol();
-        registryProtocol.setRegistryFactory(registryFactory);
 
         when(registryFactory.getRegistry(registryProtocol.getRegistryUrl(url))).thenReturn(registry);
 
@@ -543,8 +535,6 @@ public class RegistryProtocolTest {
             String.valueOf(false));
 
         verify(registry,times(1)).register(registeredConsumerUrl);
-
-        applicationModelMockedStatic.closeOnDemand();
     }
 
 }
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
index e82b2b6de3..81cf61dd4f 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.NotifyListener;
 import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
 
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeEach;
@@ -83,10 +84,14 @@ public class ServiceOrientedRegistryTest {
 
     @BeforeEach
     public void init() {
+        ApplicationModel.reset();
+        ApplicationModel applicationModel = ApplicationModel.defaultModel();
+        ModuleModel scopeModel = applicationModel.getDefaultModule();
+        registryURL.setScopeModel(scopeModel);
         registry = ServiceDiscoveryRegistry.create(registryURL);
-        metadataService = WritableMetadataService.getDefaultExtension();
+        metadataService = WritableMetadataService.getDefaultExtension(scopeModel);
         notifyListener = new MyNotifyListener();
-        ApplicationModel.getConfigManager().setApplication(new ApplicationConfig("Test"));
+        applicationModel.getApplicationConfigManager().setApplication(new ApplicationConfig("Test"));
     }
 
     @AfterAll
diff --git a/dubbo-registry/dubbo-registry-dns/src/main/java/org/apache/dubbo/registry/dns/DNSServiceDiscovery.java b/dubbo-registry/dubbo-registry-dns/src/main/java/org/apache/dubbo/registry/dns/DNSServiceDiscovery.java
index a4d30d633e..8f302fbee4 100644
--- a/dubbo-registry/dubbo-registry-dns/src/main/java/org/apache/dubbo/registry/dns/DNSServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-dns/src/main/java/org/apache/dubbo/registry/dns/DNSServiceDiscovery.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedLi
 import org.apache.dubbo.registry.dns.util.DNSClientConst;
 import org.apache.dubbo.registry.dns.util.DNSResolver;
 import org.apache.dubbo.registry.dns.util.ResolveResult;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.Collections;
 import java.util.Comparator;
@@ -142,7 +143,7 @@ public class DNSServiceDiscovery extends SelfHostMetaServiceDiscovery {
         List instanceList = new LinkedList<>();
 
         for (String host : resolveResult.getHostnameList()) {
-            DefaultServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, host, port);
+            DefaultServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, host, port, ScopeModelUtil.getApplicationModel(getUrl().getScopeModel()));
             fillServiceInstance(serviceInstance);
             instanceList.add(serviceInstance);
         }
diff --git a/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java
index be8ab9eb48..c80cdaaa1d 100644
--- a/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java
@@ -30,7 +30,6 @@ import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.registry.Constants;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
-import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
@@ -38,6 +37,7 @@ import org.apache.dubbo.registry.dns.util.DNSClientConst;
 import org.apache.dubbo.registry.dns.util.DNSResolver;
 import org.apache.dubbo.registry.dns.util.ResolveResult;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import com.alibaba.fastjson.JSONObject;
 import org.junit.jupiter.api.AfterEach;
@@ -62,7 +62,7 @@ public class DNSServiceDiscoveryTest {
     public void setup() {
         DubboBootstrap.reset();
         ApplicationConfig applicationConfig = new ApplicationConfig("Test");
-        ApplicationModel.getConfigManager().setApplication(applicationConfig);
+        ApplicationModel.defaultModel().getApplicationConfigManager().setApplication(applicationConfig);
     }
 
     @AfterEach
@@ -72,19 +72,22 @@ public class DNSServiceDiscoveryTest {
 
     @Test
     public void testProvider() throws Exception {
-        ServiceDiscovery dnsServiceDiscovery = new DNSServiceDiscovery();
+        ApplicationModel applicationModel = ApplicationModel.defaultModel();
+        DNSServiceDiscovery dnsServiceDiscovery = new DNSServiceDiscovery();
+        dnsServiceDiscovery.setApplicationModel(applicationModel);
 
         URL registryURL = URL.valueOf("dns://");
+        registryURL.setScopeModel(ApplicationModel.defaultModel());
         dnsServiceDiscovery.initialize(registryURL);
 
         assertEquals(registryURL, dnsServiceDiscovery.getUrl());
 
-        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "localhost", 12345);
+        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "localhost", 12345, ScopeModelUtil.getApplicationModel(dnsServiceDiscovery.getUrl().getScopeModel()));
         serviceInstance.getMetadata().put("a", "b");
 
         dnsServiceDiscovery.register(serviceInstance);
 
-        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
+        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(applicationModel);
         InstanceMetadataChangedListener changeListener = Mockito.mock(InstanceMetadataChangedListener.class);
 
         String metadataString = metadataService
@@ -106,23 +109,26 @@ public class DNSServiceDiscoveryTest {
 
     @Test
     public void testConsumer() throws Exception {
+        ApplicationModel applicationModel = ApplicationModel.defaultModel();
         DNSServiceDiscovery dnsServiceDiscovery = new DNSServiceDiscovery();
+        dnsServiceDiscovery.setApplicationModel(applicationModel);
 
         URL registryURL = URL.valueOf("dns://")
                 .addParameter(DNSClientConst.DNS_POLLING_CYCLE, 100)
                 .addParameter(Constants.ECHO_POLLING_CYCLE_KEY, 100);
-        ApplicationModel.getEnvironment().getAppExternalConfigMap()
+        registryURL.setScopeModel(ApplicationModel.defaultModel());
+        applicationModel.getApplicationEnvironment().getAppExternalConfigMap()
                 .put(METADATA_PROXY_TIMEOUT_KEY, String.valueOf(500));
         dnsServiceDiscovery.initialize(registryURL);
 
-        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension();
-        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "localhost", 12345);
+        WritableMetadataService metadataService = WritableMetadataService.getDefaultExtension(applicationModel);
+        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "localhost", 12345, ScopeModelUtil.getApplicationModel(dnsServiceDiscovery.getUrl().getScopeModel()));
         serviceInstance.getMetadata().put("a", "b");
 
         dnsServiceDiscovery.register(serviceInstance);
 
         int port = NetUtils.getAvailablePort();
-        ApplicationModel.getApplicationConfig().setMetadataServicePort(port);
+        applicationModel.getCurrentConfig().setMetadataServicePort(port);
 
         WritableMetadataService spiedMetadataService = Mockito.spy(metadataService);
 
@@ -164,7 +170,7 @@ public class DNSServiceDiscoveryTest {
         serviceConfig.unexport();
 
         dnsServiceDiscovery.destroy();
-        ApplicationModel.getEnvironment().getAppExternalConfigMap()
+        applicationModel.getApplicationEnvironment().getAppExternalConfigMap()
                 .remove(METADATA_PROXY_TIMEOUT_KEY);
     }
 
diff --git a/dubbo-registry/dubbo-registry-kubernetes/src/main/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscovery.java b/dubbo-registry/dubbo-registry-kubernetes/src/main/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscovery.java
index 0f61a57b48..f9d58f6243 100644
--- a/dubbo-registry/dubbo-registry-kubernetes/src/main/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-kubernetes/src/main/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscovery.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.registry.kubernetes.util.KubernetesClientConst;
 import org.apache.dubbo.registry.kubernetes.util.KubernetesConfigUtils;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import com.alibaba.fastjson.JSONObject;
 import io.fabric8.kubernetes.api.model.EndpointAddress;
@@ -362,7 +363,7 @@ public class KubernetesServiceDiscovery extends AbstractServiceDiscovery {
                 }
 
                 instancePorts.forEach(port -> {
-                    ServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, ip, port);
+                    ServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, ip, port, ScopeModelUtil.getApplicationModel(getUrl().getScopeModel()));
 
                     String properties = pod.getMetadata().getAnnotations().get(KUBERNETES_PROPERTIES_KEY);
                     if (StringUtils.isNotEmpty(properties)) {
diff --git a/dubbo-registry/dubbo-registry-kubernetes/src/test/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-kubernetes/src/test/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscoveryTest.java
index 4dc43e8290..0fc62fd4a6 100644
--- a/dubbo-registry/dubbo-registry-kubernetes/src/test/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-kubernetes/src/test/java/org/apache/dubbo/registry/kubernetes/KubernetesServiceDiscoveryTest.java
@@ -22,6 +22,8 @@ import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.registry.kubernetes.util.KubernetesClientConst;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import io.fabric8.kubernetes.api.model.Endpoints;
 import io.fabric8.kubernetes.api.model.EndpointsBuilder;
@@ -66,6 +68,7 @@ public class KubernetesServiceDiscoveryTest {
                 .setProtocol("kubernetes")
                 .addParameter(KubernetesClientConst.USE_HTTPS, "false")
                 .addParameter(KubernetesClientConst.HTTP2_DISABLE, "true");
+        serverUrl.setScopeModel(ApplicationModel.defaultModel());
 
         System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
         System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
@@ -107,7 +110,7 @@ public class KubernetesServiceDiscoveryTest {
         serviceDiscovery.setCurrentHostname("TestServer");
         serviceDiscovery.setKubernetesClient(mockClient);
 
-        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345);
+        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()));
         serviceDiscovery.register(serviceInstance);
 
         HashSet serviceList = new HashSet<>(4);
@@ -146,7 +149,7 @@ public class KubernetesServiceDiscoveryTest {
         serviceDiscovery.setCurrentHostname("TestServer");
         serviceDiscovery.setKubernetesClient(mockClient);
 
-        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345);
+        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()));
         serviceDiscovery.register(serviceInstance);
 
         HashSet serviceList = new HashSet<>(4);
@@ -156,7 +159,7 @@ public class KubernetesServiceDiscoveryTest {
 
         serviceDiscovery.addServiceInstancesChangedListener(mockListener);
 
-        serviceInstance = new DefaultServiceInstance("TestService", "Test12345", 12345);
+        serviceInstance = new DefaultServiceInstance("TestService", "Test12345", 12345, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()));
         serviceDiscovery.update(serviceInstance);
 
         Thread.sleep(5000);
@@ -178,7 +181,7 @@ public class KubernetesServiceDiscoveryTest {
         serviceDiscovery.setCurrentHostname("TestServer");
         serviceDiscovery.setKubernetesClient(mockClient);
 
-        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345);
+        ServiceInstance serviceInstance = new DefaultServiceInstance("TestService", "Test", 12345, ScopeModelUtil.getApplicationModel(serviceDiscovery.getUrl().getScopeModel()));
         serviceDiscovery.register(serviceInstance);
 
         serviceDiscovery.update(serviceInstance);
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
index 67f4c8911a..0048ca71ec 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosServiceDiscovery.java
@@ -110,8 +110,8 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
     @Override
     public List getInstances(String serviceName) throws NullPointerException {
         return ThrowableFunction.execute(namingService, service ->
-                service.selectInstances(serviceName, Constants.DEFAULT_GROUP, true)
-                        .stream().map(NacosNamingServiceUtils::toServiceInstance)
+            service.selectInstances(serviceName, Constants.DEFAULT_GROUP, true)
+                .stream().map((i)->NacosNamingServiceUtils.toServiceInstance(registryURL, i))
                         .collect(Collectors.toList())
         );
     }
@@ -144,7 +144,7 @@ public class NacosServiceDiscovery extends AbstractServiceDiscovery {
         String serviceName = event.getServiceName();
         List serviceInstances = event.getInstances()
                 .stream()
-                .map(NacosNamingServiceUtils::toServiceInstance)
+                .map((i)->NacosNamingServiceUtils.toServiceInstance(registryURL, i))
                 .collect(Collectors.toList());
         listener.onEvent(new ServiceInstancesChangedEvent(serviceName, serviceInstances));
     }
diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
index 9136eeeb3a..5ebe4ca97f 100644
--- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
+++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/util/NacosNamingServiceUtils.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.nacos.NacosNamingServiceWrapper;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import com.alibaba.nacos.api.NacosFactory;
 import com.alibaba.nacos.api.PropertyKeyConst;
@@ -75,8 +76,12 @@ public class NacosNamingServiceUtils {
      * @return non-null
      * @since 2.7.5
      */
-    public static ServiceInstance toServiceInstance(Instance instance) {
-        DefaultServiceInstance serviceInstance = new DefaultServiceInstance(NamingUtils.getServiceName(instance.getServiceName()), instance.getIp(), instance.getPort());
+    public static ServiceInstance toServiceInstance(URL registryUrl, Instance instance) {
+        DefaultServiceInstance serviceInstance =
+            new DefaultServiceInstance(
+                NamingUtils.getServiceName(instance.getServiceName()),
+                instance.getIp(), instance.getPort(),
+                ScopeModelUtil.getApplicationModel(registryUrl.getScopeModel()));
         serviceInstance.setMetadata(instance.getMetadata());
         serviceInstance.setEnabled(instance.isEnabled());
         serviceInstance.setHealthy(instance.isHealthy());
diff --git a/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/XdsServiceDiscovery.java b/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/XdsServiceDiscovery.java
index a2bded3db1..7765f7c18c 100644
--- a/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/XdsServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/XdsServiceDiscovery.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
 import org.apache.dubbo.registry.xds.util.PilotExchanger;
 import org.apache.dubbo.registry.xds.util.protocol.message.Endpoint;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.Collection;
 import java.util.Comparator;
@@ -74,7 +75,7 @@ public class XdsServiceDiscovery extends SelfHostMetaServiceDiscovery {
         List instances = new LinkedList<>();
         endpoints.forEach(endpoint -> {
             try {
-                DefaultServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, endpoint.getAddress(), endpoint.getPortValue());
+                DefaultServiceInstance serviceInstance = new DefaultServiceInstance(serviceName, endpoint.getAddress(), endpoint.getPortValue(), ScopeModelUtil.getApplicationModel(getUrl().getScopeModel()));
                 // fill metadata by SelfHostMetaServiceDiscovery, will be fetched by RPC request
                 fillServiceInstance(serviceInstance);
                 instances.add(serviceInstance);
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
index 45da52c7f8..403741ec5f 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscovery.java
@@ -119,7 +119,7 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
 
     @Override
     public List getInstances(String serviceName) throws NullPointerException {
-        return doInServiceDiscovery(s -> build(s.queryForInstances(serviceName)));
+        return doInServiceDiscovery(s -> build(registryURL, s.queryForInstances(serviceName)));
     }
 
     @Override
@@ -148,7 +148,7 @@ public class ZookeeperServiceDiscovery extends AbstractServiceDiscovery {
                 for (int i = 0; i < pageSize; i++) {
                     if (iterator.hasNext()) {
                         String serviceId = iterator.next();
-                        ServiceInstance serviceInstance = build(serviceDiscovery.queryForInstance(serviceName, serviceId));
+                        ServiceInstance serviceInstance = build(registryURL, serviceDiscovery.queryForInstance(serviceName, serviceId));
                         serviceInstances.add(serviceInstance);
                     }
                 }
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java
index 2e45589fb5..83d2333ff2 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.registry.client.ServiceDiscovery;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import org.apache.curator.framework.api.CuratorWatcher;
 import org.apache.zookeeper.WatchedEvent;
@@ -31,7 +32,6 @@ import java.util.List;
 import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 
-import static org.apache.dubbo.rpc.model.ApplicationModel.getExecutorRepository;
 import static org.apache.zookeeper.Watcher.Event.EventType.NodeChildrenChanged;
 import static org.apache.zookeeper.Watcher.Event.EventType.NodeDataChanged;
 
@@ -65,10 +65,11 @@ public class ZookeeperServiceDiscoveryChangeWatcher implements CuratorWatcher {
         this.serviceName = serviceName;
         this.path = path;
         this.latch = latch;
-        this.notifier = new RegistryNotifier(zookeeperServiceDiscovery.getDelay(), getExecutorRepository().getServiceDiscoveryAddressNotificationExecutor()) {
+        this.notifier = new RegistryNotifier(zookeeperServiceDiscovery.getDelay(),
+            ScopeModelUtil.getApplicationModel(zookeeperServiceDiscovery.getUrl().getScopeModel()).getApplicationExecutorRepository().getServiceDiscoveryAddressNotificationExecutor()) {
             @Override
             protected void doNotify(Object rawAddresses) {
-                listeners.forEach(listener -> listener.onEvent((ServiceInstancesChangedEvent)rawAddresses));
+                listeners.forEach(listener -> listener.onEvent((ServiceInstancesChangedEvent) rawAddresses));
             }
         };
     }
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
index d9e137c9ee..97e471f7e9 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/util/CuratorFrameworkUtils.java
@@ -16,15 +16,16 @@
  */
 package org.apache.dubbo.registry.zookeeper.util;
 
-import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
 import org.apache.dubbo.registry.zookeeper.ZookeeperInstance;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import org.apache.curator.RetryPolicy;
 import org.apache.curator.framework.CuratorFramework;
 import org.apache.curator.framework.CuratorFrameworkFactory;
+import org.apache.curator.framework.imps.CuratorFrameworkState;
 import org.apache.curator.retry.ExponentialBackoffRetry;
 import org.apache.curator.x.discovery.ServiceDiscovery;
 import org.apache.curator.x.discovery.ServiceDiscoveryBuilder;
@@ -84,17 +85,17 @@ public abstract class CuratorFrameworkUtils {
     }
 
 
-    public static List build(Collection>
-                                                  instances) {
-        return instances.stream().map(CuratorFrameworkUtils::build).collect(Collectors.toList());
+    public static List build(URL registryUrl, Collection>
+        instances) {
+        return instances.stream().map((i)->build(registryUrl, i)).collect(Collectors.toList());
     }
 
-    public static ServiceInstance build(org.apache.curator.x.discovery.ServiceInstance instance) {
+    public static ServiceInstance build(URL registryUrl, org.apache.curator.x.discovery.ServiceInstance instance) {
         String name = instance.getName();
         String host = instance.getAddress();
         int port = instance.getPort();
         ZookeeperInstance zookeeperInstance = instance.getPayload();
-        DefaultServiceInstance serviceInstance = new DefaultServiceInstance(name, host, port);
+        DefaultServiceInstance serviceInstance = new DefaultServiceInstance(name, host, port, ScopeModelUtil.getApplicationModel(registryUrl.getScopeModel()));
         serviceInstance.setMetadata(zookeeperInstance.getMetadata());
         return serviceInstance;
     }
diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
index ae067cc085..378beeebed 100644
--- a/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
+++ b/dubbo-registry/dubbo-registry-zookeeper/src/test/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryTest.java
@@ -21,10 +21,12 @@ import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.common.utils.Page;
 import org.apache.dubbo.registry.client.DefaultServiceInstance;
 import org.apache.dubbo.registry.client.ServiceInstance;
-
-import org.apache.curator.test.TestingServer;
 import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
 import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
+import org.apache.curator.test.TestingServer;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
@@ -67,6 +69,7 @@ public class ZookeeperServiceDiscoveryTest {
         zkServer.start();
 
         this.registryUrl = URL.valueOf("zookeeper://127.0.0.1:" + zkServerPort);
+        registryUrl.setScopeModel(ApplicationModel.defaultModel());
         this.discovery = new ZookeeperServiceDiscovery();
         this.discovery.initialize(registryUrl);
     }
@@ -108,7 +111,7 @@ public class ZookeeperServiceDiscoveryTest {
     }
 
     private DefaultServiceInstance createServiceInstance(String serviceName, String host, int port) {
-        return new DefaultServiceInstance(serviceName, host, port);
+        return new DefaultServiceInstance(serviceName, host, port, ScopeModelUtil.getApplicationModel(registryUrl.getScopeModel()));
     }
 
     @Test
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java
index b1fb112d6a..14fa5d043e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/ChannelHandler.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.remoting;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 
@@ -25,7 +26,7 @@ import org.apache.dubbo.common.extension.SPI;
  * @see org.apache.dubbo.remoting.Transporter#bind(org.apache.dubbo.common.URL, ChannelHandler)
  * @see org.apache.dubbo.remoting.Transporter#connect(org.apache.dubbo.common.URL, ChannelHandler)
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ChannelHandler {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec.java
index ad4098e442..ee0dcad885 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.remoting;
 
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import java.io.IOException;
@@ -27,7 +28,7 @@ import java.io.OutputStream;
  * Codec. (SPI, Singleton, ThreadSafe)
  */
 @Deprecated
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface Codec {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec2.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec2.java
index f851b46617..a862cae615 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec2.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Codec2.java
@@ -17,12 +17,13 @@
 package org.apache.dubbo.remoting;
 
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.buffer.ChannelBuffer;
 
 import java.io.IOException;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface Codec2 {
 
     @Adaptive({Constants.CODEC_KEY})
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Dispatcher.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Dispatcher.java
index c67f33e74f..6f6f88f2e5 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Dispatcher.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Dispatcher.java
@@ -18,13 +18,14 @@ package org.apache.dubbo.remoting;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.transport.dispatcher.all.AllDispatcher;
 
 /**
  * ChannelHandlerWrapper (SPI, Singleton, ThreadSafe)
  */
-@SPI(AllDispatcher.NAME)
+@SPI(value = AllDispatcher.NAME, scope = ExtensionScope.FRAMEWORK)
 public interface Dispatcher {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
index 9bee120153..3b4ba462a8 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporter.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.remoting;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
@@ -28,7 +29,7 @@ import org.apache.dubbo.common.extension.SPI;
  *
  * @see org.apache.dubbo.remoting.Transporters
  */
-@SPI("netty")
+@SPI(value = "netty", scope = ExtensionScope.FRAMEWORK)
 public interface Transporter {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
index 4143c9d1ce..7095b13b9a 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
@@ -17,12 +17,13 @@
 package org.apache.dubbo.remoting.api;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.RemotingException;
 
 import java.util.function.Consumer;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ConnectionManager {
 
     Connection connect(URL url) throws RemotingException;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/NettyEventLoopFactory.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/NettyEventLoopFactory.java
index d6e2698902..5fb50153cd 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/NettyEventLoopFactory.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/NettyEventLoopFactory.java
@@ -16,9 +16,7 @@
  */
 package org.apache.dubbo.remoting.api;
 
-import org.apache.dubbo.common.config.Configuration;
 import org.apache.dubbo.remoting.Constants;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.epoll.Epoll;
@@ -55,9 +53,8 @@ public class NettyEventLoopFactory {
     }
 
     private static boolean shouldEpoll() {
-        Configuration configuration = ApplicationModel.getEnvironment().getConfiguration();
-        if (configuration.getBoolean("netty.epoll.enable", false)) {
-            String osName = configuration.getString("os.name");
+        if (Boolean.parseBoolean(System.getProperty("netty.epoll.enable", "false"))) {
+            String osName = System.getProperty("os.name");
             return osName.toLowerCase().contains("linux") && Epoll.isAvailable();
         }
 
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java
index 41d343ba1a..71d8d87da7 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.config.SslConfig;
 import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import io.netty.handler.ssl.ClientAuth;
 import io.netty.handler.ssl.OpenSsl;
@@ -39,7 +39,7 @@ public class SslContexts {
     private static final Logger logger = LoggerFactory.getLogger(SslContexts.class);
 
     public static SslContext buildServerSslContext(URL url) {
-        ConfigManager globalConfigManager = ApplicationModel.getConfigManager();
+        ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager();
         SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!"));
 
         SslContextBuilder sslClientContextBuilder;
@@ -68,7 +68,7 @@ public class SslContexts {
     }
 
     public static SslContext buildClientSslContext(URL url) {
-        ConfigManager globalConfigManager = ApplicationModel.getConfigManager();
+        ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager();
         SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!"));
 
         SslContextBuilder builder = SslContextBuilder.forClient();
@@ -97,10 +97,6 @@ public class SslContexts {
         }
     }
 
-    private static SslConfig getSslConfig() {
-        return ApplicationModel.getConfigManager().getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!"));
-    }
-
     /**
      * Returns OpenSSL if available, otherwise returns the JDK provider.
      */
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/WireProtocol.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/WireProtocol.java
index ae9ab84ba1..de6cd324a3 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/WireProtocol.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/WireProtocol.java
@@ -16,12 +16,13 @@
  */
 package org.apache.dubbo.remoting.api;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import io.netty.channel.ChannelPipeline;
 import io.netty.handler.ssl.SslContext;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface WireProtocol {
 
     ProtocolDetector detector();
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java
index d7c321d454..9b94db8bd7 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchanger.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.remoting.exchange;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.Constants;
 import org.apache.dubbo.remoting.RemotingException;
@@ -29,7 +30,7 @@ import org.apache.dubbo.remoting.exchange.support.header.HeaderExchanger;
  * Message Exchange Pattern
  * Request-Response
  */
-@SPI(HeaderExchanger.NAME)
+@SPI(value = HeaderExchanger.NAME, scope = ExtensionScope.FRAMEWORK)
 public interface Exchanger {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
index 552c61bf46..0063576e04 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/codec/ExchangeCodec.java
@@ -429,7 +429,7 @@ public class ExchangeCodec extends TelnetCodec {
         try {
             if (eventBytes != null) {
                 int dataLen = eventBytes.length;
-                int threshold = ConfigurationUtils.getSystemConfiguration().getInt("deserialization.event.size", 50);
+                int threshold = ConfigurationUtils.getSystemConfiguration(channel.getUrl().getScopeModel()).getInt("deserialization.event.size", 50);
                 if (dataLen > threshold) {
                     throw new IllegalArgumentException("Event data too long, actual size " + threshold + ", threshold " + threshold + " rejected for security consideration.");
                 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java
index 8bfc7fd56a..fe3acb776c 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/telnet/TelnetHandler.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.remoting.telnet;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.Channel;
 import org.apache.dubbo.remoting.RemotingException;
@@ -23,7 +24,7 @@ import org.apache.dubbo.remoting.RemotingException;
 /**
  * TelnetHandler
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface TelnetHandler {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
index 6db207b952..0995a1c9ca 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java
@@ -158,7 +158,8 @@ public class CodecSupport {
     }
 
     public static void checkSerialization(String path, String version, Byte id) throws IOException {
-        ServiceRepository repository = ApplicationModel.getServiceRepository();
+        // TODO: fetch from FrameworkModel
+        ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
         Set urls = repository.lookupRegisteredProviderUrlsWithoutGroup(keyWithoutGroup(path, version));
         if (CollectionUtils.isEmpty(urls)) {
             throw new IOException("Service " + path + " with version " + version + " not found, invocation rejected.");
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/zookeeper/ZookeeperTransporter.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/zookeeper/ZookeeperTransporter.java
index 2b360f1452..136d8d3472 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/zookeeper/ZookeeperTransporter.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/zookeeper/ZookeeperTransporter.java
@@ -18,11 +18,12 @@ package org.apache.dubbo.remoting.zookeeper;
 
 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;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ZookeeperTransporter {
 
     String CURATOR_5 = "curator5";
diff --git a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpBinder.java b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpBinder.java
index 031139dff1..338283b482 100644
--- a/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpBinder.java
+++ b/dubbo-remoting/dubbo-remoting-http/src/main/java/org/apache/dubbo/remoting/http/HttpBinder.java
@@ -18,13 +18,14 @@ package org.apache.dubbo.remoting.http;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.remoting.Constants;
 
 /**
  * HttpBinder
  */
-@SPI("jetty")
+@SPI(value = "jetty", scope = ExtensionScope.FRAMEWORK)
 public interface HttpBinder {
 
     /**
diff --git a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyEventLoopFactory.java b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyEventLoopFactory.java
index f9c56804fd..eb97078aa5 100644
--- a/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyEventLoopFactory.java
+++ b/dubbo-remoting/dubbo-remoting-netty4/src/main/java/org/apache/dubbo/remoting/transport/netty4/NettyEventLoopFactory.java
@@ -16,9 +16,6 @@
  */
 package org.apache.dubbo.remoting.transport.netty4;
 
-import org.apache.dubbo.common.config.Configuration;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
 import io.netty.channel.EventLoopGroup;
 import io.netty.channel.epoll.Epoll;
 import io.netty.channel.epoll.EpollEventLoopGroup;
@@ -49,9 +46,8 @@ public class NettyEventLoopFactory {
     }
 
     private static boolean shouldEpoll() {
-        Configuration configuration = ApplicationModel.getEnvironment().getConfiguration();
-        if (configuration.getBoolean("netty.epoll.enable", false)) {
-            String osName = configuration.getString("os.name");
+        if (Boolean.parseBoolean(System.getProperty("netty.epoll.enable", "false"))) {
+            String osName = System.getProperty("os.name");
             return osName.toLowerCase().contains("linux") && Epoll.isAvailable();
         }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java
index d20cc1bedc..68197469b4 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ExporterListener.java
@@ -16,12 +16,13 @@
  */
 package org.apache.dubbo.rpc;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
  * ExporterListener. (SPI, Singleton, ThreadSafe)
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ExporterListener {
 
     /**
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
index bedd350af1..19a0434cfc 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java
@@ -17,6 +17,7 @@
 package org.apache.dubbo.rpc;
 
 import org.apache.dubbo.common.Experimental;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.util.Map;
 import java.util.stream.Stream;
@@ -138,6 +139,10 @@ public interface Invocation {
      */
     Invoker getInvoker();
 
+    void setServiceModel(ServiceModel serviceModel);
+
+    ServiceModel getServiceModel();
+
     Object put(Object key, Object value);
 
     Object get(Object key);
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
index 5f86ec5901..838801dbfc 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Protocol.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.rpc;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import java.util.Collections;
@@ -26,7 +27,7 @@ import java.util.List;
 /**
  * Protocol. (API/SPI, Singleton, ThreadSafe)
  */
-@SPI("dubbo")
+@SPI(value = "dubbo", scope = ExtensionScope.FRAMEWORK)
 public interface Protocol {
 
     /**
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java
index f7e607f11f..dcd51ac092 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/ProxyFactory.java
@@ -20,12 +20,13 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
 import org.apache.dubbo.common.extension.SPI;
 
+import static org.apache.dubbo.common.extension.ExtensionScope.FRAMEWORK;
 import static org.apache.dubbo.rpc.Constants.PROXY_KEY;
 
 /**
  * ProxyFactory. (API/SPI, Singleton, ThreadSafe)
  */
-@SPI("javassist")
+@SPI(value = "javassist", scope = FRAMEWORK)
 public interface ProxyFactory {
 
     /**
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
index 4dccbabd9c..eb1af936c5 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/RpcInvocation.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.MethodDescriptor;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
+import org.apache.dubbo.rpc.model.ServiceModel;
 import org.apache.dubbo.rpc.model.ServiceRepository;
 import org.apache.dubbo.rpc.support.RpcUtils;
 
@@ -54,6 +55,7 @@ public class RpcInvocation implements Invocation, Serializable {
     private String targetServiceUniqueName;
     private String protocolServiceKey;
 
+    private ServiceModel serviceModel;
     private String methodName;
     private String serviceName;
 
@@ -85,7 +87,7 @@ public class RpcInvocation implements Invocation, Serializable {
     }
 
     public RpcInvocation(Invocation invocation, Invoker invoker) {
-        this(invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(),
+        this(invocation.getServiceModel(), invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(),
                 invocation.getParameterTypes(), invocation.getArguments(), new LinkedHashMap<>(invocation.getObjectAttachments()),
                 invocation.getInvoker(), invocation.getAttributes());
         if (invoker != null) {
@@ -115,29 +117,56 @@ public class RpcInvocation implements Invocation, Serializable {
     }
 
     public RpcInvocation(Invocation invocation) {
-        this(invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(), invocation.getParameterTypes(),
+        this(invocation.getServiceModel(), invocation.getMethodName(), invocation.getServiceName(), invocation.getProtocolServiceKey(), invocation.getParameterTypes(),
                 invocation.getArguments(), invocation.getObjectAttachments(), invocation.getInvoker(), invocation.getAttributes());
         this.targetServiceUniqueName = invocation.getTargetServiceUniqueName();
     }
 
+    public RpcInvocation(ServiceModel serviceModel, Method method, String serviceName, String protocolServiceKey, Object[] arguments) {
+        this(serviceModel, method, serviceName, protocolServiceKey, arguments, null, null);
+    }
+
+    @Deprecated
     public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments) {
-        this(method, serviceName, protocolServiceKey, arguments, null, null);
+        this(null, method, serviceName, protocolServiceKey, arguments, null, null);
     }
 
+    public RpcInvocation(ServiceModel serviceModel, Method method, String serviceName, String protocolServiceKey, Object[] arguments, Map attachment, Map attributes) {
+        this(serviceModel, method.getName(), serviceName, protocolServiceKey, method.getParameterTypes(), arguments, attachment, null, attributes);
+    }
+
+    @Deprecated
     public RpcInvocation(Method method, String serviceName, String protocolServiceKey, Object[] arguments, Map attachment, Map attributes) {
-        this(method.getName(), serviceName, protocolServiceKey, method.getParameterTypes(), arguments, attachment, null, attributes);
+        this(null, method.getName(), serviceName, protocolServiceKey, method.getParameterTypes(), arguments, attachment, null, attributes);
     }
 
+    public RpcInvocation(ServiceModel serviceModel, String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments) {
+        this(serviceModel, methodName, serviceName, protocolServiceKey, parameterTypes, arguments, null, null, null);
+    }
+
+    @Deprecated
     public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments) {
-        this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, null, null, null);
+        this(null, methodName, serviceName, protocolServiceKey, parameterTypes, arguments, null, null, null);
     }
 
+    public RpcInvocation(ServiceModel serviceModel, String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments, Map attachments) {
+        this(serviceModel, methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, null, null);
+    }
+
+    @Deprecated
     public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments, Map attachments) {
-        this(methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, null, null);
+        this(null, methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, null, null);
     }
 
+    @Deprecated
     public RpcInvocation(String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments,
                          Map attachments, Invoker invoker, Map attributes) {
+        this(null, methodName, serviceName, protocolServiceKey, parameterTypes, arguments, attachments, invoker, attributes);
+    }
+
+    public RpcInvocation(ServiceModel serviceModel, String methodName, String serviceName, String protocolServiceKey, Class[] parameterTypes, Object[] arguments,
+                         Map attachments, Invoker invoker, Map attributes) {
+        this.serviceModel = serviceModel;
         this.methodName = methodName;
         this.serviceName = serviceName;
         this.protocolServiceKey = protocolServiceKey;
@@ -150,20 +179,25 @@ public class RpcInvocation implements Invocation, Serializable {
     }
 
     private void initParameterDesc() {
-        ServiceRepository repository = ApplicationModel.getServiceRepository();
-        if (StringUtils.isNotEmpty(serviceName)) {
-            ServiceDescriptor serviceDescriptor = repository.lookupService(serviceName);
-            if (serviceDescriptor != null) {
-                MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(methodName, parameterTypes);
-                if (methodDescriptor != null) {
-                    this.parameterTypesDesc = methodDescriptor.getParamDesc();
-                    this.compatibleParamSignatures = methodDescriptor.getCompatibleParamSignatures();
-                    this.returnTypes = methodDescriptor.getReturnTypes();
-                    this.returnType = methodDescriptor.getReturnClass();
-                }
+        ServiceDescriptor serviceDescriptor = null;
+        if (serviceModel != null) {
+            serviceDescriptor = serviceModel.getServiceModel();
+        } else if (StringUtils.isNotEmpty(serviceName)){
+            ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
+            serviceDescriptor = repository.lookupService(serviceName);
+        }
+
+        if (serviceDescriptor != null) {
+            MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(methodName, parameterTypes);
+            if (methodDescriptor != null) {
+                this.parameterTypesDesc = methodDescriptor.getParamDesc();
+                this.compatibleParamSignatures = methodDescriptor.getCompatibleParamSignatures();
+                this.returnTypes = methodDescriptor.getReturnTypes();
+                this.returnType = methodDescriptor.getReturnClass();
             }
         }
 
+
         if (parameterTypesDesc == null) {
             this.parameterTypesDesc = ReflectUtils.getDesc(this.getParameterTypes());
             this.compatibleParamSignatures = Stream.of(this.parameterTypes).map(Class::getName).toArray(String[]::new);
@@ -451,6 +485,16 @@ public class RpcInvocation implements Invocation, Serializable {
         this.invokeMode = invokeMode;
     }
 
+    @Override
+    public void setServiceModel(ServiceModel serviceModel) {
+        this.serviceModel = serviceModel;
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return serviceModel;
+    }
+
     @Override
     public String toString() {
         return "RpcInvocation [methodName=" + methodName + ", parameterTypes="
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
index 41bc2d1471..73f529798e 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java
@@ -39,6 +39,7 @@ import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelAware;
 import org.apache.dubbo.rpc.service.GenericException;
 import org.apache.dubbo.rpc.service.GenericService;
 import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -64,9 +65,16 @@ import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
  * GenericInvokerFilter.
  */
 @Activate(group = CommonConstants.PROVIDER, order = -20000)
-public class GenericFilter implements Filter, Filter.Listener {
+public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware {
     private final Logger logger = LoggerFactory.getLogger(GenericFilter.class);
 
+    private ApplicationModel applicationModel;
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+    }
+
     @Override
     public Result invoke(Invoker invoker, Invocation inv) throws RpcException {
         if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
@@ -108,7 +116,7 @@ public class GenericFilter implements Filter, Filter.Listener {
                 } else if (ProtocolUtils.isGsonGenericSerialization(generic)) {
                     args = getGsonGenericArgs(args, method.getGenericParameterTypes());
                 } else if (ProtocolUtils.isJavaGenericSerialization(generic)) {
-                    Configuration configuration = ApplicationModel.getEnvironment().getConfiguration();
+                    Configuration configuration = ApplicationModel.ofNullable(applicationModel).getApplicationEnvironment().getConfiguration();
                     if (!configuration.getBoolean(CommonConstants.ENABLE_NATIVE_JAVA_GENERIC_SERIALIZE, false)) {
                         String notice = "Trigger the safety barrier! " +
                                 "Native Java Serializer is not allowed by default." +
@@ -176,7 +184,7 @@ public class GenericFilter implements Filter, Filter.Listener {
                 }
 
                 RpcInvocation rpcInvocation =
-                        new RpcInvocation(method, invoker.getInterface().getName(), invoker.getUrl().getProtocolServiceKey(), args,
+                        new RpcInvocation(invoker.getUrl().getServiceModel(), method, invoker.getInterface().getName(), invoker.getUrl().getProtocolServiceKey(), args,
                                 inv.getObjectAttachments(), inv.getAttributes());
                 rpcInvocation.setInvoker(inv.getInvoker());
                 rpcInvocation.setTargetServiceUniqueName(inv.getTargetServiceUniqueName());
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
index 3461389c9e..f60ddd902c 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolListenerWrapper.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.protocol;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Activate;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.rpc.Exporter;
@@ -30,6 +29,7 @@ import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.listener.ListenerExporterWrapper;
 import org.apache.dubbo.rpc.listener.ListenerInvokerWrapper;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 
 import java.util.Collections;
 import java.util.List;
@@ -64,7 +64,7 @@ public class ProtocolListenerWrapper implements Protocol {
             return protocol.export(invoker);
         }
         return new ListenerExporterWrapper(protocol.export(invoker),
-                Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(ExporterListener.class)
+                Collections.unmodifiableList(ScopeModelUtil.getExtensionLoader(ExporterListener.class, invoker.getUrl().getScopeModel())
                         .getActivateExtension(invoker.getUrl(), EXPORTER_LISTENER_KEY)));
     }
 
@@ -78,7 +78,7 @@ public class ProtocolListenerWrapper implements Protocol {
         if (StringUtils.isEmpty(url.getParameter(REGISTRY_CLUSTER_TYPE_KEY))) {
             invoker = new ListenerInvokerWrapper<>(invoker,
                     Collections.unmodifiableList(
-                            ExtensionLoader.getExtensionLoader(InvokerListener.class)
+                        ScopeModelUtil.getExtensionLoader(InvokerListener.class, invoker.getUrl().getScopeModel())
                                     .getActivateExtension(url, INVOKER_LISTENER_KEY)));
         }
         return invoker;
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSerializationWrapper.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSerializationWrapper.java
index 7d9722b8cc..6d97d1889c 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSerializationWrapper.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/ProtocolSerializationWrapper.java
@@ -23,10 +23,11 @@ import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProtocolServer;
 import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.List;
 
+import static org.apache.dubbo.rpc.model.ScopeModelUtil.getApplicationModel;
+
 @Activate
 public class ProtocolSerializationWrapper implements Protocol {
     private Protocol protocol;
@@ -42,7 +43,7 @@ public class ProtocolSerializationWrapper implements Protocol {
 
     @Override
     public  Exporter export(Invoker invoker) throws RpcException {
-        ApplicationModel.getServiceRepository().registerProviderUrl(invoker.getUrl());
+        getApplicationModel(invoker.getUrl().getScopeModel()).getApplicationServiceRepository().registerProviderUrl(invoker.getUrl());
         return protocol.export(invoker);
     }
 
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
index 6117b960d4..70e8b83294 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/proxy/InvokerInvocationHandler.java
@@ -23,8 +23,8 @@ import org.apache.dubbo.rpc.Constants;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.RpcServiceContext;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.ConsumerModel;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationHandler;
@@ -36,7 +36,7 @@ import java.lang.reflect.Method;
 public class InvokerInvocationHandler implements InvocationHandler {
     private static final Logger logger = LoggerFactory.getLogger(InvokerInvocationHandler.class);
     private final Invoker invoker;
-    private ConsumerModel consumerModel;
+    private ServiceModel serviceModel;
     private URL url;
     private String protocolServiceKey;
 
@@ -54,11 +54,8 @@ public class InvokerInvocationHandler implements InvocationHandler {
     public InvokerInvocationHandler(Invoker handler) {
         this.invoker = handler;
         this.url = invoker.getUrl();
-        String serviceKey = this.url.getServiceKey();
         this.protocolServiceKey = this.url.getProtocolServiceKey();
-        if (serviceKey != null) {
-            this.consumerModel = ApplicationModel.getConsumerModel(serviceKey);
-        }
+        this.serviceModel = this.url.getServiceModel();
     }
 
     @Override
@@ -80,16 +77,16 @@ public class InvokerInvocationHandler implements InvocationHandler {
         } else if (parameterTypes.length == 1 && "equals".equals(methodName)) {
             return invoker.equals(args[0]);
         }
-        RpcInvocation rpcInvocation = new RpcInvocation(method, invoker.getInterface().getName(), protocolServiceKey, args);
+        RpcInvocation rpcInvocation = new RpcInvocation(serviceModel, method, invoker.getInterface().getName(), protocolServiceKey, args);
         String serviceKey = url.getServiceKey();
         rpcInvocation.setTargetServiceUniqueName(serviceKey);
 
         // invoker.getUrl() returns consumer url.
         RpcServiceContext.setRpcContext(url);
 
-        if (consumerModel != null) {
-            rpcInvocation.put(Constants.CONSUMER_MODEL, consumerModel);
-            rpcInvocation.put(Constants.METHOD_MODEL, consumerModel.getMethodModel(method));
+        if (serviceModel instanceof ConsumerModel) {
+            rpcInvocation.put(Constants.CONSUMER_MODEL, serviceModel);
+            rpcInvocation.put(Constants.METHOD_MODEL, ((ConsumerModel) serviceModel).getMethodModel(method));
         }
 
         return invoker.invoke(rpcInvocation).recreate();
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
index 6bd4dff11f..801e212a0c 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.rpc.support;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionFactory;
+import org.apache.dubbo.common.extension.ExtensionInjector;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.ArrayUtils;
 import org.apache.dubbo.common.utils.ConfigUtils;
@@ -189,9 +189,9 @@ final public class MockInvoker implements Invoker {
             mockClass = ReflectUtils.forName(mockService);
         } catch (Exception e) {
             if (!isDefault) {// does not check Spring bean if it is default config.
-                ExtensionFactory extensionFactory =
-                        ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension();
-                Object obj = extensionFactory.getExtension(serviceType, mockService);
+                ExtensionInjector extensionFactory =
+                        ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension();
+                Object obj = extensionFactory.getInstance(serviceType, mockService);
                 if (obj != null) {
                     return obj;
                 }
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
index 8ebe8ac4db..2c8a618429 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvocation.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.support;
 import org.apache.dubbo.rpc.AttachmentsAdapter;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.util.HashMap;
 import java.util.Map;
@@ -117,6 +118,16 @@ public class MockInvocation implements Invocation {
         return null;
     }
 
+    @Override
+    public void setServiceModel(ServiceModel serviceModel) {
+
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return null;
+    }
+
     @Override
     public Object put(Object key, Object value) {
         return null;
diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java
index df5bdf382b..b1718c3992 100644
--- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RpcUtilsTest.java
@@ -368,7 +368,7 @@ public class RpcUtilsTest {
         RpcInvocation inv = new RpcInvocation("testReturnType", serviceName, "", new Class[] {String.class}, null, null, invoker, null);
         Assertions.assertFalse(RpcUtils.isReturnTypeFuture(inv));
 
-        ServiceRepository repository = ApplicationModel.getServiceRepository();
+        ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
         repository.registerService(demoServiceClass);
 
         inv = new RpcInvocation("testReturnType4", serviceName, "", new Class[] {String.class}, null, null, invoker, null);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
index 6ef932d900..0f0aecf8f6 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.rpc.protocol.dubbo;
 
+import org.apache.dubbo.common.BaseServiceMetadata;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.bytecode.Wrapper;
 import org.apache.dubbo.common.extension.ExtensionLoader;
@@ -34,6 +35,11 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
+import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+import org.apache.dubbo.rpc.model.ServiceDescriptor;
+import org.apache.dubbo.rpc.model.ServiceMetadata;
 
 import java.io.IOException;
 import java.util.HashMap;
@@ -93,7 +99,7 @@ class CallbackServiceCodec {
      * @throws IOException
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
-    private static String exportOrUnexportCallbackService(Channel channel, URL url, Class clazz, Object inst, Boolean export) throws IOException {
+    private static String exportOrUnexportCallbackService(Channel channel, RpcInvocation inv, URL url, Class clazz, Object inst, Boolean export) throws IOException {
         int instid = System.identityHashCode(inst);
 
         Map params = new HashMap<>(3);
@@ -129,7 +135,24 @@ class CallbackServiceCodec {
             // one channel can have multiple callback instances, no need to re-export for different instance.
             if (!channel.hasAttribute(cacheKey)) {
                 if (!isInstancesOverLimit(channel, url, clazz.getName(), instid, false)) {
-                    ApplicationModel.getServiceRepository().registerService(clazz);
+                    ModuleModel moduleModel;
+                    if (inv.getServiceModel() == null) {
+                        moduleModel = ApplicationModel.defaultModel().getDefaultModule();
+                        logger.error("Unable to get Service Model from Invocation. Please check if your invocation failed! " +
+                            "This error only happen in UT cases! Invocation:" + inv);
+                    } else {
+                        moduleModel = inv.getServiceModel().getModuleModel();
+                    }
+                    ServiceDescriptor serviceDescriptor = ScopeModelUtil.getApplicationModel(moduleModel).getApplicationServiceRepository().registerService(clazz);
+                    ProviderModel providerModel = new ProviderModel(BaseServiceMetadata.buildServiceKey(exportUrl.getPath(), group, exportUrl.getVersion()),
+                        inst,
+                        serviceDescriptor,
+                        null,
+                        moduleModel,
+                        new ServiceMetadata(clazz.getName() + "." + instid, exportUrl.getGroup(), exportUrl.getVersion(), clazz));
+                    moduleModel.getApplicationModel().getApplicationServiceRepository().registerProvider(providerModel);
+                    exportUrl = exportUrl.setScopeModel(moduleModel);
+                    exportUrl = exportUrl.setServiceModel(providerModel);
                     Invoker invoker = PROXY_FACTORY.getInvoker(inst, clazz, exportUrl);
                     // should destroy resource?
                     Exporter exporter = PROTOCOL.export(invoker);
@@ -167,7 +190,7 @@ class CallbackServiceCodec {
                 URL referurl = URL.valueOf("callback://" + url.getAddress() + "/" + clazz.getName() + "?" + INTERFACE_KEY + "=" + clazz.getName());
                 referurl = referurl.addParametersIfAbsent(url.getParameters()).removeParameter(METHODS_KEY);
                 if (!isInstancesOverLimit(channel, referurl, clazz.getName(), instid, true)) {
-                    ApplicationModel.getServiceRepository().registerService(clazz);
+                    ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationServiceRepository().registerService(clazz);
                     @SuppressWarnings("rawtypes")
                     Invoker invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid));
                     proxy = PROXY_FACTORY.getProxy(invoker);
@@ -276,10 +299,10 @@ class CallbackServiceCodec {
         Class[] pts = inv.getParameterTypes();
         switch (callbackStatus) {
             case CallbackServiceCodec.CALLBACK_CREATE:
-                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], true));
+                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, inv,  url, pts[paraIndex], args[paraIndex], true));
                 return null;
             case CallbackServiceCodec.CALLBACK_DESTROY:
-                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, url, pts[paraIndex], args[paraIndex], false));
+                inv.setAttachment(INV_ATT_CALLBACK_KEY + paraIndex, exportOrUnexportCallbackService(channel, inv,  url, pts[paraIndex], args[paraIndex], false));
                 return null;
             default:
                 return args[paraIndex];
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
index 91ebb814fd..a5003ef6b1 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.rpc.protocol.dubbo;
 
 
-import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.serialize.Cleanable;
@@ -123,7 +122,7 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
         setParameterTypesDesc(desc);
 
         try {
-            if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, true)) {
+            if (Boolean.parseBoolean(System.getProperty(SERIALIZATION_SECURITY_CHECK_KEY, "true"))) {
                 CodecSupport.checkSerialization(path, version, serializationType);
             }
             Object[] args = DubboCodec.EMPTY_OBJECT_ARRAY;
@@ -132,7 +131,8 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec
 //                if (RpcUtils.isGenericCall(path, getMethodName()) || RpcUtils.isEcho(path, getMethodName())) {
 //                    pts = ReflectUtils.desc2classArray(desc);
 //                } else {
-                ServiceRepository repository = ApplicationModel.getServiceRepository();
+                // TODO: fetch from FrameworkModel
+                ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
                 ServiceDescriptor serviceDescriptor = repository.lookupService(path);
                 if (serviceDescriptor != null) {
                     MethodDescriptor methodDescriptor = serviceDescriptor.getMethod(getMethodName(), desc);
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
index 05b84cb61b..d93d3452b8 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java
@@ -119,7 +119,7 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl
         if (!hasDecoded && channel != null && inputStream != null) {
             try {
                 if (invocation != null) {
-                    if (ConfigurationUtils.getSystemConfiguration().getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, true)) {
+                    if (ConfigurationUtils.getSystemConfiguration(channel.getUrl().getScopeModel()).getBoolean(SERIALIZATION_SECURITY_CHECK_KEY, true)) {
                         Object serializationTypeObj = invocation.get(SERIALIZATION_ID_KEY);
                         if (serializationTypeObj != null) {
                             if ((byte) serializationTypeObj != serializationType) {
@@ -128,6 +128,7 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl
                         }
                     }
                 }
+
                 decode(channel, inputStream);
             } catch (Throwable e) {
                 if (log.isWarnEnabled()) {
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
index 85244e9a45..a63f56fe44 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvoker.java
@@ -69,6 +69,8 @@ public class DubboInvoker extends AbstractInvoker {
 
     private final Set> invokers;
 
+    private final int serverShutdownTimeout;
+
     public DubboInvoker(Class serviceType, URL url, ExchangeClient[] clients) {
         this(serviceType, url, clients, null);
     }
@@ -79,6 +81,7 @@ public class DubboInvoker extends AbstractInvoker {
         // get version.
         this.version = url.getVersion(DEFAULT_VERSION);
         this.invokers = invokers;
+        this.serverShutdownTimeout = ConfigurationUtils.getServerShutdownTimeout(getUrl().getScopeModel());
     }
 
     @Override
@@ -151,7 +154,7 @@ public class DubboInvoker extends AbstractInvoker {
                 }
                 for (ExchangeClient client : clients) {
                     try {
-                        client.close(ConfigurationUtils.getServerShutdownTimeout());
+                        client.close(serverShutdownTimeout);
                     } catch (Throwable t) {
                         logger.warn(t.getMessage(), t);
                     }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
index 1ee0957afe..47a41cc23b 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java
@@ -46,8 +46,10 @@ import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
+import org.apache.dubbo.rpc.model.ScopeModel;
 import org.apache.dubbo.rpc.protocol.AbstractProtocol;
 
+import java.lang.reflect.Field;
 import java.net.InetSocketAddress;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -118,6 +120,7 @@ public class DubboProtocol extends AbstractProtocol {
 
             Invocation inv = (Invocation) message;
             Invoker invoker = getInvoker(channel, inv);
+            inv.setServiceModel(invoker.getUrl().getServiceModel());
             // need to consider backward-compatibility if it's a callback
             if (Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) {
                 String methodsStr = invoker.getUrl().getParameters().get("methods");
@@ -195,7 +198,7 @@ public class DubboProtocol extends AbstractProtocol {
                 return null;
             }
 
-            RpcInvocation invocation = new RpcInvocation(method, url.getParameter(INTERFACE_KEY), "", new Class[0], new Object[0]);
+            RpcInvocation invocation = new RpcInvocation(url.getServiceModel(), method, url.getParameter(INTERFACE_KEY), "", new Class[0], new Object[0]);
             invocation.setAttachment(PATH_KEY, url.getPath());
             invocation.setAttachment(GROUP_KEY, url.getGroup());
             invocation.setAttachment(INTERFACE_KEY, url.getParameter(INTERFACE_KEY));
@@ -221,6 +224,22 @@ public class DubboProtocol extends AbstractProtocol {
         return INSTANCE;
     }
 
+
+    public static DubboProtocol getDubboProtocol(ScopeModel scopeModel) {
+        Protocol protocolWrapper = scopeModel.getExtensionLoader(Protocol.class).getExtension(DubboProtocol.NAME);
+
+        try {
+            while (!(protocolWrapper instanceof DubboProtocol)) {
+                Field protocolField = protocolWrapper.getClass().getDeclaredField("protocol");
+                protocolField.setAccessible(true);
+                protocolWrapper = (Protocol) protocolField.get(protocolWrapper);
+            }
+        } catch (NoSuchFieldException | IllegalAccessException ignore) {
+        }
+
+        return (DubboProtocol) protocolWrapper;
+    }
+
     @Override
     public Collection> getExporters() {
         return Collections.unmodifiableCollection(exporterMap.values());
@@ -647,7 +666,7 @@ public class DubboProtocol extends AbstractProtocol {
                     logger.info("Close dubbo server: " + server.getLocalAddress());
                 }
 
-                server.close(ConfigurationUtils.getServerShutdownTimeout());
+                server.close(ConfigurationUtils.getServerShutdownTimeout(server.getUrl().getScopeModel()));
 
             } catch (Throwable t) {
                 logger.warn(t.getMessage(), t);
@@ -687,7 +706,7 @@ public class DubboProtocol extends AbstractProtocol {
                 logger.info("Close dubbo connect: " + client.getLocalAddress() + "-->" + client.getRemoteAddress());
             }
 
-            client.close(ConfigurationUtils.getServerShutdownTimeout());
+            client.close(ConfigurationUtils.getServerShutdownTimeout(client.getUrl().getScopeModel()));
 
             // TODO
             /*
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
index ad95481bd9..9d9e205316 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/filter/FutureFilter.java
@@ -25,9 +25,9 @@ import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Result;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
-import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.AsyncMethodInfo;
 import org.apache.dubbo.rpc.model.ConsumerModel;
+import org.apache.dubbo.rpc.model.ServiceModel;
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -192,8 +192,8 @@ public class FutureFilter implements ClusterFilter, ClusterFilter.Listener {
             return asyncMethodInfo;
         }
 
-        ConsumerModel consumerModel = ApplicationModel.getConsumerModel(invoker.getUrl().getServiceKey());
-        if (consumerModel == null) {
+        ServiceModel serviceModel = invocation.getServiceModel();
+        if (!(serviceModel instanceof ConsumerModel)) {
             return null;
         }
 
@@ -202,7 +202,7 @@ public class FutureFilter implements ClusterFilter, ClusterFilter.Listener {
             methodName = (String) invocation.getArguments()[0];
         }
 
-        return consumerModel.getAsyncInfo(methodName);
+        return ((ConsumerModel) serviceModel).getAsyncInfo(methodName);
     }
 
 }
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
index 4bc08005a1..3870b725b9 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/ArgumentCallbackTest.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.rpc.Exporter;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ConsumerModel;
 import org.apache.dubbo.rpc.protocol.dubbo.support.ProtocolUtils;
 
 import org.junit.jupiter.api.AfterEach;
@@ -59,14 +60,14 @@ public class ArgumentCallbackTest {
         // export one service first, to test connection sharing
         serviceURL = serviceURL.addParameter("connections", 1);
         URL hellourl = serviceURL.setPath(IHelloService.class.getName());
-        ApplicationModel.getServiceRepository().registerService(IDemoService.class);
-        ApplicationModel.getServiceRepository().registerService(IHelloService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(IDemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(IHelloService.class);
         hello_exporter = ProtocolUtils.export(new HelloServiceImpl(), IHelloService.class, hellourl);
         exporter = ProtocolUtils.export(new DemoServiceImpl(), IDemoService.class, serviceURL);
     }
 
     void referService() {
-        ApplicationModel.getServiceRepository().registerService(IDemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(IDemoService.class);
         demoProxy = (IDemoService) ProtocolUtils.refer(IDemoService.class, consumerUrl);
     }
 
@@ -82,8 +83,11 @@ public class ArgumentCallbackTest {
                 + "&unxxx2.0.callback=false"
                 + "&timeout=" + timeout
                 + "&retries=0"
-                + "&" + CALLBACK_INSTANCES_LIMIT_KEY + "=" + callbacks
-        );
+                + "&" + CALLBACK_INSTANCES_LIMIT_KEY + "=" + callbacks)
+            .setScopeModel(ApplicationModel.defaultModel())
+            .setServiceModel(new ConsumerModel(IDemoService.class.getName(), null, null, null,
+            ApplicationModel.defaultModel().getDefaultModule(), null, null));
+
         //      uncomment is unblock invoking
 //        serviceURL = serviceURL.addParameter("yyy."+Constants.ASYNC_KEY,String.valueOf(true));
 //        consumerUrl = consumerUrl.addParameter("yyy."+Constants.ASYNC_KEY,String.valueOf(true));
@@ -96,7 +100,7 @@ public class ArgumentCallbackTest {
     }
 
     public void destroyService() {
-        ApplicationModel.getServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
         demoProxy = null;
         try {
             if (exporter != null) exporter.unexport();
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
index e3141c828d..2b362234fd 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocolTest.java
@@ -64,12 +64,12 @@ public class DubboProtocolTest {
     @AfterAll
     public static void after() {
         ProtocolUtils.closeAll();
-        ApplicationModel.getServiceRepository().unregisterService(DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().unregisterService(DemoService.class);
     }
 
     @BeforeAll
     public static void setup() {
-        ApplicationModel.getServiceRepository().registerService(DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(DemoService.class);
     }
 
     @Test
@@ -165,7 +165,7 @@ public class DubboProtocolTest {
 
         RemoteService remote = new RemoteServiceImpl();
 
-        ApplicationModel.getServiceRepository().registerService(RemoteService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(RemoteService.class);
 
         int port = NetUtils.getAvailablePort();
         protocol.export(proxy.getInvoker(remote, RemoteService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/" + RemoteService.class.getName())));
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java
index 113ae7b5e3..e5f1ba22e9 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/MultiThreadTest.java
@@ -44,12 +44,12 @@ public class MultiThreadTest {
     @AfterEach
     public void after() {
         ProtocolUtils.closeAll();
-        ApplicationModel.getServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
     }
 
     @Test
     public void testDubboMultiThreadInvoke() throws Exception {
-        ApplicationModel.getServiceRepository().registerService("TestService", DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService("TestService", DemoService.class);
         int port = NetUtils.getAvailablePort();
         Exporter rpcExporter = protocol.export(proxy.getInvoker(new DemoServiceImpl(), DemoService.class, URL.valueOf("dubbo://127.0.0.1:" + port + "/TestService")));
 
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java
index 980d323671..aa6577bd60 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/RpcFilterTest.java
@@ -45,7 +45,7 @@ public class RpcFilterTest {
         DemoService service = new DemoServiceImpl();
         int port = NetUtils.getAvailablePort();
         URL url = URL.valueOf("dubbo://127.0.0.1:" + port + "/org.apache.dubbo.rpc.protocol.dubbo.support.DemoService?service.filter=echo");
-        ApplicationModel.getServiceRepository().registerService(DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(DemoService.class);
         protocol.export(proxy.getInvoker(service, DemoService.class, url));
         service = proxy.getProxy(protocol.refer(DemoService.class, url));
         Assertions.assertEquals("123", service.echo("123"));
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java
index 3122865df5..a66a8446ba 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java
@@ -69,13 +69,13 @@ public class DubboTelnetDecodeTest {
 
     @BeforeAll
     public static void setup() {
-        ApplicationModel.getServiceRepository().destroy();
-        ApplicationModel.getServiceRepository().registerService(DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(DemoService.class);
     }
 
     @AfterAll
     public static void teardown() {
-        ApplicationModel.getServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
     }
 
     /**
diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/EnumBak.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/EnumBak.java
index 0b74b1033c..94f8cbd8cb 100644
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/EnumBak.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/EnumBak.java
@@ -47,7 +47,7 @@ public class EnumBak {
         );
         DemoService demo = new DemoServiceImpl();
 
-        ApplicationModel.getServiceRepository().registerService("test", DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService("test", DemoService.class);
 
         Invoker invoker = proxy.getInvoker(demo, DemoService.class, serviceurl);
         protocol.export(invoker);
@@ -93,7 +93,7 @@ public class EnumBak {
         );
         DemoService demo = new DemoServiceImpl();
 
-        ApplicationModel.getServiceRepository().registerService("test", DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService("test", DemoService.class);
 
         Invoker invoker = proxy.getInvoker(demo, DemoService.class, serviceurl);
         protocol.export(invoker);
@@ -117,7 +117,7 @@ public class EnumBak {
         URL consumerurl = URL.valueOf("dubbo://127.0.0.1:" + port + "/test?timeout=" + Integer.MAX_VALUE
         );
 
-        ApplicationModel.getServiceRepository().registerService(DemoService.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(DemoService.class);
 
         Invoker reference = protocol.refer(DemoService.class, consumerurl);
         DemoService demoProxy = (DemoService) proxy.getProxy(reference);
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
index d1b1cda88c..ac2c4e7239 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.common.threadpool.ThreadPool;
 import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.config.SslConfig;
 import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
 import org.apache.dubbo.rpc.protocol.grpc.interceptors.ClientInterceptor;
 import org.apache.dubbo.rpc.protocol.grpc.interceptors.GrpcConfigurator;
 import org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerInterceptor;
@@ -153,7 +153,7 @@ public class GrpcOptionsUtils {
     }
 
     private static SslContext buildServerSslContext(URL url) {
-        ConfigManager globalConfigManager = ApplicationModel.getConfigManager();
+        ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager();
         SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!"));
 
         SslContextBuilder sslClientContextBuilder = null;
@@ -183,7 +183,7 @@ public class GrpcOptionsUtils {
     }
 
     private static SslContext buildClientSslContext(URL url) {
-        ConfigManager globalConfigManager = ApplicationModel.getConfigManager();
+        ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager();
         SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!"));
 
 
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
index 1342a17e6c..bbcbfe1951 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocol.java
@@ -72,7 +72,8 @@ public class GrpcProtocol extends AbstractProxyProtocol {
 
         GrpcRemotingServer grpcServer = (GrpcRemotingServer) protocolServer.getRemotingServer();
 
-        ServiceRepository serviceRepository = ApplicationModel.getServiceRepository();
+        // TODO: fetch from FrameworkModel
+        ServiceRepository serviceRepository = ApplicationModel.defaultModel().getApplicationServiceRepository();
         ProviderModel providerModel = serviceRepository.lookupExportedService(url.getServiceKey());
         if (providerModel == null) {
             throw new IllegalStateException("Service " + url.getServiceKey() + "should have already been stored in service repository, " +
@@ -119,11 +120,17 @@ public class GrpcProtocol extends AbstractProxyProtocol {
 
         // CallOptions
         try {
+            ReferenceConfigBase referenceConfig;
+            if (url.getServiceModel() != null) {
+                referenceConfig = url.getServiceModel().getReferenceConfig();
+            } else {
+                referenceConfig = ApplicationModel.getConsumerModel(url.getServiceKey()).getReferenceConfig();
+            }
             @SuppressWarnings("unchecked") final T stub = (T) dubboStubMethod.invoke(null,
                     channel,
                     GrpcOptionsUtils.buildCallOptions(url),
                     url,
-                    ApplicationModel.getConsumerModel(url.getServiceKey()).getReferenceConfig()
+                    referenceConfig
             );
             final Invoker target = proxyFactory.getInvoker(stub, type, url);
             GrpcInvoker grpcInvoker = new GrpcInvoker<>(type, url, target, channel);
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ClientInterceptor.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ClientInterceptor.java
index c97fec9106..33beddfbba 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ClientInterceptor.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ClientInterceptor.java
@@ -16,11 +16,12 @@
  */
 package org.apache.dubbo.rpc.protocol.grpc.interceptors;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
  * Adapt to the standard Dubbo SPI, so that we can leverage the advantages of Dubbo ExtensionLoader.
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ClientInterceptor extends io.grpc.ClientInterceptor {
 }
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/GrpcConfigurator.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/GrpcConfigurator.java
index d5330dcc00..dd551184f8 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/GrpcConfigurator.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/GrpcConfigurator.java
@@ -17,13 +17,14 @@
 package org.apache.dubbo.rpc.protocol.grpc.interceptors;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import io.grpc.CallOptions;
 import io.grpc.netty.NettyChannelBuilder;
 import io.grpc.netty.NettyServerBuilder;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface GrpcConfigurator {
 
     default NettyServerBuilder configureServerBuilder(NettyServerBuilder builder, URL url) {
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerInterceptor.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerInterceptor.java
index a4c9a37a79..f657d23e8c 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerInterceptor.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerInterceptor.java
@@ -16,11 +16,12 @@
  */
 package org.apache.dubbo.rpc.protocol.grpc.interceptors;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
  * Adapt to the standard Dubbo SPI, so that we can leverage the advantages of Dubbo ExtensionLoader.
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ServerInterceptor extends io.grpc.ServerInterceptor {
 }
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerTransportFilter.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerTransportFilter.java
index db815dc401..291163f4ac 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerTransportFilter.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/interceptors/ServerTransportFilter.java
@@ -16,12 +16,13 @@
  */
 package org.apache.dubbo.rpc.protocol.grpc.interceptors;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 /**
  * Adapt to the standard Dubbo SPI, so that we can leverage the advantages of Dubbo ExtensionLoader.
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface ServerTransportFilter {
     io.grpc.ServerTransportFilter grpcTransportFilter();
 }
diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
index d5118d973e..75d1eb8bea 100644
--- a/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-grpc/src/test/java/org/apache/dubbo/rpc/protocol/grpc/GrpcProtocolTest.java
@@ -17,8 +17,6 @@
 
 package org.apache.dubbo.rpc.protocol.grpc;
 
-import com.google.common.util.concurrent.ListenableFuture;
-import io.grpc.stub.StreamObserver;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.utils.NetUtils;
@@ -27,12 +25,16 @@ import org.apache.dubbo.rpc.Protocol;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.model.AsyncMethodInfo;
+import org.apache.dubbo.rpc.model.ConsumerModel;
 import org.apache.dubbo.rpc.model.ServiceDescriptor;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
 import org.apache.dubbo.rpc.protocol.grpc.support.DubboGreeterGrpc;
 import org.apache.dubbo.rpc.protocol.grpc.support.GrpcGreeterImpl;
 import org.apache.dubbo.rpc.protocol.grpc.support.HelloReply;
 import org.apache.dubbo.rpc.protocol.grpc.support.HelloRequest;
+
+import com.google.common.util.concurrent.ListenableFuture;
+import io.grpc.stub.StreamObserver;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -51,8 +53,8 @@ public class GrpcProtocolTest {
 
         URL url = URL.valueOf("grpc://127.0.0.1:" + availablePort + "/" + DubboGreeterGrpc.IGreeter.class.getName());
 
-        ServiceDescriptor serviceDescriptor = ApplicationModel.getServiceRepository().registerService(DubboGreeterGrpc.IGreeter.class);
-        ApplicationModel.getServiceRepository().registerProvider(
+        ServiceDescriptor serviceDescriptor = ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(DubboGreeterGrpc.IGreeter.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerProvider(
             url.getServiceKey(),
             serviceImpl,
             serviceDescriptor,
@@ -68,13 +70,10 @@ public class GrpcProtocolTest {
         serviceMetadata.setServiceKey(URL.buildKey(DubboGreeterGrpc.IGreeter.class.getName(), null, null));
 
         Map methodConfigs = new HashMap<>();
-        ApplicationModel.getServiceRepository().registerConsumer(
-            url.getServiceKey(),
-            serviceDescriptor,
-            mockReferenceConfig,
-            null,
-            serviceMetadata,
-            methodConfigs);
+        ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), null, serviceDescriptor, mockReferenceConfig,
+            serviceMetadata, methodConfigs);
+
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerConsumer(consumerModel);
 
         protocol.export(proxy.getInvoker(serviceImpl, DubboGreeterGrpc.IGreeter.class, url));
         serviceImpl = proxy.getProxy(protocol.refer(DubboGreeterGrpc.IGreeter.class, url));
@@ -103,7 +102,7 @@ public class GrpcProtocolTest {
             }
         });
         // resource recycle.
-        ApplicationModel.getServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
     }
 
     class MockReferenceConfig extends ReferenceConfigBase {
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
index 7e22132d88..d6d2ddd3ff 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/main/java/org/apache/dubbo/rpc/protocol/rest/RestProtocol.java
@@ -94,7 +94,12 @@ public class RestProtocol extends AbstractProxyProtocol {
     @Override
     protected  Runnable doExport(T impl, Class type, URL url) throws RpcException {
         String addr = getAddr(url);
-        Class implClass = ApplicationModel.getProviderModel(url.getServiceKey()).getServiceInstance().getClass();
+        Class implClass;
+        if (url.getScopeModel() != null) {
+            implClass = url.getServiceModel().getProxyObject().getClass();
+        } else {
+            implClass = ApplicationModel.getProviderModel(url.getServiceKey()).getServiceInstance().getClass();
+        }
         RestProtocolServer server = (RestProtocolServer) serverMap.computeIfAbsent(addr, restServer -> {
             RestProtocolServer s = serverFactory.createServer(url.getParameter(SERVER_KEY, DEFAULT_SERVER));
             s.setAddress(url.getAddress());
diff --git a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
index 8004d38dce..cb20fc07be 100644
--- a/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protocol/rest/RestProtocolTest.java
@@ -50,7 +50,7 @@ public class RestProtocolTest {
     private ProxyFactory proxy = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
     private final int availablePort = NetUtils.getAvailablePort();
     private final URL exportUrl = URL.valueOf("rest://127.0.0.1:" + availablePort + "/rest?interface=org.apache.dubbo.rpc.protocol.rest.DemoService");
-    private final ServiceRepository repository = ApplicationModel.getServiceRepository();
+    private final ServiceRepository repository = ApplicationModel.defaultModel().getApplicationServiceRepository();
 
     @AfterEach
     public void tearDown() {
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java
index b3fe4690d7..6ee500e4d7 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java
@@ -91,7 +91,8 @@ public abstract class AbstractServerStream extends AbstractStream implements Str
     }
 
     private static ProviderModel lookupProviderModel(URL url) {
-        ServiceRepository repo = ApplicationModel.getServiceRepository();
+        // TODO: fetch from FrameworkModel
+        ServiceRepository repo = ApplicationModel.defaultModel().getApplicationServiceRepository();
         final ProviderModel model = repo.lookupExportedService(url.getServiceKey());
         if (model != null) {
             ClassLoadUtil.switchContextLoader(model.getServiceInterfaceClass().getClassLoader());
@@ -121,11 +122,10 @@ public abstract class AbstractServerStream extends AbstractStream implements Str
     }
 
     protected RpcInvocation buildInvocation(Metadata metadata) {
-        RpcInvocation inv = new RpcInvocation();
-        inv.setServiceName(getServiceDescriptor().getServiceName());
+        RpcInvocation inv = new RpcInvocation(getUrl().getServiceModel(),
+            getMethodName(), getServiceDescriptor().getServiceName(),
+            getUrl().getProtocolServiceKey(), getMethodDescriptor().getParameterClasses(), new Object[0]);
         inv.setTargetServiceUniqueName(getUrl().getServiceKey());
-        inv.setMethodName(getMethodDescriptor().getMethodName());
-        inv.setParameterTypes(getMethodDescriptor().getParameterClasses());
         inv.setReturnTypes(getMethodDescriptor().getReturnTypes());
 
         final Map attachments = parseMetadataToAttachmentMap(metadata);
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PathResolver.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PathResolver.java
index 468a92d0a8..3490cd2105 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PathResolver.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/PathResolver.java
@@ -17,10 +17,11 @@
 package org.apache.dubbo.rpc.protocol.tri;
 
 import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.rpc.Invoker;
 
-@SPI(CommonConstants.TRIPLE)
+@SPI(value = CommonConstants.TRIPLE, scope = ExtensionScope.FRAMEWORK)
 public interface PathResolver {
 
     void add(String path, Invoker invoker);
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleClientHandler.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleClientHandler.java
index ac13126a20..d1cc418069 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleClientHandler.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleClientHandler.java
@@ -67,7 +67,7 @@ public class TripleClientHandler extends ChannelDuplexHandler {
     private void writeRequest(ChannelHandlerContext ctx, final Request req, final ChannelPromise promise) {
         final RpcInvocation inv = (RpcInvocation) req.getData();
         final URL url = inv.getInvoker().getUrl();
-        ServiceRepository repo = ApplicationModel.getServiceRepository();
+        ServiceRepository repo = ApplicationModel.defaultModel().getApplicationServiceRepository();
         MethodDescriptor methodDescriptor = repo.lookupMethod(inv.getServiceName(), inv.getMethodName());
         String serviceKey = url.getServiceKey();
         // If it is InstanceAddressURL, the serviceKey may not be obtained.
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2FrameServerHandler.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2FrameServerHandler.java
index 0d71cb9602..42f986f9ba 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2FrameServerHandler.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/TripleHttp2FrameServerHandler.java
@@ -159,7 +159,7 @@ public class TripleHttp2FrameServerHandler extends ChannelDuplexHandler {
                     GrpcStatus.fromCode(Code.UNIMPLEMENTED).withDescription("Service not found:" + serviceName));
             return;
         }
-        ServiceRepository repo = ApplicationModel.getServiceRepository();
+        ServiceRepository repo = ApplicationModel.defaultModel().getApplicationServiceRepository();
         final ServiceDescriptor serviceDescriptor = repo.lookupService(invoker.getUrl().getServiceKey());
         if (serviceDescriptor == null) {
             responseErr(ctx,
diff --git a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
index 0db41e348a..af49f3e1e1 100644
--- a/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
+++ b/dubbo-rpc/dubbo-rpc-triple/src/test/java/org/apache/dubbo/rpc/protocol/tri/TripleProtocolTest.java
@@ -28,6 +28,7 @@ import org.apache.dubbo.rpc.model.ServiceDescriptor;
 import org.apache.dubbo.rpc.model.ServiceMetadata;
 import org.apache.dubbo.rpc.protocol.tri.support.IGreeter;
 import org.apache.dubbo.rpc.protocol.tri.support.IGreeterImpl;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -44,8 +45,8 @@ public class TripleProtocolTest {
 
         URL url = URL.valueOf("tri://127.0.0.1:" + availablePort + "/" + IGreeter.class.getName());
 
-        ServiceDescriptor serviceDescriptor = ApplicationModel.getServiceRepository().registerService(IGreeter.class);
-        ApplicationModel.getServiceRepository().registerProvider(
+        ServiceDescriptor serviceDescriptor = ApplicationModel.defaultModel().getApplicationServiceRepository().registerService(IGreeter.class);
+        ApplicationModel.defaultModel().getApplicationServiceRepository().registerProvider(
             url.getServiceKey(),
             serviceImpl,
             serviceDescriptor,
@@ -77,6 +78,6 @@ public class TripleProtocolTest {
         });
 
         // resource recycle.
-        ApplicationModel.getServiceRepository().destroy();
+        ApplicationModel.defaultModel().getApplicationServiceRepository().destroy();
     }
 }
diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/MultipleSerialization.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/MultipleSerialization.java
index 18a417d406..2c6037452c 100644
--- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/MultipleSerialization.java
+++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/MultipleSerialization.java
@@ -18,13 +18,14 @@
 package org.apache.dubbo.common.serialize;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface MultipleSerialization {
 
     void serialize(URL url, String serializeType, String clz, Object obj, OutputStream os) throws IOException;
diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/Serialization.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/Serialization.java
index 430bfc5fe6..bb67639adc 100644
--- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/Serialization.java
+++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/Serialization.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.common.serialize;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
 import java.io.IOException;
@@ -32,7 +33,7 @@ import java.io.OutputStream;
  *     e.g. <dubbo:protocol serialization="xxx" />
  * 
  */
-@SPI("hessian2")
+@SPI(value = "hessian2", scope = ExtensionScope.FRAMEWORK)
 public interface Serialization {
 
     /**
diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java
index 16576ec710..1222612764 100644
--- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java
+++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/Hessian2FactoryInitializer.java
@@ -16,14 +16,14 @@
  */
 package org.apache.dubbo.common.serialize.hessian2.dubbo;
 
-import org.apache.dubbo.common.config.ConfigurationUtils;
 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.common.utils.StringUtils;
 
 import com.alibaba.com.caucho.hessian.io.SerializerFactory;
 
-@SPI("default")
+@SPI(value = "default", scope = ExtensionScope.FRAMEWORK)
 public interface Hessian2FactoryInitializer {
     String WHITELIST = "dubbo.application.hessian2.whitelist";
     String ALLOW = "dubbo.application.hessian2.allow";
@@ -33,7 +33,7 @@ public interface Hessian2FactoryInitializer {
     SerializerFactory getSerializerFactory();
 
     static Hessian2FactoryInitializer getInstance() {
-        String whitelist = ConfigurationUtils.getProperty(WHITELIST);
+        String whitelist = System.getProperty(WHITELIST);
         if (StringUtils.isNotEmpty(whitelist)) {
             return loader.getExtension("whitelist");
         }
diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java
index 9614319ed2..d17f135a0d 100644
--- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java
+++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/WhitelistHessian2FactoryInitializer.java
@@ -16,7 +16,6 @@
  */
 package org.apache.dubbo.common.serialize.hessian2.dubbo;
 
-import org.apache.dubbo.common.config.ConfigurationUtils;
 import org.apache.dubbo.common.serialize.hessian2.Hessian2SerializerFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 
@@ -30,10 +29,10 @@ public class WhitelistHessian2FactoryInitializer extends AbstractHessian2Factory
     @Override
     public SerializerFactory createSerializerFactory() {
         SerializerFactory serializerFactory = new Hessian2SerializerFactory();
-        String whiteList = ConfigurationUtils.getProperty(WHITELIST);
+        String whiteList = System.getProperty(WHITELIST);
         if ("true".equals(whiteList)) {
             serializerFactory.getClassFactory().setWhitelist(true);
-            String allowPattern = ConfigurationUtils.getProperty(ALLOW);
+            String allowPattern = System.getProperty(ALLOW);
             if (StringUtils.isNotEmpty(allowPattern)) {
                 for (String pattern : allowPattern.split(";")) {
                     serializerFactory.getClassFactory().allow(pattern);
@@ -41,7 +40,7 @@ public class WhitelistHessian2FactoryInitializer extends AbstractHessian2Factory
             }
         } else {
             serializerFactory.getClassFactory().setWhitelist(false);
-            String denyPattern = ConfigurationUtils.getProperty(DENY);
+            String denyPattern = System.getProperty(DENY);
             if (StringUtils.isNotEmpty(denyPattern)) {
                 for (String pattern : denyPattern.split(";")) {
                     serializerFactory.getClassFactory().deny(pattern);
diff --git a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java
index 3bd6113ac5..52f17e168a 100644
--- a/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java
+++ b/dubbo-spring-boot/dubbo-spring-boot-compatible/actuator/src/main/java/org/apache/dubbo/spring/boot/actuate/endpoint/metadata/DubboShutdownMetadata.java
@@ -61,7 +61,7 @@ public class DubboShutdownMetadata extends AbstractDubboMetadata {
         shutdownCountData.put("services", serviceBeansMap.size());
 
         // Reference Beans
-        Collection> references = ApplicationModel.getConfigManager().getReferences();
+        Collection> references = ApplicationModel.defaultModel().getApplicationConfigManager().getReferences();
         for (ReferenceConfigBase reference : references) {
             reference.destroy();
         }
diff --git a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
index 074baeb81f..fbff776af7 100644
--- a/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
+++ b/dubbo-test/dubbo-test-spring/src/main/java/org/apache/dubbo/test/spring/SpringJavaConfigBeanTest.java
@@ -34,6 +34,7 @@ import org.apache.dubbo.test.common.ZooKeeperServer;
 import org.apache.dubbo.test.common.api.DemoService;
 import org.apache.dubbo.test.common.impl.DemoServiceImpl;
 import org.apache.dubbo.test.spring.context.MockSpringInitializationCustomizer;
+
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeAll;
@@ -83,7 +84,7 @@ public class SpringJavaConfigBeanTest {
         try {
             consumerContext.start();
 
-            ConfigManager configManager = ApplicationModel.getConfigManager();
+            ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
             ApplicationConfig application = configManager.getApplication().get();
             Assertions.assertEquals(false, application.getQosEnable());
             Assertions.assertEquals("Tom", application.getOwner());