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

[dubbo] branch 3.0 updated: Add 3.0 Multi Instance Support (#8662)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new ff39bf3  Add 3.0 Multi Instance Support (#8662)
ff39bf3 is described below

commit ff39bf36c35316061e7e028abd28dd392405e7f0
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Thu Sep 2 17:54:20 2021 +0800

    Add 3.0 Multi Instance Support (#8662)
    
    * Add ExtensionDirector and Models
    
    * Fix access static getter method of ApplicationModel
    
    * Replace ExtensionFactory with ExtensionInjector
    
    * specify scope of some SPIs
    
    * Support scoped injection for extension
    
    * improve create extension loader logic
    
    * Add ScopeModel and ScopeBeanFactory, fix extension initialization of XxxConfig
    
    * polish doc of scope model
    
    * Extract FrameworkStatusReportService from FrameworkStatusReporter
    
    * Fix application model of default bootstrap instance
    
    * Pass scope model through URL
    
    * Fix scope model of registry, metadata, cluster and so on
    
    * exact ServiceModel from ProviderModel and ConsumerModel
    
    * Add ASF license header for ScopeBeanFactoryInitializer
    
    * Remove unused import
    
    * Remove unused import
    
    * Fix ut in ConfigManagerTest
    
    * Change default Scope Behave
    
    * Resolve recursive creation of Scope Model
    
    * Fix inject default model when scope is parent
    
    * Fix inject default model when scope is parent
    
    * Compact with url without ScopeModel
    
    * Change HttpBinder Scope
    
    * Change some SPIs' scope
    
    * Fix setApplicationModel override issue of MetadataServiceNameMapping
    
    * Default inject ScopeModel in ConfigManager
    
    * Add default Scope for AbstractConfig when init
    
    * Fix field override & Fix ut env
    
    * Fix zk not startup in DubboBootstrapMultiInstanceTest
    
    * Fix ExtensionAccessor not inject in UT of MetricsFilterTest
    
    * Compact old style getName
    
    * Fix UT in DNSServiceDiscoveryTest
    
    * Compact old style ApplicationModel
    
    * Fix UT in DNSServiceDiscoveryTest
    
    * Fix repository changed after ApplicationModel destroyed
    
    * Fix SpringExtensionInjector pollution in UT
    
    * Pass ApplicationModel in ServiceInstance
    
    * reintroduce metadata delay key
    
    * Add Transient on ApplicationModel getter of DefaultServiceInstance
    
    * Fix Configurator Listener in Singleton mode override issue
    
    * Fix Configurator Listener in Singleton mode override issue
    
    * Compact old style getApplication
    
    * Invocation pass ServiceModel
    
    * Compact old style registerConsumer
    
    * Fix NPE in RpcInvocation
    
    * Add ServiceModel pass when init
    
    * Fix ServiceModel cast error
    
    * Add ServiceModel pass when invoke
    
    * Fix NPE when simplify registry url
    
    * Revert "Resolve recursive creation of Scope Model"
    
    This reverts commit 37a99957
    
    * Improve scope model aware
    
    * polish scope model
    
    * Cleanup ApplicationModel.defaultModel usage
    
    * Fix ut
    
    * Compatible with 2.6 Registry
    
    * Fix ut
    
    * Add Callback Service build ProviderModel
    
    * improve scope model of config bean
    
    * Fix scope model of reference/service model
    
    * Revert CallbackServiceCodec for dev
    
    * Fix scope model NPE
    
    * Fix consumer url NPE
    
    * Add Callback Service build ProviderModel
    
    * Fix NPE when destroy
    
    * Fix ut
    
    * add failback logic for ut
    
    * Fix ut
    
    * Add Scope Model check
    
    * Fix uts
    
    * Fix ut in DubboBootstrapTest
    
    * Fix ut in DubboBootstrapTest
    
    * Fix uts
    
    * Reset ApplicationModel Before Test
    
    Co-authored-by: gongdewei <ky...@qq.com>
---
 .../cluster/filter/DefaultFilterChainBuilder.java  |   9 +-
 .../rpc/cluster/filter/FilterChainBuilder.java     |   4 +-
 .../rpc/cluster/filter/ProtocolFilterWrapper.java  |  10 +-
 .../DefaultGovernanceRuleRepositoryImpl.java       |  12 +-
 .../governance/GovernanceRuleRepository.java       |   4 +-
 .../loadbalance/ShortestResponseLoadBalance.java   |  10 +-
 .../cluster/router/mesh/route/MeshRuleManager.java |   2 +-
 .../cluster/support/wrapper/AbstractCluster.java   |   2 +-
 .../org/apache/dubbo/rpc/cluster/StickyTest.java   |   2 -
 .../rpc/cluster/directory/MockDirInvocation.java   |  11 +
 .../ShortestResponseLoadBalanceTest.java           |   4 +
 .../router/mesh/route/MeshRuleManagerTest.java     |  19 +-
 .../src/main/java/org/apache/dubbo/common/URL.java |  47 ++-
 .../java/org/apache/dubbo/common/URLBuilder.java   |   9 +
 .../dubbo/common/beans/ScopeBeanException.java     |  13 +-
 .../ScopeBeanExtensionInjector.java}               |  30 +-
 .../common/beans/factory/ScopeBeanFactory.java     | 195 ++++++++++
 .../beans/factory/ScopeBeanFactoryInitializer.java |  75 ++++
 .../org/apache/dubbo/common/compiler/Compiler.java |   3 +-
 .../dubbo/common/config/ConfigurationUtils.java    | 117 ++++--
 .../common/config/OrderedPropertiesProvider.java   |   3 +-
 .../configcenter/DynamicConfigurationFactory.java  |  19 +-
 .../dubbo/common/constants/CommonConstants.java    |   4 +
 .../apache/dubbo/common/context/FrameworkExt.java  |   3 +-
 .../org/apache/dubbo/common/convert/Converter.java |   3 +-
 .../convert/multiple/MultiValueConverter.java      |   3 +-
 .../dubbo/common/extension/ExtensionAccessor.java  |  45 +++
 .../common/extension/ExtensionAccessorAware.java   |  11 +-
 .../dubbo/common/extension/ExtensionDirector.java  | 127 ++++++
 .../dubbo/common/extension/ExtensionFactory.java   |  11 +-
 ...xtensionFactory.java => ExtensionInjector.java} |  13 +-
 .../dubbo/common/extension/ExtensionLoader.java    | 157 +++++---
 ...ionFactory.java => ExtensionPostProcessor.java} |  20 +-
 .../dubbo/common/extension/ExtensionScope.java     |  78 ++++
 .../org/apache/dubbo/common/extension/SPI.java     |   4 +
 .../factory/AdaptiveExtensionFactory.java          |  55 ---
 .../inject/AdaptiveExtensionInjector.java          |  77 ++++
 .../SpiExtensionInjector.java}                     |  23 +-
 .../apache/dubbo/common/infra/InfraAdapter.java    |   3 +-
 .../common/infra/support/EnvironmentAdapter.java   |  19 +-
 .../dubbo/common/lang/ShutdownHookCallback.java    |   3 +-
 .../apache/dubbo/common/logger/LoggerAdapter.java  |   3 +-
 .../apache/dubbo/common/status/StatusChecker.java  |   3 +-
 ...rter.java => FrameworkStatusReportService.java} |  60 +--
 .../status/reporter/FrameworkStatusReporter.java   |  80 +---
 .../org/apache/dubbo/common/store/DataStore.java   |   3 +-
 .../apache/dubbo/common/threadpool/ThreadPool.java |   4 +-
 .../manager/DefaultExecutorRepository.java         |  27 +-
 .../threadpool/manager/ExecutorRepository.java     |   3 +-
 .../url/component/DubboServiceAddressURL.java      |  12 +
 .../common/url/component/ServiceConfigURL.java     |  24 +-
 .../url/component/param/DynamicParamSource.java    |   3 +-
 .../org/apache/dubbo/common/utils/NetUtils.java    |   5 +-
 .../org/apache/dubbo/config/AbstractConfig.java    |  64 ++-
 .../dubbo/config/AbstractInterfaceConfig.java      |  72 +++-
 .../apache/dubbo/config/AbstractMethodConfig.java  |  20 +
 .../org/apache/dubbo/config/ApplicationConfig.java |  13 +-
 .../apache/dubbo/config/ConfigCenterConfig.java    |   4 +-
 .../apache/dubbo/config/MetadataReportConfig.java  |   4 +-
 .../java/org/apache/dubbo/config/MethodConfig.java |   3 +-
 .../apache/dubbo/config/ReferenceConfigBase.java   |  12 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |   6 +-
 .../org/apache/dubbo/config/ServiceConfigBase.java |  20 +-
 .../apache/dubbo/config/context/ConfigManager.java |  21 +-
 .../dubbo/rpc/model/ApplicationInitListener.java   |   3 +-
 .../apache/dubbo/rpc/model/ApplicationModel.java   | 189 ++++++---
 .../dubbo/rpc/model/BuiltinServiceDetector.java    |   3 +-
 .../org/apache/dubbo/rpc/model/ConsumerModel.java  | 114 ++----
 .../org/apache/dubbo/rpc/model/FrameworkModel.java |  73 ++++
 ...uiltinServiceDetector.java => ModuleModel.java} |  26 +-
 .../org/apache/dubbo/rpc/model/ProviderModel.java  |  91 ++---
 .../org/apache/dubbo/rpc/model/ScopeModel.java     |  59 +++
 ...erviceDetector.java => ScopeModelAccessor.java} |  20 +-
 .../apache/dubbo/rpc/model/ScopeModelAware.java    |  52 +++
 .../model/ScopeModelAwareExtensionProcessor.java   |  76 ++++
 ...tListener.java => ScopeModelPostProcessor.java} |  15 +-
 .../org/apache/dubbo/rpc/model/ScopeModelUtil.java |  80 ++++
 .../org/apache/dubbo/rpc/model/ServiceModel.java   | 128 ++++++
 .../apache/dubbo/rpc/model/ServiceRepository.java  |  36 +-
 ....apache.dubbo.common.extension.ExtensionFactory |   2 -
 ...apache.dubbo.common.extension.ExtensionInjector |   3 +
 .../common/config/ConfigurationUtilsTest.java      |   6 +-
 .../dubbo/common/config/EnvironmentTest.java       |   3 +-
 .../FileSystemDynamicConfigurationFactoryTest.java |   5 +-
 .../common/extension/ExtensionDirectorTest.java    | 271 +++++++++++++
 .../common/extension/ExtensionLoaderTest.java      |  16 +-
 .../common/extension/director/FooAppProvider.java  |  16 +-
 .../common/extension/director/FooAppService.java   |  18 +-
 .../extension/director/FooFrameworkProvider.java   |  16 +-
 .../extension/director/FooFrameworkService.java    |  18 +-
 .../extension/director/FooModuleProvider.java      |  16 +-
 .../extension/director/FooModuleService.java       |  16 +-
 .../extension/director/impl/BaseTestService.java   |  55 +++
 .../extension/director/impl/TestAppProvider.java   |  12 +-
 .../extension/director/impl/TestAppService.java    |  72 ++++
 .../director/impl/TestFrameworkProvider.java       |  12 +-
 .../director/impl/TestFrameworkService.java        |  61 +++
 .../director/impl/TestModuleProvider.java          |  13 +-
 .../extension/director/impl/TestModuleService.java |  83 ++++
 .../dubbo/config/context/ConfigManagerTest.java    |  32 +-
 ....dubbo.common.extension.director.FooAppProvider |   1 +
 ...e.dubbo.common.extension.director.FooAppService |   1 +
 ....common.extension.director.FooFrameworkProvider |   1 +
 ...o.common.extension.director.FooFrameworkService |   1 +
 ...bbo.common.extension.director.FooModuleProvider |   1 +
 ...ubbo.common.extension.director.FooModuleService |   1 +
 .../dubbo/common/extension/ExtensionFactory.java   |   3 +-
 .../java/com/alibaba/dubbo/rpc/Invocation.java     |  22 ++
 .../dubbo/common/extension/ExtensionTest.java      |  14 +-
 .../dubbo/common/extension/MyExtensionFactory.java |  12 +
 .../org/apache/dubbo/service/MockInvocation.java   |  11 +
 dubbo-config/dubbo-config-api/pom.xml              |   5 +
 .../org/apache/dubbo/config/DubboShutdownHook.java |   4 +-
 .../org/apache/dubbo/config/ReferenceConfig.java   |  49 ++-
 .../org/apache/dubbo/config/ServiceConfig.java     |  63 +--
 .../dubbo/config/bootstrap/DubboBootstrap.java     | 431 +++++++++++++++------
 .../ConfigurableMetadataServiceExporter.java       |  28 +-
 .../ServiceInstanceHostPortCustomizer.java         |   5 +-
 .../dubbo/config/utils/ConfigValidationUtils.java  |  16 +-
 .../dubbo/config/utils/ReferenceConfigCache.java   |  15 +-
 .../apache/dubbo/config/AbstractConfigTest.java    |  36 +-
 .../dubbo/config/ConfigCenterConfigTest.java       |  13 +-
 .../apache/dubbo/config/ConsumerConfigTest.java    |   9 +-
 .../apache/dubbo/config/ReferenceConfigTest.java   | 305 +++++----------
 .../apache/dubbo/config/RegistryConfigTest.java    |   6 +-
 .../org/apache/dubbo/config/ServiceConfigTest.java |   9 +-
 .../bootstrap/DubboBootstrapMultiInstanceTest.java | 169 ++++++++
 .../dubbo/config/bootstrap/DubboBootstrapTest.java |   7 +-
 .../org/apache/dubbo/config/cache/CacheTest.java   |   2 +-
 .../dubbo/config/url/InvokerSideConfigUrlTest.java |   4 +-
 ...egistryCenterExportProviderIntegrationTest.java |  10 +-
 ...ceDiscoveryRegistryRegistryServiceListener.java |   9 +-
 ...RegistryCenterDubboProtocolIntegrationTest.java |   2 +-
 ...egistryCenterExportProviderIntegrationTest.java |  10 +-
 .../metadata/MetadataServiceExporterTest.java      |  10 +-
 .../dubbo/config/spring/ConfigCenterBean.java      |   4 +-
 .../apache/dubbo/config/spring/ServiceBean.java    |   8 +-
 .../spring/context/DubboConfigBeanInitializer.java |   7 +-
 .../DubboInfraBeanRegisterPostProcessor.java       |   9 +-
 ...onFactory.java => SpringExtensionInjector.java} |  16 +-
 .../spring/status/DataSourceStatusChecker.java     |   4 +-
 .../config/spring/status/SpringStatusChecker.java  |   4 +-
 ....apache.dubbo.common.extension.ExtensionFactory |   1 -
 ...apache.dubbo.common.extension.ExtensionInjector |   1 +
 .../org/apache/dubbo/config/spring/ConfigTest.java |  20 +-
 .../dubbo/config/spring/JavaConfigBeanTest.java    |   5 +-
 .../DubboComponentScanRegistrarTest.java           |   4 +-
 .../context/annotation/EnableDubboConfigTest.java  |   4 +-
 ...yTest.java => SpringExtensionInjectorTest.java} |  22 +-
 .../spring/issues/issue7003/Issue7003Test.java     |   5 +-
 .../consumer/PropertyConfigurerTest.java           |   6 +-
 .../consumer2/PropertySourcesConfigurerTest.java   |   6 +-
 .../consumer3/PropertySourcesInJavaConfigTest.java |  15 +-
 .../javaconfig/JavaConfigReferenceBeanTest.java    |  45 ++-
 .../spring/schema/DubboNamespaceHandlerTest.java   |   4 +-
 .../spring/status/DataSourceStatusCheckerTest.java |   4 +-
 .../spring/status/SpringStatusCheckerTest.java     |  13 +-
 .../META-INF/native-image/reflect-config.json      |   4 +-
 .../META-INF/native-image/reflect-config.json      |   4 +-
 dubbo-distribution/dubbo-all/pom.xml               |   2 +-
 dubbo-distribution/dubbo-core-spi/pom.xml          |   2 +-
 .../dubbo/metadata/AbstractServiceNameMapping.java |  18 +-
 .../apache/dubbo/metadata/MetadataConstants.java   |   4 +-
 .../dubbo/metadata/MetadataServiceExporter.java    |   3 +-
 .../apache/dubbo/metadata/ServiceNameMapping.java  |  12 +-
 .../dubbo/metadata/WritableMetadataService.java    |  21 +-
 .../metadata/report/MetadataReportInstance.java    |  32 +-
 .../dubbo/metadata/ServiceNameMappingTest.java     |   4 +-
 .../report/support/AbstractMetadataReportTest.java |   2 +-
 .../apache/dubbo/monitor/dubbo/MetricsFilter.java  |  25 +-
 .../dubbo/monitor/dubbo/MetricsFilterTest.java     |   6 +
 .../apache/dubbo/qos/command/impl/BaseOffline.java |   2 +-
 .../apache/dubbo/qos/command/impl/BaseOnline.java  |   2 +-
 .../dubbo/qos/command/impl/InvokeTelnet.java       |   2 +-
 .../org/apache/dubbo/qos/command/impl/Live.java    |   2 +-
 .../java/org/apache/dubbo/qos/command/impl/Ls.java |   4 +-
 .../org/apache/dubbo/qos/command/impl/Ready.java   |   2 +-
 .../org/apache/dubbo/qos/command/impl/Startup.java |   2 +-
 .../qos/probe/impl/ProviderReadinessProbe.java     |   2 +-
 .../dubbo/qos/command/impl/InvokeTelnetTest.java   |   3 +-
 .../org/apache/dubbo/qos/command/impl/LsTest.java  |   2 +-
 .../apache/dubbo/qos/command/impl/OfflineTest.java |   4 +-
 .../apache/dubbo/qos/command/impl/OnlineTest.java  |   2 +-
 .../dubbo/qos/command/impl/SelectTelnetTest.java   |   2 +-
 .../org/apache/dubbo/registry/RegistryFactory.java |   4 +-
 .../registry/client/DefaultServiceInstance.java    |  32 +-
 .../dubbo/registry/client/InstanceAddressURL.java  |  12 +
 .../registry/client/RegistryClusterIdentifier.java |   3 +-
 .../client/SelfHostMetaServiceDiscovery.java       |  18 +-
 .../dubbo/registry/client/ServiceDiscovery.java    |   3 +-
 .../registry/client/ServiceDiscoveryRegistry.java  |   8 +-
 .../client/ServiceDiscoveryRegistryDirectory.java  |  36 +-
 .../dubbo/registry/client/ServiceInstance.java     |   8 +
 .../registry/client/ServiceInstanceCustomizer.java |   4 +-
 .../listener/ServiceInstancesChangedListener.java  |   2 +-
 .../metadata/MetadataServiceNameMapping.java       |  77 ++--
 ...MetadataServiceURLParamsMetadataCustomizer.java |   3 +-
 .../registry/client/metadata/MetadataUtils.java    |  34 +-
 .../metadata/ProtocolPortsMetadataCustomizer.java  |   2 +-
 .../ServiceInstanceMetadataCustomizer.java         |   9 +-
 .../metadata/ServiceInstanceMetadataUtils.java     |   6 +-
 .../StandardMetadataServiceURLBuilder.java         |  16 +-
 .../store/InMemoryWritableMetadataService.java     |  23 +-
 .../metadata/store/RemoteMetadataServiceImpl.java  |  13 +-
 .../DefaultMigrationAddressComparator.java         |   2 +-
 .../client/migration/MigrationInvoker.java         |  21 +-
 .../client/migration/MigrationRuleHandler.java     |  12 +-
 .../client/migration/MigrationRuleListener.java    |  30 +-
 .../client/migration/model/MigrationRule.java      |  12 +-
 .../integration/AbstractConfiguratorListener.java  |  17 +-
 .../InterfaceCompatibleRegistryProtocol.java       |   2 +-
 .../registry/integration/RegistryDirectory.java    |  24 +-
 .../registry/integration/RegistryProtocol.java     | 145 ++++---
 .../integration/RegistryProtocolListener.java      |   4 +-
 .../registry/support/AbstractRegistryFactory.java  |   2 +-
 .../support/CacheableFailbackRegistry.java         |  33 +-
 .../client/DefaultServiceInstanceTest.java         |   7 +-
 .../registry/client/InstanceAddressURLTest.java    |   3 +-
 .../client/ServiceDiscoveryRegistryTest.java       |  91 ++---
 .../registry/client/ServiceDiscoveryTest.java      |  31 +-
 .../metadata/MetadataServiceNameMappingTest.java   | 118 +++---
 .../metadata/MetadataServiceURLBuilderTest.java    |   3 +-
 .../ProtocolPortsMetadataCustomizerTest.java       |   4 +-
 .../ServiceInstanceMetadataCustomizerTest.java     |   6 +-
 .../SpringCloudMetadataServiceURLBuilderTest.java  |   3 +-
 .../store/InMemoryMetadataServiceTest.java         |   2 +
 .../client/migration/MigrationInvokerTest.java     |   3 +-
 .../migration/MigrationRuleListenerTest.java       |  10 +-
 .../client/migration/model/MigrationRuleTest.java  | 129 +++---
 .../registry/integration/RegistryProtocolTest.java | 106 +++--
 .../support/ServiceOrientedRegistryTest.java       |   9 +-
 .../dubbo/registry/dns/DNSServiceDiscovery.java    |   3 +-
 .../registry/dns/DNSServiceDiscoveryTest.java      |  26 +-
 .../kubernetes/KubernetesServiceDiscovery.java     |   3 +-
 .../kubernetes/KubernetesServiceDiscoveryTest.java |  11 +-
 .../registry/nacos/NacosServiceDiscovery.java      |   6 +-
 .../nacos/util/NacosNamingServiceUtils.java        |   9 +-
 .../dubbo/registry/xds/XdsServiceDiscovery.java    |   3 +-
 .../zookeeper/ZookeeperServiceDiscovery.java       |   4 +-
 .../ZookeeperServiceDiscoveryChangeWatcher.java    |   7 +-
 .../zookeeper/util/CuratorFrameworkUtils.java      |  13 +-
 .../zookeeper/ZookeeperServiceDiscoveryTest.java   |   9 +-
 .../org/apache/dubbo/remoting/ChannelHandler.java  |   3 +-
 .../main/java/org/apache/dubbo/remoting/Codec.java |   3 +-
 .../java/org/apache/dubbo/remoting/Codec2.java     |   3 +-
 .../java/org/apache/dubbo/remoting/Dispatcher.java |   3 +-
 .../org/apache/dubbo/remoting/Transporter.java     |   3 +-
 .../dubbo/remoting/api/ConnectionManager.java      |   3 +-
 .../dubbo/remoting/api/NettyEventLoopFactory.java  |   7 +-
 .../org/apache/dubbo/remoting/api/SslContexts.java |  10 +-
 .../apache/dubbo/remoting/api/WireProtocol.java    |   3 +-
 .../apache/dubbo/remoting/exchange/Exchanger.java  |   3 +-
 .../remoting/exchange/codec/ExchangeCodec.java     |   2 +-
 .../dubbo/remoting/telnet/TelnetHandler.java       |   3 +-
 .../dubbo/remoting/transport/CodecSupport.java     |   3 +-
 .../remoting/zookeeper/ZookeeperTransporter.java   |   3 +-
 .../org/apache/dubbo/remoting/http/HttpBinder.java |   3 +-
 .../transport/netty4/NettyEventLoopFactory.java    |   8 +-
 .../org/apache/dubbo/rpc/ExporterListener.java     |   3 +-
 .../main/java/org/apache/dubbo/rpc/Invocation.java |   5 +
 .../main/java/org/apache/dubbo/rpc/Protocol.java   |   3 +-
 .../java/org/apache/dubbo/rpc/ProxyFactory.java    |   3 +-
 .../java/org/apache/dubbo/rpc/RpcInvocation.java   |  78 +++-
 .../org/apache/dubbo/rpc/filter/GenericFilter.java |  14 +-
 .../rpc/protocol/ProtocolListenerWrapper.java      |   6 +-
 .../rpc/protocol/ProtocolSerializationWrapper.java |   5 +-
 .../dubbo/rpc/proxy/InvokerInvocationHandler.java  |  17 +-
 .../org/apache/dubbo/rpc/support/MockInvoker.java  |   8 +-
 .../apache/dubbo/rpc/support/MockInvocation.java   |  11 +
 .../org/apache/dubbo/rpc/support/RpcUtilsTest.java |   2 +-
 .../rpc/protocol/dubbo/CallbackServiceCodec.java   |  33 +-
 .../protocol/dubbo/DecodeableRpcInvocation.java    |   6 +-
 .../rpc/protocol/dubbo/DecodeableRpcResult.java    |   3 +-
 .../dubbo/rpc/protocol/dubbo/DubboInvoker.java     |   5 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    |  25 +-
 .../rpc/protocol/dubbo/filter/FutureFilter.java    |   8 +-
 .../rpc/protocol/dubbo/ArgumentCallbackTest.java   |  16 +-
 .../rpc/protocol/dubbo/DubboProtocolTest.java      |   6 +-
 .../dubbo/rpc/protocol/dubbo/MultiThreadTest.java  |   4 +-
 .../dubbo/rpc/protocol/dubbo/RpcFilterTest.java    |   2 +-
 .../dubbo/decode/DubboTelnetDecodeTest.java        |   6 +-
 .../dubbo/rpc/protocol/dubbo/support/EnumBak.java  |   6 +-
 .../dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java  |   6 +-
 .../dubbo/rpc/protocol/grpc/GrpcProtocol.java      |  11 +-
 .../grpc/interceptors/ClientInterceptor.java       |   3 +-
 .../grpc/interceptors/GrpcConfigurator.java        |   3 +-
 .../grpc/interceptors/ServerInterceptor.java       |   3 +-
 .../grpc/interceptors/ServerTransportFilter.java   |   3 +-
 .../dubbo/rpc/protocol/grpc/GrpcProtocolTest.java  |  23 +-
 .../dubbo/rpc/protocol/rest/RestProtocol.java      |   7 +-
 .../dubbo/rpc/protocol/rest/RestProtocolTest.java  |   2 +-
 .../rpc/protocol/tri/AbstractServerStream.java     |  10 +-
 .../dubbo/rpc/protocol/tri/PathResolver.java       |   3 +-
 .../rpc/protocol/tri/TripleClientHandler.java      |   2 +-
 .../tri/TripleHttp2FrameServerHandler.java         |   2 +-
 .../dubbo/rpc/protocol/tri/TripleProtocolTest.java |   7 +-
 .../common/serialize/MultipleSerialization.java    |   3 +-
 .../dubbo/common/serialize/Serialization.java      |   3 +-
 .../hessian2/dubbo/Hessian2FactoryInitializer.java |   6 +-
 .../dubbo/WhitelistHessian2FactoryInitializer.java |   7 +-
 .../endpoint/metadata/DubboShutdownMetadata.java   |   2 +-
 .../test/spring/SpringJavaConfigBeanTest.java      |   3 +-
 302 files changed, 4730 insertions(+), 2051 deletions(-)

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 e2e26d2..478ad66 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 <T> Invoker<T> buildInvokerChain(final Invoker<T> originalInvoker, String key, String group) {
         Invoker<T> last = originalInvoker;
-        List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(originalInvoker.getUrl(), key, group);
+        URL url = originalInvoker.getUrl();
+        List<Filter> 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 <T> ClusterInvoker<T> buildClusterInvokerChain(final ClusterInvoker<T> originalInvoker, String key, String group) {
         ClusterInvoker<T> last = originalInvoker;
-        List<ClusterFilter> filters = ExtensionLoader.getExtensionLoader(ClusterFilter.class).getActivateExtension(originalInvoker.getUrl(), key, group);
+        URL url = originalInvoker.getUrl();
+        List<ClusterFilter> 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 949a66c..7edab08 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 389b173..efbc454 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 <T> FilterChainBuilder getFilterChainBuilder(URL url) {
+        return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel()).getDefaultExtension();
+    }
+
     @Override
     public <T> Invoker<T> refer(Class<T> 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 dfebf27..61f8aeb 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 aaa604f..d375c8b 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 9c0967b..7f0625a 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<RpcStatus, SlideWindowData> 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 b07fede..c64d780 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<MeshEnvListenerFactory> 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 4ede912..d2a6ea3 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<T> last = clusterInvoker;
         AbstractClusterInvoker<T> 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 f9f9311..eddd7f6 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/StickyTest.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster;
 
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.rpc.AppResponse;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
@@ -72,7 +71,6 @@ public class StickyTest {
 
         clusterinvoker = new StickyClusterInvoker<StickyTest>(dic);
 
-        ExtensionLoader.resetExtensionLoader(LoadBalance.class);
     }
 
     @Test
diff --git a/dubbo-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 3923937..75ad1cc 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;
@@ -130,6 +131,16 @@ public class MockDirInvocation implements Invocation {
     }
 
     @Override
+    public void setServiceModel(ServiceModel serviceModel) {
+
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return null;
+    }
+
+    @Override
     public Map<Object, Object> 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 345c370..aebaf00 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 214a65b..74be2fd 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<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+        Optional<DynamicConfiguration> 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<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+        Optional<DynamicConfiguration> 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<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
+        Optional<DynamicConfiguration> 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 65ec401..dd40e76 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<String, Object> 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<String, Object> 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<String, String>) 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<String, String>) 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<String, Number> getNumbers() {
         // concurrent initialization is tolerant
         if (numbers == null) {
@@ -1449,7 +1481,7 @@ class URL implements Serializable {
     }
 
     protected <T extends URL> 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<String, Object> getAttributes() {
-        return new HashMap<>();
+        return attributes;
     }
 
     public URL addAttributes(Map<String, Object> 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 83a2dab..21e114f 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;
 
@@ -207,6 +210,12 @@ public final class URLBuilder extends ServiceConfigURL {
     }
 
     @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)) {
             return this;
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
similarity index 74%
copy from dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
index f9602b4..a6bb1b3 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanException.java
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.beans;
 
-import com.alibaba.dubbo.common.extension.ExtensionFactory;
+public class ScopeBeanException extends RuntimeException {
 
-public class MyExtensionFactory implements ExtensionFactory {
+    public ScopeBeanException(String message, Throwable cause) {
+        super(message, cause);
+    }
 
-    @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        return null;
+    public ScopeBeanException(String message) {
+        super(message);
     }
 }
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/beans/ScopeBeanExtensionInjector.java
similarity index 52%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/extension/factory/SpiExtensionFactory.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/beans/ScopeBeanExtensionInjector.java
index 46cbe19..05dc985 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/beans/ScopeBeanExtensionInjector.java
@@ -14,26 +14,28 @@
  * 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.beans;
 
-import org.apache.dubbo.common.extension.ExtensionFactory;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.extension.SPI;
+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;
 
 /**
- * SpiExtensionFactory
+ * Inject scope bean to SPI extension instance
  */
-public class SpiExtensionFactory implements ExtensionFactory {
+public class ScopeBeanExtensionInjector implements ExtensionInjector, ScopeModelAware {
+    private ScopeModel scopeModel;
+    private ScopeBeanFactory beanFactory;
 
     @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
-            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
-            if (!loader.getSupportedExtensions().isEmpty()) {
-                return loader.getAdaptiveExtension();
-            }
-        }
-        return null;
+    public void setScopeModel(ScopeModel scopeModel) {
+        this.scopeModel = scopeModel;
+        this.beanFactory = scopeModel.getBeanFactory();
     }
 
+    @Override
+    public <T> T getInstance(Class<T> type, String name) {
+        return beanFactory.getBean(name, type);
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
new file mode 100644
index 0000000..bdc45e4
--- /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<ExtensionPostProcessor> extensionPostProcessors;
+    private Map<Class, AtomicInteger> beanNameIdCounterMap = new ConcurrentHashMap<>();
+    private List<BeanInfo> registeredBeanInfos = Collections.synchronizedList(new ArrayList<>());
+
+    public ScopeBeanFactory(ScopeBeanFactory parent, ExtensionAccessor extensionAccessor) {
+        this.parent = parent;
+        this.extensionAccessor = extensionAccessor;
+        extensionPostProcessors = extensionAccessor.getExtensionDirector().getExtensionPostProcessors();
+    }
+
+    public <T> T registerBean(Class<T> bean) throws ScopeBeanException {
+        return this.registerBean(null, bean);
+    }
+
+    public <T> T registerBean(String name, Class<T> clazz) throws ScopeBeanException {
+        T instance = getBean(name, clazz);
+        if (instance != null) {
+            throw new ScopeBeanException("already exists bean with same name and type, name=" + name + ", type=" + clazz.getName());
+        }
+        try {
+            instance = clazz.newInstance();
+        } catch (Throwable e) {
+            throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName());
+        }
+        registerBean(name, instance);
+        return instance;
+    }
+
+    public void registerBean(Object bean) {
+        this.registerBean(null, bean);
+    }
+
+    public void registerBean(String name, Object bean) {
+        // 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> T registerBeanIfAbsent(Class<T> type) {
+        return registerBeanIfAbsent(null, type);
+    }
+
+    public <T> T registerBeanIfAbsent(String name, Class<T> type) {
+        T bean = getBean(name, type);
+        if (bean == null) {
+            bean = registerBean(name, type);
+        }
+        return bean;
+    }
+
+    public <T> T registerBeanIfAbsent(Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
+        return registerBeanIfAbsent(null, type, mappingFunction);
+    }
+
+    public <T> T registerBeanIfAbsent(String name, Class<T> type, Function<? super Class<T>, ? 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> 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> T getBean(Class<T> type) {
+        return this.getBean(null, type);
+    }
+
+    public <T> T getBean(String name, Class<T> type) {
+        T bean = getBeanInternal(name, type);
+        if (bean == null && parent != null) {
+            return parent.getBean(name, type);
+        }
+        return bean;
+    }
+
+    private <T> T getBeanInternal(String name, Class<T> type) {
+        List<BeanInfo> 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<String> 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 0000000..07ced8d
--- /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 acac7bd..ecf6f14 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 913b218..c206f2b 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<String, String> 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<DynamicConfigurationFactory> 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 4068311..e1c02e7 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 f1f6100..a6b6dbc 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
@@ -17,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<DynamicConfigurationFactory> factoryClass = DynamicConfigurationFactory.class;
-        ExtensionLoader<DynamicConfigurationFactory> loader = getExtensionLoader(factoryClass);
-        return loader.getOrDefaultExtension(name);
-    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index 7c59e88..c1019ea 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 47cd15e..8fd724d 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 e36fdf2..ec7c1da 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 <T> The target type
  * @since 2.7.6
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 @FunctionalInterface
 public interface Converter<S, T> 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 637d1a8..9b5210d 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 <S> The source type
  * @since 2.7.6
  */
-@SPI
+@SPI(scope = ExtensionScope.FRAMEWORK)
 public interface MultiValueConverter<S> 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 0000000..be13080
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessor.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.extension;
+
+/**
+ * Uniform accessor for extension
+ */
+public interface ExtensionAccessor {
+
+    ExtensionDirector getExtensionDirector();
+
+    default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+        return this.getExtensionDirector().getExtensionLoader(type);
+    }
+
+    default <T> T getExtension(Class<T> type, String name) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getExtension(name) : null;
+    }
+
+    default <T> T getAdaptiveExtension(Class<T> type) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null;
+    }
+
+    default <T> T getDefaultExtension(Class<T> type) {
+        ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
+        return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
+    }
+
+}
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
similarity index 78%
copy from dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
index f9602b4..e2215e5 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionAccessorAware.java
@@ -16,12 +16,11 @@
  */
 package org.apache.dubbo.common.extension;
 
-import com.alibaba.dubbo.common.extension.ExtensionFactory;
+/**
+ * SPI extension can implement this aware interface to obtain appropriate {@link ExtensionAccessor} instance.
+ */
+public interface ExtensionAccessorAware {
 
-public class MyExtensionFactory implements ExtensionFactory {
+    void setExtensionAccessor(ExtensionAccessor extensionAccessor);
 
-    @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        return null;
-    }
 }
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 0000000..07d8cde
--- /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.
+ *
+ * <p></p>
+ * <p>ExtensionDirector supports multiple levels, and the child can inherit the parent's extension instances. </p>
+ * <p>The way to find and create an extension instance is similar to Java classloader.</p>
+ */
+public class ExtensionDirector implements ExtensionAccessor {
+
+    private final ConcurrentMap<Class<?>, ExtensionLoader<?>> extensionLoadersMap = new ConcurrentHashMap<>(64);
+    private ExtensionDirector parent;
+    private final ExtensionScope scope;
+    private List<ExtensionPostProcessor> 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<ExtensionPostProcessor> getExtensionPostProcessors() {
+        return extensionPostProcessors;
+    }
+
+    @Override
+    public ExtensionDirector getExtensionDirector() {
+        return this;
+    }
+
+    @Override
+    public <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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<T> loader = (ExtensionLoader<T>) 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 <T> ExtensionLoader<T> createExtensionLoader(Class<T> type) {
+        ExtensionLoader<T> 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 <T> ExtensionLoader<T> createExtensionLoader0(Class<T> type) {
+        ExtensionLoader<T> loader;
+        extensionLoadersMap.putIfAbsent(type, new ExtensionLoader<T>(type, this));
+        loader = (ExtensionLoader<T>) 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 32bb846..6eab44d 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> T getInstance(Class<T> type, String name) {
+        return getExtension(type, name);
+    }
 
     /**
      * Get extension.
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/ExtensionInjector.java
similarity index 73%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionInjector.java
index 32bb846..4906805 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/ExtensionInjector.java
@@ -17,18 +17,21 @@
 package org.apache.dubbo.common.extension;
 
 /**
- * ExtensionFactory
+ * An injector to provide resources for SPI extension.
  */
-@SPI
-public interface ExtensionFactory {
+@SPI(scope = ExtensionScope.SELF)
+public interface ExtensionInjector extends ExtensionAccessorAware {
 
     /**
-     * Get extension.
+     * Get instance of specify type and name.
      *
      * @param type object type.
      * @param name object name.
      * @return object instance.
      */
-    <T> T getExtension(Class<T> type, String name);
+    <T> T getInstance(Class<T> 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 e7d00d2..c71ed7d 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<T> {
 
     private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
 
-    private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
-
-    private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
+    private final ConcurrentMap<Class<?>, Object> extensionInstances = new ConcurrentHashMap<>(64);
 
     private final Class<?> type;
 
-    private final ExtensionFactory objectFactory;
+    private final ExtensionInjector injector;
 
     private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
 
@@ -121,6 +123,9 @@ public class ExtensionLoader<T> {
      * Record all unacceptable exceptions when using SPI
      */
     private Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
+    private ExtensionDirector extensionDirector;
+    private List<ExtensionPostProcessor> extensionPostProcessors;
+    private Environment environment;
 
     public static void setLoadingStrategies(LoadingStrategy... strategies) {
         if (ArrayUtils.isNotEmpty(strategies)) {
@@ -152,52 +157,42 @@ public class ExtensionLoader<T> {
         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());
-    }
-
-    private static <T> boolean withExtensionAnnotation(Class<T> type) {
-        return type.isAnnotationPresent(SPI.class);
+        this.injector = (type == ExtensionInjector.class ? null : extensionDirector.getExtensionLoader(ExtensionInjector.class)
+            .getAdaptiveExtension());
     }
 
-    @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 <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
-        if (loader == null) {
-            EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
-            loader = (ExtensionLoader<T>) 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<String, Class<?>> classes = loader.getExtensionClasses();
-            for (Map.Entry<String, Class<?>> 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<String, Class<?>> classes = loader.getExtensionClasses();
+//            for (Map.Entry<String, Class<?>> 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<T> {
                 }
             }
         });
+        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<T> {
             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<Class<?>> wrapperClassesList = new ArrayList<>();
                 if (cachedWrapperClasses != null) {
                     wrapperClassesList.addAll(cachedWrapperClasses);
@@ -718,6 +709,7 @@ public class ExtensionLoader<T> {
                         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<T> {
         }
     }
 
+    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<T> {
 
                 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<T> {
         Map<String, Class<?>> 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<String, Class<?>> 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<T> {
                                 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<T> {
     @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<T> {
     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/ExtensionFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionPostProcessor.java
similarity index 69%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionFactory.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionPostProcessor.java
index 32bb846..fcc4822 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/ExtensionPostProcessor.java
@@ -17,18 +17,16 @@
 package org.apache.dubbo.common.extension;
 
 /**
- * ExtensionFactory
+ * A Post-processor called before or after extension initialization.
  */
-@SPI
-public interface ExtensionFactory {
+public interface ExtensionPostProcessor {
 
-    /**
-     * Get extension.
-     *
-     * @param type object type.
-     * @param name object name.
-     * @return object instance.
-     */
-    <T> T getExtension(Class<T> type, String name);
+    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 0000000..170a9c0
--- /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.
+     *
+     * <p>Framework scope SPI extension can only obtain {@link FrameworkModel},
+     * cannot get the {@link ApplicationModel} and {@link ModuleModel}.</p>
+     *
+     * <p></p>
+     * Consideration:
+     * <ol>
+     * <li>Some SPI need share data between applications inside framework</li>
+     * <li>Stateless SPI is safe shared inside framework</li>
+     * </ol>
+     */
+    FRAMEWORK,
+
+    /**
+     * The extension instance is used within one application, shared with all modules of the application,
+     * and different applications create different extension instances.
+     *
+     * <p>Application scope SPI extension can obtain {@link FrameworkModel} and {@link ApplicationModel},
+     * cannot get the {@link ModuleModel}.</p>
+     *
+     * <p></p>
+     * Consideration:
+     * <ol>
+     * <li>Isolate extension data in different applications inside framework</li>
+     * <li>Share extension data between all modules inside application</li>
+     * </ol>
+     */
+    APPLICATION,
+
+    /**
+     * The extension instance is used within one module, and different modules create different extension instances.
+     *
+     * <p>Module scope SPI extension can obtain {@link FrameworkModel}, {@link ApplicationModel} and {@link ModuleModel}.</p>
+     *
+     * <p></p>
+     * Consideration:
+     * <ol>
+     * <li>Isolate extension data in different modules inside application</li>
+     * </ol>
+     */
+    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 70aa5b7..47cd1fc 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 d136ebc..0000000
--- 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<ExtensionFactory> factories;
-
-    public AdaptiveExtensionFactory() {
-        ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
-        List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
-        for (String name : loader.getSupportedExtensions()) {
-            list.add(loader.getExtension(name));
-        }
-        factories = Collections.unmodifiableList(list);
-    }
-
-    @Override
-    public <T> T getExtension(Class<T> 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 0000000..1ae03cf
--- /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<ExtensionInjector> injectors = Collections.emptyList();
+
+    private ExtensionAccessor extensionAccessor;
+
+    public AdaptiveExtensionInjector() {
+    }
+
+    @Override
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
+
+    @Override
+    public void initialize() throws IllegalStateException {
+        ExtensionLoader<ExtensionInjector> loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
+        List<ExtensionInjector> list = new ArrayList<ExtensionInjector>();
+        for (String name : loader.getSupportedExtensions()) {
+            list.add(loader.getExtension(name));
+        }
+        injectors = Collections.unmodifiableList(list);
+    }
+
+    @Override
+    public <T> T getInstance(Class<T> 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 46cbe19..d45cc7b 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> T getExtension(Class<T> type, String name) {
+    public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
+        this.extensionAccessor = extensionAccessor;
+    }
+
+    @Override
+    public <T> T getInstance(Class<T> type, String name) {
         if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
-            ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
+            ExtensionLoader<T> 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 539ffe9..3784069 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 4a38446..e7b509c 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<String, String> getExtraAttributes(Map<String, String> params) {
         Map<String, String> 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 52d5605..3ce6556 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 1560c64..fc644e5 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 b5d7c41..2ff75cf 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/FrameworkStatusReporter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReportService.java
similarity index 62%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReporter.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/status/reporter/FrameworkStatusReportService.java
index d122f91..2dacee5 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/FrameworkStatusReportService.java
@@ -16,48 +16,56 @@
  */
 package org.apache.dubbo.common.status.reporter;
 
-import org.apache.dubbo.common.extension.ExtensionLoader;
-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";
+/**
+ *
+ */
+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";
 
-    void report(String type, Object obj);
+    private ApplicationModel applicationModel;
+    private Set<FrameworkStatusReporter> reporters;
+    private Gson gson = new Gson();
+
+    @Override
+    public void setApplicationModel(ApplicationModel applicationModel) {
+        this.applicationModel = applicationModel;
+        reporters = applicationModel.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances();
+    }
 
-    static void reportRegistrationStatus(Object obj) {
+    public void reportRegistrationStatus(Object obj) {
         doReport(REGISTRATION_STATUS, obj);
     }
 
-    static void reportConsumptionStatus(Object obj) {
+    public void reportConsumptionStatus(Object obj) {
         doReport(ADDRESS_CONSUMPTION_STATUS, obj);
     }
 
-    static void reportMigrationStepStatus(Object obj) {
+    public void reportMigrationStepStatus(Object obj) {
         doReport(MIGRATION_STEP_STATUS, obj);
     }
 
-    static boolean hasReporter() {
-        return ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensions().size() > 0;
+    public boolean hasReporter() {
+        return reporters.size() > 0;
     }
 
-    static void doReport(String type, Object obj) {
+    private void doReport(String type, Object obj) {
         // TODO, report asynchronously
         try {
-            Set<FrameworkStatusReporter> reporters = ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances();
             if (CollectionUtils.isNotEmpty(reporters)) {
                 FrameworkStatusReporter reporter = reporters.iterator().next();
                 reporter.report(type, obj);
@@ -67,18 +75,18 @@ public interface FrameworkStatusReporter {
         }
     }
 
-    static String createRegistrationReport(String status) {
+    public String createRegistrationReport(String status) {
         return "{\"application\":\"" +
-                ApplicationModel.getName() +
-                "\",\"status\":\"" +
-                status +
-                "\"}";
+            applicationModel.getApplicationName() +
+            "\",\"status\":\"" +
+            status +
+            "\"}";
     }
 
-    static String createConsumptionReport(String interfaceName, String version, String group, String status) {
+    public String createConsumptionReport(String interfaceName, String version, String group, String status) {
         HashMap<String, String> migrationStatus = new HashMap<>();
         migrationStatus.put("type", "consumption");
-        migrationStatus.put("application", ApplicationModel.getName());
+        migrationStatus.put("application", applicationModel.getApplicationName());
         migrationStatus.put("service", interfaceName);
         migrationStatus.put("version", version);
         migrationStatus.put("group", group);
@@ -86,10 +94,10 @@ public interface FrameworkStatusReporter {
         return gson.toJson(migrationStatus);
     }
 
-    static String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) {
+    public String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) {
         HashMap<String, String> migrationStatus = new HashMap<>();
         migrationStatus.put("type", "migrationStepStatus");
-        migrationStatus.put("application", ApplicationModel.getName());
+        migrationStatus.put("application", applicationModel.getApplicationName());
         migrationStatus.put("service", interfaceName);
         migrationStatus.put("version", version);
         migrationStatus.put("group", group);
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 d122f91..293bb49 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<FrameworkStatusReporter> 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<String, String> 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<String, String> 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 8a6d475..59d7414 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 312cd69..b1ff4a8 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 ae437ee..5c93b23 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<ExecutorService> executorServiceRing = new Ring<ExecutorService>();
 
     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<Integer> threadNum = getConfigManager().getProviders()
+        List<Integer> 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<Integer> threadNum = getConfigManager().getConsumers()
+        List<Integer> 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 b209f48..dabd581 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 d0eccff..b929988 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;
@@ -97,6 +99,16 @@ public class DubboServiceAddressURL extends ServiceAddressURL {
     }
 
     @Override
+    public ScopeModel getScopeModel() {
+        return consumerURL.getScopeModel();
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return consumerURL.getServiceModel();
+    }
+
+    @Override
     public int hashCode() {
         final int prime = 31;
         return prime * super.hashCode() + (overrideURL == null ? 0 : overrideURL.hashCode());
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 4771297..5fcd263 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<String, Object> 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<String, Object> attributes) {
-        super(urlAddress, urlParam);
-        this.attributes = (attributes != null ? attributes : new HashMap<>());
+        super(urlAddress, urlParam, attributes);
     }
 
 
@@ -99,21 +97,10 @@ public class ServiceConfigURL extends URL {
     }
 
     @Override
-    public Map<String, Object> getAttributes() {
-        return attributes;
-    }
-
-    @Override
-    public Object getAttribute(String key) {
-        return attributes.get(key);
-    }
-
-    @Override
     public URL addAttributes(Map<String, Object> attributes) {
         Map<String, Object> 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<String, Object> newAttributes = new HashMap<>(attributes);
         newAttributes.put(key, obj);
-
         return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes);
     }
 
@@ -129,16 +115,10 @@ public class ServiceConfigURL extends URL {
     public URL removeAttribute(String key) {
         Map<String, Object> 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) {
             return string;
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 15df9aa..49008f1 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<String> keys, List<ParamValue> 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 dbeeff9..d409806 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 249fd3e..994444b 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.
+     * <p>
+     * <b>NOTE:</b> the model maybe changed during config processing,
+     * the extension spi instance needs to be reinitialized after changing the model!
+     */
+    protected ScopeModel scopeModel;
+
+    public 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.
+     * <p>
+     * For example:
+     * <pre>
+     * this.protocol = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+     * </pre>
+     */
+    protected void initExtensions() {
+    }
+
+    protected <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+        if (scopeModel == null) {
+            throw new IllegalStateException("owner module is not initialized");
+        }
+        return scopeModel.getExtensionLoader(type);
+    }
+
     @Parameter(excluded = true, attribute = true)
     public String getId() {
         return id;
@@ -443,7 +502,7 @@ public abstract class AbstractConfig implements Serializable {
             // check and init before do refresh
             preProcessRefresh();
 
-            Environment environment = ApplicationModel.getEnvironment();
+            Environment environment = getApplicationModel().getApplicationEnvironment();
             List<Map<String, String>> 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 cd9fdda..6acdfa7 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<MethodConfig> 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<MethodConfig> 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<RegistryConfig> registryConfigs = ApplicationModel.getConfigManager().getDefaultRegistries();
+                List<RegistryConfig> registryConfigs = getConfigManager().getDefaultRegistries();
                 registryConfigs = new ArrayList<>(registryConfigs);
                 setRegistries(registryConfigs);
             }
@@ -397,7 +431,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             List<RegistryConfig> tmpRegistries = new ArrayList<>();
             Arrays.stream(ids).forEach(id -> {
                 if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
-                    Optional<RegistryConfig> globalRegistry = ApplicationModel.getConfigManager().getRegistry(id);
+                    Optional<RegistryConfig> 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<ConfigCenterConfig> configCenterConfigs = ApplicationModel.getConfigManager().getConfigCenters();
+        Collection<ConfigCenterConfig> 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<MetadataReportConfig> metadataReportConfigs = ApplicationModel.getConfigManager().getMetadataConfigs();
+        Collection<MetadataReportConfig> 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 2c43206..b234d98 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 4521c6b..d990ddb 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.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.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
+import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_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<InfraAdapter> adapters = ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
+        Set<InfraAdapter> adapters = this.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
         if (CollectionUtils.isNotEmpty(adapters)) {
             Map<String, String> inputParameters = new HashMap<>();
             inputParameters.put(APPLICATION_KEY, getName());
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index 412122e..59ff045 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 239d11c..65f560e 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<String, String> map = new HashMap<String, String>();
-        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 2210d6d..2eb2870 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 88e9b2a..525ccbc 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<T> extends AbstractReferenceConfig {
     protected void preProcessRefresh() {
         super.preProcessRefresh();
         if (consumer == null) {
-            consumer = ApplicationModel.getConfigManager()
+            consumer = getConfigManager()
                     .getDefaultConsumer()
                     .orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized"));
         }
@@ -201,6 +201,14 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
     }
 
     @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 9ed3df1..f007b54 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -327,7 +327,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setTransporter(String transporter) {
-        /*if(transporter != null && transporter.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(transporter)){
+        /*if(transporter != null && transporter.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(transporter)){
             throw new IllegalStateException("No such transporter type : " + transporter);
         }*/
         this.transporter = transporter;
@@ -338,7 +338,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setServer(String server) {
-        /*if(server != null && server.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(server)){
+        /*if(server != null && server.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(server)){
             throw new IllegalStateException("No such server type : " + server);
         }*/
         this.server = server;
@@ -349,7 +349,7 @@ public class RegistryConfig extends AbstractConfig {
     }
 
     public void setClient(String client) {
-        /*if(client != null && client.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(client)){
+        /*if(client != null && client.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(client)){
             throw new IllegalStateException("No such client type : " + client);
         }*/
         this.client = client;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
index 4d2fbfc..6d61914 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<T> 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<ProviderConfig> convertProtocolToProvider(List<ProtocolConfig> protocols) {
         if (CollectionUtils.isEmpty(protocols)) {
@@ -199,7 +207,7 @@ public abstract class ServiceConfigBase<T> 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<T> 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<T> extends AbstractServiceConfig {
     protected void convertProtocolIdsToProtocols() {
         if (StringUtils.isEmpty(protocolIds)) {
             if (CollectionUtils.isEmpty(protocols)) {
-                List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
+                List<ProtocolConfig> protocolConfigs = getConfigManager().getDefaultProtocols();
                 if (protocolConfigs.isEmpty()) {
                     throw new IllegalStateException("The default protocol has not been initialized.");
                 }
@@ -266,7 +274,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
             Set<String> idsSet = new LinkedHashSet<>(Arrays.asList(idsArray));
             List<ProtocolConfig> tmpProtocols = new ArrayList<>();
             for (String id : idsSet) {
-                Optional<ProtocolConfig> globalProtocol = ApplicationModel.getConfigManager().getProtocol(id);
+                Optional<ProtocolConfig> globalProtocol = getConfigManager().getProtocol(id);
                 if (globalProtocol.isPresent()) {
                     tmpProtocols.add(globalProtocol.get());
                 } else {
@@ -336,7 +344,7 @@ public abstract class ServiceConfigBase<T> 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 5d7584c..4cd79de 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 8b0f488..1e4b50b 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 9e0521b..cd814ea 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;
  * <p>
  */
 
-public class ApplicationModel {
+public class ApplicationModel extends ScopeModel {
     protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
     public static final String NAME = "application";
+    private static volatile ApplicationModel defaultInstance;
 
-    private static AtomicBoolean INIT_FLAG = new AtomicBoolean(false);
-    private static Environment environment;
-    private static ConfigManager configManager;
-    private static ServiceRepository serviceRepository;
+    private volatile List<ModuleModel> 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<ApplicationInitListener> 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<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
             Set<String> 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<ConsumerModel> allConsumerModels() {
-        return getServiceRepository().getReferredServices();
+        return defaultModel().getApplicationServiceRepository().getReferredServices();
+    }
+
+    public Collection<ConsumerModel> allApplicationConsumerModels() {
+        // TODO: aggregate from sub modules
+        return defaultModel().getApplicationServiceRepository().getReferredServices();
     }
 
+
+    @Deprecated
     public static Collection<ProviderModel> allProviderModels() {
-        return getServiceRepository().getExportedServices();
+        return defaultModel().getApplicationServiceRepository().getExportedServices();
+    }
+
+    public Collection<ProviderModel> 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<FrameworkExt> LOADER = ExtensionLoader.getExtensionLoader(FrameworkExt.class);
-
-    public static void initFrameworkExts() {
-        Set<FrameworkExt> exts = ExtensionLoader.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
+    public void initFrameworkExts() {
+        Set<FrameworkExt> 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 ExecutorRepository getApplicationExecutorRepository() {
+        return this.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+    }
+
+    @Deprecated
     public static ApplicationConfig getApplicationConfig() {
-        return getConfigManager().getApplicationOrElseThrow();
+        return defaultModel().getCurrentConfig();
     }
 
-    public static String getName() {
-        return getApplicationConfig().getName();
+    public ApplicationConfig getCurrentConfig() {
+        return getApplicationConfigManager().getApplicationOrElseThrow();
     }
 
     @Deprecated
-    //It will be remove at next version
-    private static String application;
+    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();
     }
 
-    // only for unit test
-    public static void reset() {
-        if (serviceRepository!=null){
-            serviceRepository.destroy();
-            serviceRepository = null;
+    public void addModule(ModuleModel model) {
+        if (!this.moduleModels.contains(model)) {
+            this.moduleModels.add(model);
         }
-        if (configManager != null) {
-            configManager.destroy();
-            configManager = null;
+    }
+
+    public void removeModule(ModuleModel model) {
+        this.moduleModels.remove(model);
+    }
+
+    public List<ModuleModel> getModuleModels() {
+        return moduleModels;
+    }
+
+    public synchronized ModuleModel getDefaultModule() {
+        if (moduleModels.isEmpty()) {
+            this.addModule(new ModuleModel(this));
         }
-        if (environment != null) {
-            environment.destroy();
-            environment = null;
+        return moduleModels.get(0);
+    }
+
+    // only for unit test
+    @Deprecated
+    public static void reset() {
+        if (defaultInstance != null) {
+            defaultInstance.destroy();
+            defaultInstance = 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 06a5725..ca27eb7 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 81b1a88..444b85a 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<String> apps = new TreeSet<>();
 
-    private Object proxyObject;
-
     private final Map<String, AsyncMethodInfo> methodConfigs;
+    private Map<Method, ConsumerMethodModel> 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<String, AsyncMethodInfo> 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<String, AsyncMethodInfo> methodConfigs) {
 
-    public void setProxyObject(Object proxyObject) {
-        this.proxyObject = proxyObject;
-    }
+        super(proxyObject, serviceKey, serviceModel, referenceConfig, metadata);
+        Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
 
-    /**
-     * Return all method models for the current service
-     *
-     * @return method model list
-     */
-    public Set<MethodDescriptor> getAllMethods() {
-        return serviceModel.getAllMethods();
+        this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
     }
 
-    public Class<?> getServiceInterfaceClass() {
-        return serviceModel.getServiceInterfaceClass();
-    }
+    public ConsumerModel(String serviceKey,
+                         Object proxyObject,
+                         ServiceDescriptor serviceModel,
+                         ReferenceConfigBase<?> referenceConfig,
+                         ModuleModel moduleModel,
+                         ServiceMetadata metadata,
+                         Map<String, AsyncMethodInfo> methodConfigs) {
+
+        super(proxyObject, serviceKey, serviceModel, referenceConfig, moduleModel, metadata);
+        Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
 
-    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<String> getApps() {
         return apps;
     }
@@ -117,41 +97,17 @@ public class ConsumerModel {
         return methodConfigs.get(methodName);
     }
 
-    /* *************** Start, metadata compatible **************** */
-
-    private ServiceMetadata serviceMetadata;
-    private Map<Method, ConsumerMethodModel> methodModels = new HashMap<>();
-
-    public ConsumerModel(String serviceKey,
-                         Object proxyObject,
-                         ServiceDescriptor serviceModel,
-                         ReferenceConfigBase<?> referenceConfig,
-                         ServiceMetadata metadata,
-                         Map<String, AsyncMethodInfo> 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<ConsumerMethodModel> 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 0000000..7b3740f
--- /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<ApplicationModel> 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<ApplicationModel> getApplicationModels() {
+        return applicationModels;
+    }
+
+    @Override
+    public String toString() {
+        return "FrameworkModel";
+    }
+}
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/ModuleModel.java
similarity index 53%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
index 06a5725..e9757f3 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/ModuleModel.java
@@ -16,11 +16,29 @@
  */
 package org.apache.dubbo.rpc.model;
 
-import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.extension.ExtensionDirector;
+import org.apache.dubbo.common.extension.ExtensionScope;
 
-@SPI
-public interface BuiltinServiceDetector {
+/**
+ * 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();
+    }
 
-    Class<?> getService();
+    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 a640204..235f7a5 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<RegisterStatedURL> urls;
+    private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
 
     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 Class<?> getServiceInterfaceClass() {
-        return serviceModel.getServiceInterfaceClass();
-    }
+    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.");
+        }
 
-    public Object getServiceInstance() {
-        return serviceInstance;
+        initMethod(serviceModel.getServiceInterfaceClass());
+        this.urls = new ArrayList<>(1);
     }
 
-    public Set<MethodDescriptor> getAllMethods() {
-        return serviceModel.getAllMethods();
-    }
+    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 ServiceDescriptor getServiceModel() {
-        return serviceModel;
+        initMethod(serviceModel.getServiceInterfaceClass());
+        this.urls = new ArrayList<>(1);
     }
 
-    public ServiceConfigBase getServiceConfig() {
-        return serviceConfig;
+    public Object getServiceInstance() {
+        return getProxyObject();
     }
 
     public List<RegisterStatedURL> getStatedUrl() {
@@ -125,35 +125,6 @@ public class ProviderModel {
         }
     }
 
-    /* *************** Start, metadata compatible **************** */
-
-    private ServiceMetadata serviceMetadata;
-    private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
-
-    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<ProviderMethodModel> getAllMethodModels() {
         List<ProviderMethodModel> result = new ArrayList<ProviderMethodModel>();
         for (List<ProviderMethodModel> 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 0000000..d774bb3
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.rpc.model;
+
+import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
+import org.apache.dubbo.common.extension.ExtensionDirector;
+
+import java.util.Set;
+
+public abstract class ScopeModel implements ExtensionAccessor {
+
+    private final ScopeModel parent;
+
+    private final ExtensionDirector extensionDirector;
+
+    private final ScopeBeanFactory beanFactory;
+
+    public ScopeModel(ScopeModel parent, ExtensionDirector extensionDirector) {
+        this.parent = parent;
+        this.extensionDirector = extensionDirector;
+        this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
+        this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector);
+    }
+
+    public ExtensionDirector getExtensionDirector() {
+        return extensionDirector;
+    }
+
+    public ScopeBeanFactory getBeanFactory() {
+        return beanFactory;
+    }
+
+    public ScopeModel getParent() {
+        return parent;
+    }
+
+    protected void postProcessAfterCreated() {
+        Set<ScopeModelPostProcessor> scopeModelPostProcessors = getExtensionLoader(ScopeModelPostProcessor.class)
+            .getSupportedExtensionInstances();
+        for (ScopeModelPostProcessor processor : scopeModelPostProcessors) {
+            processor.postProcessScopeModel(this);
+        }
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java
similarity index 61%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/BuiltinServiceDetector.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelAccessor.java
index 06a5725..9e9291e 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/ScopeModelAccessor.java
@@ -16,11 +16,23 @@
  */
 package org.apache.dubbo.rpc.model;
 
-import org.apache.dubbo.common.extension.SPI;
+/**
+ * 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());
+    }
 
-@SPI
-public interface BuiltinServiceDetector {
+    default ApplicationModel getApplicationModel() {
+        return ScopeModelUtil.getApplicationModel(getScopeModel());
+    }
 
-    Class<?> getService();
+    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 0000000..6b60567
--- /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 0000000..49e3012
--- /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/ApplicationInitListener.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
similarity index 70%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationInitListener.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
index 8b0f488..5a78a3f 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/ScopeModelPostProcessor.java
@@ -16,12 +16,19 @@
  */
 package org.apache.dubbo.rpc.model;
 
+import org.apache.dubbo.common.extension.ExtensionScope;
 import org.apache.dubbo.common.extension.SPI;
 
-@SPI
-public interface ApplicationInitListener {
+/**
+ * A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel)
+ */
+@SPI(scope = ExtensionScope.FRAMEWORK)
+public interface ScopeModelPostProcessor {
+
     /**
-     * init the application
+     * Post-process after a scope model is created.
+     * @param scopeModel
      */
-    void init();
+    void postProcessScopeModel(ScopeModel scopeModel);
+
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelUtil.java
new file mode 100644
index 0000000..a23a84d
--- /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 <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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 0000000..35bf5e3
--- /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<MethodDescriptor> 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 7567dcd..c136593 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<String, Set<URL>> providerUrlsWithoutGroup = new ConcurrentHashMap<>();
+    private ExtensionAccessor extensionAccessor;
 
     public ServiceRepository() {
+    }
+
+    @Override
+    public void initialize() throws IllegalStateException {
         Set<BuiltinServiceDetector> builtinServices
-            = ExtensionLoader.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
+            = extensionAccessor.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
         if (CollectionUtils.isNotEmpty(builtinServices)) {
             for (BuiltinServiceDetector service : builtinServices) {
                 registerService(service.getService());
@@ -104,13 +109,16 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
                                  ServiceDescriptor serviceDescriptor,
                                  ReferenceConfigBase<?> rc,
                                  Object proxy,
-                                 ServiceMetadata serviceMetadata,
-                                 Map<String, AsyncMethodInfo> 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 094382f..0000000
--- 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 0000000..a6ef1e3
--- /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 1c8a549..d10ad6a 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 34f8884..2a93ca7 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<String, String> 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 9e8991d..7af1663 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactoryTest.java
@@ -16,8 +16,9 @@
  */
 package org.apache.dubbo.common.config.configcenter.file;
 
-import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.config.ConfigurationUtils;
 
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -31,6 +32,6 @@ public class FileSystemDynamicConfigurationFactoryTest {
 
     @Test
     public void testGetFactory() {
-        assertEquals(FileSystemDynamicConfigurationFactory.class, DynamicConfigurationFactory.getDynamicConfigurationFactory("file").getClass());
+        assertEquals(FileSystemDynamicConfigurationFactory.class, ConfigurationUtils.getDynamicConfigurationFactory(ApplicationModel.defaultModel(), "file").getClass());
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
new file mode 100644
index 0000000..f2d4030
--- /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<ApplicationModel> applicationsOfFw1 = frameworkModel1.getApplicationModels();
+        Assertions.assertEquals(2, applicationsOfFw1.size());
+        Assertions.assertTrue(applicationsOfFw1.contains(applicationModel11));
+        Assertions.assertTrue(applicationsOfFw1.contains(applicationModel12));
+        Assertions.assertFalse(applicationsOfFw1.contains(applicationModel21));
+
+        Collection<ModuleModel> 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 57736b8..1e474eb 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionLoaderTest.java
@@ -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 <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
         ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(false),
                 new DubboInternalLoadingStrategyTest(false));
-        ExtensionLoader<DuplicatedWithoutOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedWithoutOverriddenExt.class);
+        ExtensionLoader<DuplicatedWithoutOverriddenExt> extensionLoader = getExtensionLoader(DuplicatedWithoutOverriddenExt.class);
         try {
             extensionLoader.getExtension("duplicated");
             fail();
@@ -577,7 +577,7 @@ public class ExtensionLoaderTest {
         List<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
         ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(true),
                 new DubboInternalLoadingStrategyTest(true));
-        ExtensionLoader<DuplicatedOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedOverriddenExt.class);
+        ExtensionLoader<DuplicatedOverriddenExt> extensionLoader = getExtensionLoader(DuplicatedOverriddenExt.class);
         DuplicatedOverriddenExt duplicatedOverriddenExt = extensionLoader.getExtension("duplicated");
         assertEquals("DuplicatedOverriddenExt1", duplicatedOverriddenExt.echo());
         //recover the loading strategies
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java
index 4143c9d..e885271 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppProvider.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
 
-import java.util.function.Consumer;
+@SPI(scope = ExtensionScope.APPLICATION)
+public interface FooAppProvider {
 
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
+    @Adaptive
+    void process(URL url);
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java
index 4143c9d..d475092 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooAppService.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
-
-import java.util.function.Consumer;
-
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
 
+@SPI(scope = ExtensionScope.APPLICATION)
+public interface FooAppService {
+    @Adaptive
+    void process(URL url);
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java
index 4143c9d..194c818 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkProvider.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
 
-import java.util.function.Consumer;
+@SPI(scope = ExtensionScope.FRAMEWORK)
+public interface FooFrameworkProvider {
 
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
+    @Adaptive
+    void process(URL url);
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java
index 4143c9d..2ff1403 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooFrameworkService.java
@@ -14,19 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
-
-import java.util.function.Consumer;
-
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
 
+@SPI(scope = ExtensionScope.FRAMEWORK)
+public interface FooFrameworkService {
+    @Adaptive
+    void process(URL url);
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java
index 4143c9d..9d4b81e 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleProvider.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
 
-import java.util.function.Consumer;
+@SPI(scope = ExtensionScope.MODULE)
+public interface FooModuleProvider {
 
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
+    @Adaptive
+    void process(URL url);
 
 }
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java
similarity index 74%
copy from dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java
index 4143c9d..87ce080 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/ConnectionManager.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/FooModuleService.java
@@ -14,19 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.remoting.api;
+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;
-import org.apache.dubbo.remoting.RemotingException;
 
-import java.util.function.Consumer;
+@SPI(scope = ExtensionScope.MODULE)
+public interface FooModuleService {
 
-@SPI
-public interface ConnectionManager {
-
-    Connection connect(URL url) throws RemotingException;
-
-    void forEachConnection(Consumer<Connection> connectionConsumer);
+    @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 0000000..e3171a4
--- /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-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java
similarity index 76%
copy from dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java
index f9602b4..cf60246 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestAppProvider.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.extension.director.impl;
 
-import com.alibaba.dubbo.common.extension.ExtensionFactory;
-
-public class MyExtensionFactory implements ExtensionFactory {
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.director.FooAppProvider;
 
+public class TestAppProvider implements FooAppProvider {
     @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        return null;
+    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 0000000..ed5aec4
--- /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-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java
similarity index 75%
copy from dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java
index f9602b4..25dcb66 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestFrameworkProvider.java
@@ -14,14 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.extension.director.impl;
 
-import com.alibaba.dubbo.common.extension.ExtensionFactory;
-
-public class MyExtensionFactory implements ExtensionFactory {
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.director.FooFrameworkProvider;
 
+public class TestFrameworkProvider implements FooFrameworkProvider {
     @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        return null;
+    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 0000000..45b71b1
--- /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-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java
similarity index 75%
copy from dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java
index f9602b4..604c291 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/common/extension/MyExtensionFactory.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/director/impl/TestModuleProvider.java
@@ -14,14 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.extension;
+package org.apache.dubbo.common.extension.director.impl;
 
-import com.alibaba.dubbo.common.extension.ExtensionFactory;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.director.FooModuleProvider;
 
-public class MyExtensionFactory implements ExtensionFactory {
+public class TestModuleProvider implements FooModuleProvider {
+
+    public void process(URL url) {
 
-    @Override
-    public <T> T getExtension(Class<T> type, String name) {
-        return null;
     }
+
 }
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 0000000..d7c0ad7
--- /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 b15f9c5..a80fffd 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 0000000..667a52d
--- /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 0000000..37fe7c3
--- /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 0000000..a1f9f61
--- /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 0000000..f695488
--- /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 0000000..cfa3cd9
--- /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 0000000..9d3ef32
--- /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 bc0f0b2..2a2f35f 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 f53e159..d8ae4e3 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;
 
@@ -75,6 +77,16 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation {
     }
 
     @Override
+    default void setServiceModel(ServiceModel serviceModel) {
+
+    }
+
+    @Override
+    default ServiceModel getServiceModel() {
+        return null;
+    }
+
+    @Override
     default Object put(Object key, Object value) {
         return null;
     }
@@ -158,6 +170,16 @@ public interface Invocation extends org.apache.dubbo.rpc.Invocation {
         }
 
         @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 2b7a5c8..b126d6a 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 f9602b4..d8bc822 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> T getExtension(Class<T> 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 a2cb52e..532f6bd 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;
@@ -132,6 +133,16 @@ public class MockInvocation implements Invocation {
     }
 
     @Override
+    public void setServiceModel(ServiceModel serviceModel) {
+
+    }
+
+    @Override
+    public ServiceModel getServiceModel() {
+        return null;
+    }
+
+    @Override
     public Map<Object, Object> getAttributes() {
         return null;
     }
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index ad4220b..b8ea09d 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -52,6 +52,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-rpc-api</artifactId>
+            <version>${project.parent.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-rpc-injvm</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
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 6380a24..9e03a23 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 aa5bef5..97e52f6 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<T> extends ReferenceConfigBase<T> {
      * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
      * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
      */
-    private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+    private Protocol protocolSPI;
 
     /**
      * A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
      * its default implementation
      */
-    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    private ProxyFactory proxyFactory;
+
+    private ConsumerModel consumerModel;
 
     /**
      * The interface proxy reference
@@ -149,6 +150,14 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         super(reference);
     }
 
+    @Override
+    protected void initExtensions() {
+        super.initExtensions();
+
+        protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+        proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    }
+
     /**
      * Get a string presenting the service names that the Dubbo interface subscribed.
      * If it is a multiple-values, the content will be a comma-delimited String.
@@ -247,15 +256,12 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         Map<String, String> 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<T> extends ReferenceConfigBase<T> {
         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<T> extends ReferenceConfigBase<T> {
 
         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<T> extends ReferenceConfigBase<T> {
      */
     private void createInvokerForLocal(Map<String, String> referenceParameters) {
         URL url = new ServiceConfigURL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(referenceParameters);
-        invoker = REF_PROTOCOL.refer(interfaceClass, url);
+        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<T> extends ReferenceConfigBase<T> {
                 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<T> extends ReferenceConfigBase<T> {
                 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<T> extends ReferenceConfigBase<T> {
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void createInvokerForRemote() {
         if (urls.size() == 1) {
-            invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
+            invoker = protocolSPI.refer(interfaceClass, urls.get(0));
         } else {
             List<Invoker<?>> invokers = new ArrayList<>();
             URL registryUrl = null;
             for (URL url : urls) {
                 // For multi-registry scenarios, it is not checked whether each referInvoker is available.
                 // Because this invoker may become available later.
-                invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
+                invokers.add(protocolSPI.refer(interfaceClass, url));
 
                 if (UrlUtils.isRegistry(url)) {
                     // use last registry url
@@ -515,7 +528,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         completeCompoundConfigs();
 
         // init some null configuration.
-        List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
+        List<ConfigInitializer> configInitializers = this.getExtensionLoader(ConfigInitializer.class)
             .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
         configInitializers.forEach(e -> e.initReferConfig(this));
 
@@ -591,7 +604,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
     }
 
     private void postProcessConfig() {
-        List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
+        List<ConfigPostProcessor> configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class)
             .getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
         configPostProcessors.forEach(component -> component.postProcessReferConfig(this));
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index f527cb1..c108502 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<T> extends ServiceConfigBase<T> {
      */
     private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
 
-    private static final Protocol PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+    private Protocol protocolSPI;
 
     /**
      * A {@link ProxyFactory} implementation that will generate a exported service proxy,the JavassistProxyFactory is its
      * default implementation
      */
-    private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+    private ProxyFactory proxyFactory;
+
+    private ProviderModel providerModel;
 
     /**
      * Whether the provider has been exported
@@ -144,6 +147,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
 
     private List<ServiceListener> serviceListeners = new ArrayList<>();
+    private WritableMetadataService localMetadataService;
 
     public ServiceConfig() {
     }
@@ -152,6 +156,13 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         super(service);
     }
 
+    @Override
+    protected void initExtensions() {
+        super.initExtensions();
+        protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+        proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+        localMetadataService = this.getScopeModel().getDefaultExtension(WritableMetadataService.class);
+    }
 
     @Override
     @Parameter(excluded = true, attribute = false)
@@ -197,7 +208,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             this.bootstrap.service(this);
 
             // load ServiceListeners from extension
-            ExtensionLoader<ServiceListener> extensionLoader = ExtensionLoader.getExtensionLoader(ServiceListener.class);
+            ExtensionLoader<ServiceListener> extensionLoader = this.getExtensionLoader(ServiceListener.class);
             this.serviceListeners.addAll(extensionLoader.getSupportedExtensionInstances());
         }
 
@@ -252,7 +263,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         List<URL> 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<T> extends ServiceConfigBase<T> {
         checkProtocol();
 
         // init some null configuration.
-        List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
-                .getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
+        List<ConfigInitializer> 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<T> extends ServiceConfigBase<T> {
 
     @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<URL> registryURLs = ConfigValidationUtils.loadRegistries(this, true);
 
@@ -382,7 +394,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         }
     }
 
-
     private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
         Map<String, String> map = buildAttributes(protocolConfig);
 
@@ -535,14 +546,16 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
         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<T> extends ServiceConfigBase<T> {
         } else {
 
             if (MetadataService.class.getName().equals(url.getServiceInterface())) {
-                MetadataUtils.saveMetadataURL(url);
+                localMetadataService.setMetadataServiceURL(url);
             }
 
             if (logger.isInfoEnabled()) {
@@ -620,11 +633,11 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
     @SuppressWarnings({"unchecked", "rawtypes"})
     private void doExportUrl(URL url, boolean withMetaData) {
-        Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
+        Invoker<?> invoker = proxyFactory.getInvoker(ref, (Class) interfaceClass, url);
         if (withMetaData) {
             invoker = new DelegateProviderMetaDataInvoker(invoker, this);
         }
-        Exporter<?> exporter = PROTOCOL.export(invoker);
+        Exporter<?> exporter = protocolSPI.export(invoker);
         exporters.add(exporter);
     }
 
@@ -754,7 +767,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             if (provider != null && (portToBind == null || portToBind == 0)) {
                 portToBind = provider.getPort();
             }
-            final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
+            final int defaultPort = this.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
             if (portToBind == null || portToBind == 0) {
                 portToBind = defaultPort;
             }
@@ -819,8 +832,8 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     }
 
     private void postProcessConfig() {
-        List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
-                .getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
+        List<ConfigPostProcessor> 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 19d924d..47b8029 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<CompletableFuture<?>> 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 <T> ExtensionLoader<T> getExtensionLoader(Class<T> 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 <S> DubboBootstrap service(Consumer<ServiceBuilder<S>> consumerBuilder) {
-        return service(DEFAULT_SERVICE_ID, consumerBuilder);
+        getCurrentModule().service(consumerBuilder);
+        return this;
     }
 
     public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
-        ServiceBuilder builder = createServiceBuilder(id);
-        consumerBuilder.accept(builder);
-        return service(builder.build());
+        getCurrentModule().service(id, consumerBuilder);
+        return this;
     }
 
     public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
-        serviceConfig.setBootstrap(this);
-        configManager.addService(serviceConfig);
+        getCurrentModule().service(serviceConfig);
         return this;
     }
 
     public DubboBootstrap services(List<ServiceConfig> serviceConfigs) {
-        if (CollectionUtils.isEmpty(serviceConfigs)) {
-            return this;
-        }
-        serviceConfigs.forEach(configManager::addService);
+        getCurrentModule().services(serviceConfigs);
         return this;
     }
 
     // {@link Reference} correlative methods
     public <S> DubboBootstrap reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
-        return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+        getCurrentModule().reference(consumerBuilder);
+        return this;
     }
 
     public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
-        ReferenceBuilder builder = createReferenceBuilder(id);
-        consumerBuilder.accept(builder);
-        return reference(builder.build());
+        getCurrentModule().reference(id, consumerBuilder);
+        return this;
     }
 
     public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
-        referenceConfig.setBootstrap(this);
-        configManager.addReference(referenceConfig);
+        getCurrentModule().reference(referenceConfig);
         return this;
     }
 
     public DubboBootstrap references(List<ReferenceConfig> referenceConfigs) {
-        if (CollectionUtils.isEmpty(referenceConfigs)) {
-            return this;
-        }
-
-        referenceConfigs.forEach(configManager::addReference);
+        getCurrentModule().references(referenceConfigs);
         return this;
     }
 
     // {@link ProviderConfig} correlative methods
     public DubboBootstrap provider(Consumer<ProviderBuilder> builderConsumer) {
-        return provider(DEFAULT_PROVIDER_ID, builderConsumer);
+        getCurrentModule().provider(builderConsumer);
+        return this;
     }
 
     public DubboBootstrap provider(String id, Consumer<ProviderBuilder> builderConsumer) {
-        ProviderBuilder builder = createProviderBuilder(id);
-        builderConsumer.accept(builder);
-        return provider(builder.build());
+        getCurrentModule().provider(id, builderConsumer);
+        return this;
     }
 
     public DubboBootstrap provider(ProviderConfig providerConfig) {
@@ -471,80 +519,75 @@ public final class DubboBootstrap {
     }
 
     public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
-        if (CollectionUtils.isEmpty(providerConfigs)) {
-            return this;
-        }
-
-        providerConfigs.forEach(configManager::addProvider);
+        getCurrentModule().providers(providerConfigs);
         return this;
     }
 
     // {@link ConsumerConfig} correlative methods
     public DubboBootstrap consumer(Consumer<ConsumerBuilder> builderConsumer) {
-        return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+        getCurrentModule().consumer(builderConsumer);
+        return this;
     }
 
     public DubboBootstrap consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
-        ConsumerBuilder builder = createConsumerBuilder(id);
-        builderConsumer.accept(builder);
-        return consumer(builder.build());
+        getCurrentModule().consumer(id, builderConsumer);
+        return this;
     }
 
     public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
-        return consumers(singletonList(consumerConfig));
+        getCurrentModule().consumer(consumerConfig);
+        return this;
     }
 
     public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
-        if (CollectionUtils.isEmpty(consumerConfigs)) {
-            return this;
-        }
-
-        consumerConfigs.forEach(configManager::addConsumer);
+        getCurrentModule().consumers(consumerConfigs);
         return this;
     }
+    // module configs end
 
     // {@link ConfigCenterConfig} correlative methods
     public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
-        return configCenters(singletonList(configCenterConfig));
+        configCenterConfig.setScopeModel(applicationModel);
+        configManager.addConfigCenter(configCenterConfig);
+        return this;
     }
 
     public DubboBootstrap configCenters(List<ConfigCenterConfig> configCenterConfigs) {
         if (CollectionUtils.isEmpty(configCenterConfigs)) {
             return this;
         }
-        configManager.addConfigCenters(configCenterConfigs);
+        for (ConfigCenterConfig configCenterConfig : configCenterConfigs) {
+            this.configCenter(configCenterConfig);
+        }
         return this;
     }
 
     public DubboBootstrap monitor(MonitorConfig monitor) {
+        monitor.setScopeModel(applicationModel);
         configManager.setMonitor(monitor);
         return this;
     }
 
     public DubboBootstrap metrics(MetricsConfig metrics) {
+        metrics.setScopeModel(applicationModel);
         configManager.setMetrics(metrics);
         return this;
     }
 
     public DubboBootstrap module(ModuleConfig module) {
+        //TODO module config?
+        module.setScopeModel(applicationModel);
         configManager.setModule(module);
         return this;
     }
 
     public DubboBootstrap ssl(SslConfig sslConfig) {
+        sslConfig.setScopeModel(applicationModel);
         configManager.setSsl(sslConfig);
         return this;
     }
 
-    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 <T extends AbstractConfig> void checkDefaultAndValidateConfigs(Class<T> configType) {
         try {
             if (shouldAddDefaultConfig(configType)) {
-                T config = configType.newInstance();
+                T config = createConfig(configType);
                 config.refresh();
                 if (!isNeedValidation(config) || config.isValid()) {
                     configManager.addConfig(config);
@@ -721,6 +764,7 @@ public final class DubboBootstrap {
         Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
         if (CollectionUtils.isEmpty(configCenters)) {
             ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
+            configCenterConfig.setScopeModel(applicationModel);
             configCenterConfig.refresh();
             ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
             if (configCenterConfig.isValid()) {
@@ -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<Map<String, String>> configurationMaps = env.getConfigurationMaps();
+            List<Map<String, String>> 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 extends AbstractConfig> T createConfig(Class<T> cls) throws InstantiationException, IllegalAccessException {
+        T config = cls.newInstance();
+        if (config instanceof ProviderConfig || config instanceof ConsumerConfig || config instanceof ReferenceConfigBase
+            || config instanceof ServiceConfigBase) {
+            config.setScopeModel(getCurrentModule().moduleModel);
+        } else {
+            config.setScopeModel(applicationModel);
+        }
+        return config;
+    }
+
     /**
      * Search props and extract config ids of specify type.
      * <pre>
@@ -1080,7 +1137,6 @@ public final class DubboBootstrap {
      */
     private Set<String> getConfigIds(Class<? extends AbstractConfig> 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<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
+        ExtensionLoader<Protocol> 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 <S> Module service(Consumer<ServiceBuilder<S>> consumerBuilder) {
+            return service(DEFAULT_SERVICE_ID, consumerBuilder);
+        }
+
+        public <S> Module service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
+            ServiceBuilder builder = createServiceBuilder(id);
+            consumerBuilder.accept(builder);
+            return service(builder.build());
+        }
+
+        public Module service(ServiceConfig<?> serviceConfig) {
+            serviceConfig.setBootstrap(this.bootstrap);
+            serviceConfig.setScopeModel(moduleModel);
+            configManager.addService(serviceConfig);
+            return this;
+        }
+
+        public Module services(List<ServiceConfig> serviceConfigs) {
+            if (CollectionUtils.isEmpty(serviceConfigs)) {
+                return this;
+            }
+            serviceConfigs.forEach(configManager::addService);
+            return this;
+        }
+
+        // {@link Reference} correlative methods
+        public <S> Module reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
+            return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+        }
+
+        public <S> Module reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
+            ReferenceBuilder builder = createReferenceBuilder(id);
+            consumerBuilder.accept(builder);
+            return reference(builder.build());
+        }
+
+        public Module reference(ReferenceConfig<?> referenceConfig) {
+            referenceConfig.setBootstrap(this.bootstrap);
+            referenceConfig.setScopeModel(moduleModel);
+            configManager.addReference(referenceConfig);
+            return this;
+        }
+
+        public Module references(List<ReferenceConfig> referenceConfigs) {
+            if (CollectionUtils.isEmpty(referenceConfigs)) {
+                return this;
+            }
+
+            referenceConfigs.forEach(configManager::addReference);
+            return this;
+        }
+
+        // {@link ProviderConfig} correlative methods
+        public Module provider(Consumer<ProviderBuilder> builderConsumer) {
+            return provider(DEFAULT_PROVIDER_ID, builderConsumer);
+        }
+
+        public Module provider(String id, Consumer<ProviderBuilder> builderConsumer) {
+            ProviderBuilder builder = createProviderBuilder(id);
+            builderConsumer.accept(builder);
+            return provider(builder.build());
+        }
+
+        public Module provider(ProviderConfig providerConfig) {
+            return providers(singletonList(providerConfig));
+        }
+
+        public Module providers(List<ProviderConfig> providerConfigs) {
+            if (CollectionUtils.isEmpty(providerConfigs)) {
+                return this;
+            }
+            for (ProviderConfig providerConfig : providerConfigs) {
+                providerConfig.setScopeModel(moduleModel);
+                configManager.addProvider(providerConfig);
+            }
+            return this;
+        }
+
+        // {@link ConsumerConfig} correlative methods
+        public Module consumer(Consumer<ConsumerBuilder> builderConsumer) {
+            return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+        }
+
+        public Module consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
+            ConsumerBuilder builder = createConsumerBuilder(id);
+            builderConsumer.accept(builder);
+            return consumer(builder.build());
+        }
+
+        public Module consumer(ConsumerConfig consumerConfig) {
+            return consumers(singletonList(consumerConfig));
+        }
+
+        public Module consumers(List<ConsumerConfig> consumerConfigs) {
+            if (CollectionUtils.isEmpty(consumerConfigs)) {
+                return this;
+            }
+            for (ConsumerConfig consumerConfig : consumerConfigs) {
+                consumerConfig.setScopeModel(moduleModel);
+                configManager.addConsumer(consumerConfig);
+            }
+            return this;
+        }
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/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 f7d1db3..8dbf910 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<MetadataService> 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<MetadataService> 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<ProtocolConfig> defaultProtocols = ApplicationModel.getConfigManager().getDefaultProtocols();
+            List<ProtocolConfig> 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 8693828..07d8ffa 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<URL> 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 47ccae9..fa5476e 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<URL> genCompatibleRegistries(List<URL> registryList, boolean provider) {
+    private static List<URL> genCompatibleRegistries(ApplicationModel applicationModel, List<URL> registryList, boolean provider) {
         List<URL> 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 1f6a773..f95e00f 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<String, ReferenceConfigCache> CACHE_HOLDER = new ConcurrentHashMap<String, ReferenceConfigCache>();
     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<String, Object> 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 9718452..8278220 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<String, String> 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 014d764..427a265 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
+            Collection<ConfigCenterConfig> 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 a4ea9af..313fa71 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<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection<ConsumerConfig> 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<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection<ConsumerConfig> 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<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection<ConsumerConfig> 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<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
+            Collection<ConsumerConfig> 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 9f13ce3..fa64410 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.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.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.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.METHODS_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_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<DemoService> 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<DemoService> 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<ApplicationModel> 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<MetadataReportInstance> 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<DemoService> referenceConfig = new ReferenceConfig<>();
         referenceConfig.setScope(LOCAL_KEY);
 
-        DubboBootstrap.getInstance()
-            .application("application1")
-            .initialize();
-        referenceConfig.setBootstrap(DubboBootstrap.getInstance());
-
         ApplicationConfig applicationConfig = new ApplicationConfig();
         applicationConfig.setName("application1");
         Map<String, String> 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<ApplicationModel> 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<MetadataReportInstance> 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<ApplicationModel> 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<MetadataReportInstance> 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<ApplicationModel> 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<MetadataReportInstance> 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 76e79bd..b895d6d 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<RegistryConfig> registries = ApplicationModel.getConfigManager().getRegistries();
+        Collection<RegistryConfig> 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 18a35bd..c425456 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 0000000..19fe85f
--- /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<DemoService> 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<DemoService> 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 24915d7..9c669c1 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<URL> 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<String, Exporter<?>> 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 fd63b8a..e0dab84 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 fee5470..5e932c6 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 9eb749c..322d6da 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 b7cbf34..00d45f4 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 1396fcb..cfb9df8 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 05378e7..ec806b9 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 77c04fe..95fc792 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 84ddac5..6374cdb 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 ca3e85c..94af84a 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<T> extends ServiceConfig<T> 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<T> extends ServiceConfig<T> 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 61e0f81..f51bb35 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 7952982..0f79d22 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<String, String> 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 27eec78..c580ab2 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<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
 
@@ -47,10 +47,6 @@ public class SpringExtensionFactory implements ExtensionFactory, Lifecycle {
         }
     }
 
-    public static void removeApplicationContext(ApplicationContext context) {
-        CONTEXTS.remove(context);
-    }
-
     public static Set<ApplicationContext> getContexts() {
         return CONTEXTS;
     }
@@ -62,9 +58,9 @@ public class SpringExtensionFactory implements ExtensionFactory, Lifecycle {
 
     @Override
     @SuppressWarnings("unchecked")
-    public <T> T getExtension(Class<T> type, String name) {
+    public <T> T getInstance(Class<T> 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 28323bb..c28db37 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<ApplicationContext> 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 c259a78..cae9260 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 4ac9db2..0000000
--- 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 0000000..c5ef410
--- /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 9a1b3b9..f829284 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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 43be931..2f216c0 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 e15175d..6e25b8f 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+        ConcurrentMap<String, Set<URL>> 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 666e0f1..4c309df 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<ProtocolConfig> 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 ca70f1f..71e98d7 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 869770b..75d6b7a 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<String, ReferenceBean> referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
             Assertions.assertEquals(1, referenceBeanMap.size());
 
-            Collection<ReferenceConfigBase<?>> references = ApplicationModel.getConfigManager().getReferences();
+            Collection<ReferenceConfigBase<?>> 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 fc9e03a..099f8a7 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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 c8edbc3..2cb92ff 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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 4d88db2..b5b1a2d 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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<String, Set<URL>> tmp = ApplicationModel.getServiceRepository().getProviderUrlsWithoutGroup();
+            ConcurrentMap<String, Set<URL>> 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 f93bf06..cd65bb4 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.AfterEach;
 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.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());
... 5946 lines suppressed ...