You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2021/06/01 06:14:52 UTC

[dubbo] branch 3.0 updated: Migrate master bugfix (#7927)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 8bc9257  Migrate master bugfix (#7927)
8bc9257 is described below

commit 8bc9257f4e09b2937e21842b90984dfcaefe97b6
Author: Albumen Kevin <jh...@gmail.com>
AuthorDate: Tue Jun 1 14:14:35 2021 +0800

    Migrate master bugfix (#7927)
---
 CONTRIBUTING.md                                    |  42 +-
 NOTICE                                             |   2 +-
 PULL_REQUEST_TEMPLATE.md                           |   8 +-
 README.md                                          |  66 +--
 SECURITY.md                                        |   6 +-
 dubbo-cluster/pom.xml                              |   6 +
 .../java/org/apache/dubbo/rpc/cluster/Cluster.java |   6 +-
 .../org/apache/dubbo/rpc/cluster/Constants.java    |   6 +
 .../org/apache/dubbo/rpc/cluster/RouterChain.java  |  24 +-
 .../cluster/configurator/AbstractConfigurator.java |  21 +-
 .../cluster/configurator/parser/ConfigParser.java  |  21 +-
 .../governance/GovernanceRuleRepository.java       |   2 +-
 .../loadbalance/ConsistentHashLoadBalance.java     |  22 +-
 .../rpc/cluster/loadbalance/RandomLoadBalance.java |  18 +-
 .../cluster/router/condition/ConditionRouter.java  |  65 ++-
 .../router/condition/ConditionRouterFactory.java   |   2 +-
 .../dubbo/rpc/cluster/router/tag/TagRouter.java    |  17 +-
 .../cluster/support/BroadcastClusterInvoker.java   |  61 ++-
 .../dubbo/rpc/cluster/support/ClusterUtils.java    |  32 +-
 .../cluster/support/FailoverClusterInvoker.java    |  20 +-
 .../cluster/support/MergeableClusterInvoker.java   |   2 +-
 .../support/registry/ZoneAwareClusterInvoker.java  |   5 +-
 .../cluster/support/wrapper/AbstractCluster.java   |   2 +-
 .../support/wrapper/MockClusterInvoker.java        |   4 +-
 .../loadbalance/RoundRobinLoadBalanceTest.java     |   8 +-
 .../router/condition/ConditionRouterTest.java      |  34 ++
 .../support/FailoverClusterInvokerTest.java        |  28 ++
 .../apache/dubbo/common/BaseServiceMetadata.java   |  10 +-
 .../java/org/apache/dubbo/common/Parameters.java   |   3 +
 .../src/main/java/org/apache/dubbo/common/URL.java |   4 +-
 .../java/org/apache/dubbo/common/URLStrParser.java |   2 +-
 .../common/beanutil/JavaBeanSerializeUtil.java     |   2 +-
 .../dubbo/common/bytecode/ClassGenerator.java      |   4 +-
 .../common/bytecode/CustomizedLoaderClassPath.java |   3 +-
 .../org/apache/dubbo/common/bytecode/Mixin.java    |   2 +-
 .../org/apache/dubbo/common/bytecode/Proxy.java    |   3 -
 .../org/apache/dubbo/common/bytecode/Wrapper.java  |  45 +-
 .../dubbo/common/compiler/support/ClassUtils.java  |  14 +-
 .../common/compiler/support/CtClassBuilder.java    |  24 +-
 .../dubbo/common/compiler/support/JdkCompiler.java |  34 +-
 .../configcenter/AbstractDynamicConfiguration.java |   2 +-
 .../config/configcenter/ConfigChangedEvent.java    |   8 +-
 .../common/config/configcenter/Constants.java      |   1 +
 .../configcenter/TreePathDynamicConfiguration.java |   4 +-
 .../dubbo/common/constants/ClusterRules.java       |  63 +++
 .../dubbo/common/constants/CommonConstants.java    |  16 +
 .../dubbo/common/constants/LoadbalanceRules.java   |  51 ++
 .../dubbo/common/extension/ExtensionLoader.java    |  47 +-
 .../org/apache/dubbo/common/extension/Wrapper.java |   4 +
 .../org/apache/dubbo/common/json/J2oVisitor.java   |   8 +-
 .../org/apache/dubbo/common/lang/Prioritized.java  |   2 +-
 .../dubbo/common/threadlocal/InternalRunnable.java |  53 ++
 .../common/threadlocal/InternalThreadLocal.java    |   2 +-
 .../threadlocal/NamedInternalThreadFactory.java    |   2 +-
 .../common/threadpool/ThreadlessExecutor.java      |  35 +-
 .../threadpool/support/AbortPolicyWithReport.java  |  37 +-
 .../dubbo/common/timer/HashedWheelTimer.java       |   6 +-
 .../dubbo/common/url/component/URLParam.java       |  34 +-
 .../apache/dubbo/common/utils/AnnotationUtils.java |  30 ++
 .../org/apache/dubbo/common/utils/ArrayUtils.java  |  12 +
 .../org/apache/dubbo/common/utils/ClassUtils.java  |  30 +-
 .../apache/dubbo/common/utils/CollectionUtils.java |  43 +-
 .../dubbo/common/utils/CompatibleTypeUtils.java    |  33 +-
 .../apache/dubbo/common/utils/ExecutorUtil.java    |   8 +-
 .../org/apache/dubbo/common/utils/FieldUtils.java  |   5 +
 .../org/apache/dubbo/common/utils/IOUtils.java     |  39 ++
 .../org/apache/dubbo/common/utils/LFUCache.java    |  21 +-
 .../org/apache/dubbo/common/utils/MethodUtils.java |  18 +-
 .../org/apache/dubbo/common/utils/NetUtils.java    |  10 +-
 .../org/apache/dubbo/common/utils/PojoUtils.java   |  15 +-
 .../apache/dubbo/common/utils/ReflectUtils.java    |  49 +-
 .../common/utils/ServiceAnnotationResolver.java    |  25 +-
 .../org/apache/dubbo/common/utils/UrlUtils.java    |  18 +-
 .../org/apache/dubbo/config/AbstractConfig.java    |  17 +-
 .../dubbo/config/AbstractInterfaceConfig.java      |  77 ++-
 .../dubbo/config/AbstractReferenceConfig.java      |  22 -
 .../org/apache/dubbo/config/ApplicationConfig.java |  13 -
 .../java/org/apache/dubbo/config/Constants.java    |   2 +
 .../org/apache/dubbo/config/ConsumerConfig.java    |  19 +-
 .../apache/dubbo/config/MetadataReportConfig.java  |  14 +
 .../java/org/apache/dubbo/config/MethodConfig.java |  27 +-
 .../java/org/apache/dubbo/config/ModuleConfig.java |  13 -
 .../org/apache/dubbo/config/MonitorConfig.java     |  13 -
 .../org/apache/dubbo/config/ProtocolConfig.java    |  68 ++-
 .../org/apache/dubbo/config/ProviderConfig.java    |  55 +-
 .../apache/dubbo/config/ReferenceConfigBase.java   |  16 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |  13 -
 .../org/apache/dubbo/config/ServiceConfigBase.java |  56 +--
 .../java/org/apache/dubbo/config/SslConfig.java    |  28 +-
 .../dubbo/config/annotation/DubboReference.java    |  10 +-
 .../dubbo/config/annotation/DubboService.java      |   9 +-
 .../config/context/ConfigConfigurationAdapter.java |   2 +-
 .../apache/dubbo/config/context/ConfigManager.java |  17 +-
 .../apache/dubbo/event/DirectEventDispatcher.java  |   1 +
 .../org/apache/dubbo/event/EventDispatcher.java    |   2 +-
 .../dubbo/event/ParallelEventDispatcher.java       |   1 +
 .../apache/dubbo/rpc/support/ProtocolUtils.java    |   7 +
 .../dubbo/common/BaseServiceMetadataTest.java      |  66 +++
 ...t.java => PojoUtilsForNonPublicStaticTest.java} |  40 +-
 .../org/apache/dubbo/common/URLStrParserTest.java  |  58 ++-
 .../test/java/org/apache/dubbo/common/URLTest.java | 112 +++++
 .../apache/dubbo/common/bytecode/WrapperTest.java  |  52 +-
 .../common/compiler/support/JdkCompilerTest.java   |  31 ++
 .../configcenter/ConfigChangedEventTest.java       |  30 +-
 .../common/extension/ExtensionLoaderTest.java      |  91 +++-
 .../duplicated/DuplicatedOverriddenExt.java}       |  16 +-
 .../DuplicatedWithoutOverriddenExt.java}           |  17 +-
 .../duplicated/impl/DuplicatedOverriddenExt1.java} |  15 +-
 .../duplicated/impl/DuplicatedOverriddenExt2.java} |  15 +-
 .../impl/DuplicatedWithoutOverriddenExt1.java}     |  17 +-
 .../impl/DuplicatedWithoutOverriddenExt2.java}     |  17 +-
 .../dubbo/common/extension/wrapper/Demo.java}      |  12 +-
 .../wrapper/WrapperTest.java}                      |  27 +-
 .../common/extension/wrapper/impl/DemoImpl.java}   |  14 +-
 .../wrapper/impl/DemoWrapper.java}                 |  26 +-
 .../wrapper/impl/DemoWrapper2.java}                |  26 +-
 .../dubbo/common/model/SerializablePerson.java     |   5 +-
 .../threadlocal/InternalThreadLocalTest.java       |   1 +
 .../common/threadpool/ThreadlessExecutorTest.java  |  58 +++
 .../threadpool/manager/ExecutorRepositoryTest.java |  79 +++
 .../support/AbortPolicyWithReportTest.java         |  52 ++
 .../support/cached/CachedThreadPoolTest.java       |  13 +-
 .../support/eager/EagerThreadPoolExecutorTest.java |  17 +-
 .../support/eager/EagerThreadPoolTest.java         |  13 +-
 .../dubbo/common/timer/HashedWheelTimerTest.java   | 182 +++++--
 .../dubbo/common/utils/CollectionUtilsTest.java    |   2 +-
 .../common/utils/CompatibleTypeUtilsTest.java      |   2 +-
 .../apache/dubbo/common/utils/ConfigUtilsTest.java |   2 +-
 .../apache/dubbo/common/utils/DefaultPageTest.java |   9 +-
 .../apache/dubbo/common/utils/LFUCacheTest.java    |  21 +-
 .../org/apache/dubbo/common/utils/LogTest.java     |  55 +-
 .../apache/dubbo/common/utils/MemberUtilsTest.java |  12 +
 .../apache/dubbo/common/utils/MethodUtilsTest.java |  54 ++
 .../apache/dubbo/common/utils/NetUtilsTest.java    |  11 +-
 .../apache/dubbo/common/utils/PojoUtilsTest.java   |  96 +++-
 .../dubbo/common/utils/ReflectUtilsTest.java       |  34 +-
 ...on.extension.duplicated.DuplicatedOverriddenExt |   1 +
 ...nsion.duplicated.DuplicatedWithoutOverriddenExt |   1 +
 ...on.extension.duplicated.DuplicatedOverriddenExt |   1 +
 ...nsion.duplicated.DuplicatedWithoutOverriddenExt |   1 +
 .../org.apache.dubbo.common.extension.wrapper.Demo |   4 +
 .../dubbo/registry/support/FailbackRegistry.java   |   4 -
 .../dubbo/rpc/protocol/dubbo/FutureAdapter.java    |  25 +-
 .../org/apache/dubbo/echo/EchoServiceTest.java     |   3 +-
 .../apache/dubbo/generic/GenericServiceTest.java   |  24 +
 dubbo-config/dubbo-config-api/pom.xml              |   6 +
 .../org/apache/dubbo/config/ReferenceConfig.java   |  47 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |   9 +-
 .../dubbo/config/bootstrap/DubboBootstrap.java     |  67 +--
 .../bootstrap/DubboBootstrapStartStopListener.java |  20 +-
 .../bootstrap/builders/ReferenceBuilder.java       |   6 +-
 .../config/bootstrap/builders/ServiceBuilder.java  |   8 +-
 .../dubbo/config/utils/ConfigValidationUtils.java  |  38 +-
 .../internal/org.apache.dubbo.event.EventListener  |   2 +-
 ...g.apache.dubbo.metadata.MetadataServiceExporter |   1 -
 .../apache/dubbo/config/AbstractConfigTest.java    |  15 +-
 .../dubbo/config/MetadataReportConfigTest.java     |  32 +-
 .../org/apache/dubbo/config/MethodConfigTest.java  |  12 +-
 .../apache/dubbo/config/ReferenceConfigTest.java   |  38 +-
 .../apache/dubbo/config/RegistryConfigTest.java    |  28 ++
 .../org/apache/dubbo/config/ServiceConfigTest.java |  20 +
 .../PublishingServiceDefinitionListenerTest.java   |   1 +
 ...onfigDefaultPropertyValueBeanPostProcessor.java |  11 +-
 .../context/DubboBootstrapApplicationListener.java |  17 +-
 ...bboBootstrapStartStopListenerSpringAdapter.java |  48 ++
 ...DubboLifecycleComponentApplicationListener.java |  11 +-
 ...meExecutionApplicationContextEventListener.java |  71 ---
 .../context/annotation/EnableDubboConfig.java      |   5 +-
 .../context/event/DubboBootstrapStatedEvent.java   |  50 ++
 .../context/event/DubboBootstrapStopedEvent.java   |  50 ++
 .../properties/DefaultDubboConfigBinder.java       |  22 +
 .../spring/extension/SpringExtensionFactory.java   |   3 +
 .../spring/schema/DubboNamespaceHandler.java       |   2 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  10 +
 .../src/main/resources/META-INF/dubbo.xsd          |  15 +
 ...onfig.bootstrap.DubboBootstrapStartStopListener |   1 +
 .../spring/registry/MockRegistryFactory.java       |   8 +-
 .../META-INF/spring/dubbo-generic-consumer.xml     |   2 +-
 .../spring/dubbo-nacos-consumer-context.xml        |  12 +-
 .../spring/dubbo-nacos-provider-context.xml        |   6 +-
 .../support/apollo/ApolloDynamicConfiguration.java |   2 +-
 .../apollo/ApolloDynamicConfigurationTest.java     |  17 +-
 .../support/apollo/EmbeddedApolloJunit5.java       | 193 +++++++
 .../support/zookeeper/CacheListener.java           |   7 +-
 .../zookeeper/ZookeeperDynamicConfiguration.java   |  15 +-
 .../main/resources/META-INF/assembly/bin/start.sh  |  10 +-
 .../dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml |   4 +
 .../dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml |   2 +-
 dubbo-dependencies-bom/pom.xml                     |   6 +-
 .../org/apache/dubbo/cache/filter/CacheFilter.java |   2 +-
 .../dubbo/cache/support/AbstractCacheFactory.java  |  25 +-
 .../dubbo/cache/support/expiring/ExpiringMap.java  |  20 +-
 .../internal/org.apache.dubbo.cache.CacheFactory   |   3 +-
 .../support/expiring/ExpiringCacheFactoryTest.java |  76 ++-
 dubbo-metadata/dubbo-metadata-api/pom.xml          |   7 +
 .../DynamicConfigurationServiceNameMapping.java    |   2 +-
 .../definition/builder/MapTypeBuilder.java         |  11 +-
 .../definition/model/MethodDefinition.java         |   7 +-
 .../metadata/definition/model/TypeDefinition.java  |  51 +-
 .../metadata/report/MetadataReportInstance.java    |   3 +
 .../support/AbstractMetadataReportFactory.java     |   8 +-
 .../rest/AbstractServiceRestMetadataResolver.java  |   6 +-
 .../dubbo/metadata/rest/RestMetadataConstants.java |  33 ++
 .../dubbo/metadata/rest/RestMethodMetadata.java    |   8 +-
 .../dubbo/metadata/rest/ServiceRestMetadata.java   |   8 +-
 ...bstractRequestAnnotationParameterProcessor.java |  17 +-
 .../SpringMvcServiceRestMetadataResolver.java      |  43 +-
 .../dubbo/metadata/rest/SpringRestService.java     |   4 +-
 .../dubbo/metadata/rest/StandardRestService.java   |   4 +-
 .../JAXRSServiceRestMetadataResolverTest.java      |   3 +-
 .../SpringMvcServiceRestMetadataResolverTest.java} |  21 +-
 .../dubbo/spring-mvc-servoce-rest-metadata.json    | 321 ++++++++++++
 .../protobuf/ProtobufTypeBuilderTest.java          |   3 +-
 .../processing/util/ServiceAnnotationUtils.java    |  42 +-
 .../util/ServiceAnnotationUtilsTest.java           |   8 +-
 .../dubbo/metadata/rest/DefaultRestService.java    |   4 +-
 .../dubbo/metadata/rest/SpringRestService.java     |   4 +-
 .../dubbo/metadata/rest/StandardRestService.java   |   4 +-
 .../zookeeper/ZookeeperMetadataReportTest.java     | 556 +++++++++++----------
 .../dubbo/monitor/support/MonitorFilter.java       |   6 +-
 .../apache/dubbo/qos/legacy/ListTelnetHandler.java |   1 +
 .../apache/dubbo/qos/legacy/LogTelnetHandler.java  |   2 +-
 .../qos/server/handler/QosProcessHandler.java      |   4 +-
 .../qos/server/handler/TelnetIdleEventHandler.java |  42 ++
 .../registry/client/DefaultServiceInstance.java    |  12 +-
 .../dubbo/registry/client/InstanceAddressURL.java  |   4 +
 .../dubbo/registry/client/ServiceDiscovery.java    |  12 +-
 .../client/ServiceDiscoveryRegistryDirectory.java  |   3 +-
 .../listener/ServiceInstancesChangedListener.java  |   8 +-
 .../metadata/store/RemoteMetadataServiceImpl.java  |   1 -
 .../client/migration/MigrationInvoker.java         |  15 +-
 .../client/migration/MigrationRuleHandler.java     |   2 -
 .../registry/integration/DynamicDirectory.java     |   7 +-
 .../registry/integration/RegistryDirectory.java    |  16 +-
 .../registry/integration/RegistryProtocol.java     |   2 +-
 .../dubbo/registry/retry/FailedNotifiedTask.java   |  67 ---
 .../dubbo/registry/support/AbstractRegistry.java   |   5 +-
 .../registry/support/AbstractRegistryFactory.java  |  20 +-
 .../dubbo/registry/support/FailbackRegistry.java   |  46 +-
 .../registry/support/FailbackRegistryTest.java     |  31 --
 .../registry/multicast/MulticastRegistry.java      |   4 +-
 .../apache/dubbo/registry/nacos/NacosRegistry.java |  20 +-
 .../dubbo/registry/nacos/NacosRegistryFactory.java |   8 +
 .../registry/zookeeper/ZookeeperRegistry.java      |  10 +-
 .../zookeeper/ZookeeperServiceDiscovery.java       |  10 +
 .../ZookeeperServiceDiscoveryChangeWatcher.java    |   2 +-
 .../apache/dubbo/remoting/exchange/Request.java    |  10 +
 .../remoting/exchange/codec/ExchangeCodec.java     | 141 ++++--
 .../remoting/exchange/support/DefaultFuture.java   |   2 +-
 .../dubbo/remoting/telnet/support/TelnetUtils.java |   4 +-
 .../telnet/support/command/LogTelnetHandler.java   |   2 +-
 .../support/command/StatusTelnetHandler.java       |   4 +-
 .../dubbo/remoting/transport/AbstractClient.java   |  78 +--
 .../dubbo/remoting/transport/AbstractCodec.java    |  39 +-
 .../dubbo/remoting/transport/AbstractEndpoint.java |  22 +-
 .../dubbo/remoting/transport/AbstractServer.java   |  23 +-
 .../dubbo/remoting/transport/CodecSupport.java     | 114 ++++-
 .../remoting/transport/MultiMessageHandler.java    |  13 +-
 .../org/apache/dubbo/remoting/MockTransporter.java |  72 +--
 .../apache/dubbo/remoting/TransportersTest.java    |  46 ++
 .../dubbo/remoting/codec/ExchangeCodecTest.java    |  32 +-
 .../dubbo/remoting/exchange/ExchangersTest.java    |  58 +++
 .../dubbo/remoting/exchange/MockExchanger.java     |  73 +--
 .../exchange/support/DefaultFutureTest.java        |  67 +++
 .../dubbo/remoting/telnet/TelnetUtilsTest.java     |  72 +++
 .../telnet/support/ClearTelnetHandlerTest.java     |  46 ++
 .../telnet/support/ExitTelnetHandlerTest.java      |  27 +-
 .../telnet/support/HelpTelnetHandlerTest.java      |  48 ++
 .../telnet/support/StatusTelnetHandlerTest.java    |  44 ++
 .../dubbo/remoting/utils/PayloadDropperTest.java   |  43 ++
 .../apache/dubbo/remoting/utils/UrlUtilsTest.java  |  40 ++
 .../internal/org.apache.dubbo.remoting.Transporter |   1 +
 .../org.apache.dubbo.remoting.exchange.Exchanger   |   1 +
 .../remoting/transport/netty4/NettyClient.java     |   7 +-
 .../remoting/transport/netty4/NettyServer.java     |   5 +
 .../zookeeper/curator/CuratorZookeeperClient.java  |  12 +-
 dubbo-rpc/dubbo-rpc-api/pom.xml                    |   6 +
 .../java/org/apache/dubbo/rpc/AppResponse.java     |  31 +-
 .../java/org/apache/dubbo/rpc/AsyncRpcResult.java  |   6 +-
 .../org/apache/dubbo/rpc/AttachmentsAdapter.java   |   6 +-
 .../main/java/org/apache/dubbo/rpc/Constants.java  |   4 +
 .../java/org/apache/dubbo/rpc/RpcInvocation.java   |   9 +-
 .../main/java/org/apache/dubbo/rpc/RpcStatus.java  |  17 +-
 .../apache/dubbo/rpc/filter/AccessLogFilter.java   |   3 +-
 .../apache/dubbo/rpc/filter/ExceptionFilter.java   |   4 +-
 .../org/apache/dubbo/rpc/filter/GenericFilter.java |  42 +-
 .../apache/dubbo/rpc/filter/GenericImplFilter.java |   2 +-
 .../org/apache/dubbo/rpc/filter/TokenFilter.java   |   4 +-
 .../org/apache/dubbo/rpc/filter/tps/StatItem.java  |   2 +-
 .../dubbo/rpc/protocol/AbstractExporter.java       |   9 +-
 .../apache/dubbo/rpc/protocol/AbstractInvoker.java |  11 +
 .../dubbo/rpc/protocol/AbstractProxyProtocol.java  |  10 +-
 .../dubbo/rpc/proxy/AbstractProxyFactory.java      |   5 +-
 .../dubbo/rpc/proxy/AbstractProxyInvoker.java      |   4 +-
 .../dubbo/rpc/proxy/InvokerInvocationHandler.java  |  12 +
 .../apache/dubbo/rpc/support/AccessLogData.java    |  15 +
 .../org/apache/dubbo/rpc/support/RpcUtils.java     |   2 +-
 .../java/org/apache/dubbo/rpc/RpcContextTest.java  |   1 +
 .../org/apache/dubbo/rpc/TimeoutCountDownTest.java |  29 +-
 .../dubbo/rpc/filter/AccessLogFilterTest.java      |   2 +
 .../rpc/filter/tps/DefaultTPSLimiterTest.java      |  24 +-
 .../apache/dubbo/rpc/filter/tps/StatItemTest.java  |  11 +
 .../org/apache/dubbo/rpc/support/RpcUtilsTest.java | 120 +++--
 .../protocol/dubbo/DecodeableRpcInvocation.java    |  14 +-
 .../rpc/protocol/dubbo/DecodeableRpcResult.java    |  14 +-
 .../dubbo/rpc/protocol/dubbo/DubboCodec.java       |  40 +-
 .../rpc/protocol/dubbo/DubboCodecSupport.java      |  53 ++
 .../dubbo/rpc/protocol/dubbo/DubboExporter.java    |   3 +-
 .../dubbo/rpc/protocol/dubbo/DubboInvoker.java     |   3 +-
 .../dubbo/rpc/protocol/dubbo/DubboProtocol.java    | 104 ++--
 .../dubbo/ReferenceCountExchangeClient.java        |  21 +-
 ...bleTest.java => DubboInvokerAvailableTest.java} |   3 +-
 .../rpc/protocol/dubbo/DubboProtocolTest.java      |  18 +
 .../dubbo/decode/DubboTelnetDecodeTest.java        |   4 +-
 .../rpc/protocol/dubbo/support/DemoService.java    |   2 +
 .../protocol/dubbo/support/DemoServiceImpl.java    |   8 +
 .../rpc/protocol/grpc/DubboHandlerRegistry.java    |   9 +-
 .../dubbo/rpc/protocol/injvm/InjvmExporter.java    |   3 +-
 .../dubbo/rpc/protocol/injvm/InjvmInvoker.java     |  41 +-
 .../dubbo/rpc/protocol/injvm/InjvmProtocol.java    |  11 +-
 .../dubbo/rpc/protocol/injvm/DemoService.java      |   2 +
 .../dubbo/rpc/protocol/injvm/DemoServiceImpl.java  |  11 +
 .../rpc/protocol/injvm/InjvmProtocolTest.java      |  18 +
 .../dubbo/rpc/protocol/tri/TripleProtocol.java     |   3 +-
 .../serialize/hessian2/Hessian2ObjectInput.java    |  10 +-
 .../serialize/hessian2/Hessian2ObjectOutput.java   |  10 +-
 pom.xml                                            |  40 +-
 327 files changed, 5893 insertions(+), 2080 deletions(-)

diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c92e4a1..a1f163a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,18 +1,18 @@
 
-## Contributing to dubbo
-Dubbo is released under the non-restrictive Apache 2.0 license, and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. If you want to contribute even something trivial please do not hesitate, but follow the guidelines below.
+## Contributing to Dubbo
+Dubbo is released under the non-restrictive Apache 2.0 licenses and follows a very standard Github development process, using Github tracker for issues and merging pull requests into master. Contributions of all form to this repository is acceptable, as long as it follows the prescribed community guidelines enumerated below.
 
 ### Sign the Contributor License Agreement
-Before we accept a non-trivial patch or pull request we will need you to sign the Contributor License Agreement. Signing the contributor’s agreement does not grant anyone commit rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors might be asked to join the core team, and given the ability to merge pull requests.
+Before we accept a non-trivial patch or pull request (PRs), we will need you to sign the Contributor License Agreement. Signing the contributors' agreement does not grant anyone commits rights to the main repository, but it does mean that we can accept your contributions, and you will get an author credit if we do. Active contributors may get invited to join the core team that will grant them privileges to merge existing PRs. 
 
 ### Contact
 
 #### Mailing list
 
-The mailing list is the recommended way for discussing almost anything that related to Dubbo. Please refer to this [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) for detailed documentation on how to subscribe.
+The mailing list is the recommended way of pursuing a discussion on almost anything related to Dubbo. Please refer to this [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) for detailed documentation on how to subscribe.
 
-- [dev@dubbo.apache.org](mailto:dev-subscribe@dubbo.apache.org): the develop mailing list, you can ask question here if you have encountered any problem when using or developing Dubbo.
-- [commits@dubbo.apache.org](mailto:commits-subscribe@dubbo.apache.org): all the commits will be sent to this mailing list. You can subscribe to it if you are interested in Dubbo's development.
+- [dev@dubbo.apache.org](mailto:dev-subscribe@dubbo.apache.org): the developer mailing list where you can ask questions about an issue you may have encountered while working with Dubbo. 
+- [commits@dubbo.apache.org](mailto:commits-subscribe@dubbo.apache.org): the commit updates will get broadcasted on this mailing list. You can subscribe to it, should you be interested in following Dubbo's development.
 - [notifications@dubbo.apache.org](mailto:notifications-subscribe@dubbo.apache.org): all the Github [issue](https://github.com/apache/dubbo/issues) updates and [pull request](https://github.com/apache/dubbo/pulls) updates will be sent to this mailing list.
 
 ### Reporting issue
@@ -21,33 +21,33 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?templat
 
 ### Code Conventions
 Our code style is almost in line with the standard java conventions (Popular IDE's default setting satisfy this), with the following additional restricts:  
-* If there are more than 120 characters in current line, start a new line.
+* If there are more than 120 characters in the current line, begin a new line.
 
-* Make sure all new .java files to have a simple Javadoc class comment with at least a @date tag identifying birth, and preferably at least a paragraph on what the class is for.
+* Make sure all new .java files to have a simple Javadoc class comment with at least a @date tag identifying birth, and preferably at least a paragraph on the intended purpose of the class.
 
 * Add the ASF license header comment to all new .java files (copy from existing files in the project)
 
-* Make sure no @author tag added to the file you contribute since @author tag is not used at Apache, other ways such as cvs will record all your contributions fairly.
+* Make sure no @author tag gets appended to the file you contribute to as the @author tag is incompatible with Apache. Rest assured, other ways, including CVS, will ensure transparency, fairness in recording your contributions. 
 
 * Add some Javadocs and, if you change the namespace, some XSD doc elements.
 
-* A few unit tests should be added for a new feature or an important bugfix.
+* Sufficient unit-tests should accompany new feature development or non-trivial bug fixes. 
 
-* If no-one else is using your branch, please rebase it against the current master (or other target branch in the main project).
+* If no-one else is using your branch, please rebase it against the current master (or another target branch in the main project).
 
-* When writing a commit message please follow these conventions, if you are fixing an existing issue please add Fixes #XXX at the end of the commit message (where XXX is the issue number).
+* When writing a commit message, please follow the following conventions: should your commit address an open issue, please add Fixes #XXX at the end of the commit message (where XXX is the issue number).
 
 ### Contribution flow
 
-This is a rough outline of what a contributor's workflow looks like:
+A rough outline of an ideal contributors' workflow is as follows:
 
 * Fork the current repository
-* Create a topic branch from where to base the contribution. This is usually master.
+* Create a topic branch from where to base the contribution. Mostly, it's the master branch.
 * Make commits of logical units.
-* Make sure commit messages are in the proper format (see below).
+* Make sure the commit messages are in the proper format (see below).
 * Push changes in a topic branch to your forked repository.
 * Follow the checklist in the [pull request template](https://github.com/apache/dubbo/blob/master/PULL_REQUEST_TEMPLATE.md)
-* Before you sending out the pull request, please sync your forked repository with remote repository, this will make your pull request simple and clear. See guide below:
+* Before sending out the pull request, please sync your forked repository with the remote repository to ensure that your PR is elegant, concise. Reference the guide below:
 ```
 git remote add upstream git@github.com:apache/dubbo.git
 git fetch upstream
@@ -62,15 +62,15 @@ Thanks for contributing!
 
 ### Code style
 
-We provide a template file [dubbo_codestyle_for_idea.xml](https://github.com/apache/dubbo/tree/master/codestyle/dubbo_codestyle_for_idea.xml) for IntelliJ idea, you can import it to you IDE. 
-If you use Eclipse you can config manually by referencing the same file.
+We provide a template file [dubbo_codestyle_for_idea.xml](https://github.com/apache/dubbo/tree/master/codestyle/dubbo_codestyle_for_idea.xml) for IntelliJ idea that you can import it to your workplace. 
+If you use Eclipse, you can use the IntelliJ Idea template for manually configuring your file.
 
 **NOTICE**
 
-It is very important to set the dubbo_codestyle_for_idea.xml, otherwise you will fail to pass the Travis CI. Steps to set the code style are as below:
+It's critical to set the dubbo_codestyle_for_idea.xml to avoid the failure of your Travis CI builds. Steps to configure the code styles are as follows:
 
 1. Enter `Editor > Code Style`
-2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click ![manage profiles](codestyle/manage_profiles.png).
-From the drop-down list, select `Import Scheme`, then select this option `IntelliJ IDEA code style XML` to import scheme
+2. To manage a code style scheme, in the Code Style page, select the desired scheme from the drop-down list, and click on ![manage profiles](codestyle/manage_profiles.png).
+From the drop-down list, select `Import Scheme`, then choose the option `IntelliJ IDEA code style XML` to import the scheme. 
 3. In the Scheme field, type the name of the new scheme and press ⏎ to save the changes.
 
diff --git a/NOTICE b/NOTICE
index 9664603..e414ebf 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache Dubbo
-Copyright 2018-2020 The Apache Software Foundation
+Copyright 2018-2021 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).
diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md
index 20c5854..a1384f2 100644
--- a/PULL_REQUEST_TEMPLATE.md
+++ b/PULL_REQUEST_TEMPLATE.md
@@ -1,18 +1,16 @@
 ## What is the purpose of the change
 
-XXXXX
+
 
 ## Brief changelog
 
-XXXXX
 
 ## Verifying this change
 
-XXXXX
 
-Follow this checklist to help us incorporate your contribution quickly and easily:
+<!-- Follow this checklist to help us incorporate your contribution quickly and easily: -->
 
-- [x] Make sure there is a [GITHUB_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GITHUB issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
+- [x] Make sure there is a [GitHub_issue](https://github.com/apache/dubbo/issues) field for the change (usually before you start working on it). Trivial changes like typos do not require a GitHub issue. Your pull request should address just this issue, without pulling in other changes - one PR resolves one issue.
 - [ ] Format the pull request title like `[Dubbo-XXX] Fix UnknownException when host config not exist #XXX`. Each commit in the pull request should have a meaningful subject line and body.
 - [ ] Write a pull request description that is detailed enough to understand what the pull request does, how, and why.
 - [ ] Write necessary unit-test to verify your logic correction, more mock a little better when cross module dependency exist. If the new feature or significant change is committed, please remember to add sample in [dubbo samples](https://github.com/apache/dubbo-samples) project.
diff --git a/README.md b/README.md
index 153121d..d84a5ec 100644
--- a/README.md
+++ b/README.md
@@ -1,22 +1,22 @@
 # Apache Dubbo Project
 
-[![Build Status](https://travis-ci.org/apache/dubbo.svg?branch=master)](https://travis-ci.org/apache/dubbo)
-[![codecov](https://codecov.io/gh/apache/dubbo/branch/master/graph/badge.svg)](https://codecov.io/gh/apache/dubbo)
-![maven](https://img.shields.io/maven-central/v/org.apache.dubbo/dubbo.svg)
-![license](https://img.shields.io/github/license/alibaba/dubbo.svg)
+[![Build Status](https://travis-ci.com/apache/dubbo.svg?branch=master)](https://travis-ci.com/apache/dubbo)
+[![Codecov](https://codecov.io/gh/apache/dubbo/branch/master/graph/badge.svg)](https://codecov.io/gh/apache/dubbo)
+![Maven](https://img.shields.io/maven-central/v/org.apache.dubbo/dubbo.svg)
+![License](https://img.shields.io/github/license/alibaba/dubbo.svg)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/apache/dubbo.svg)](http://isitmaintained.com/project/apache/dubbo "Average time to resolve an issue")
 [![Percentage of issues still open](http://isitmaintained.com/badge/open/apache/dubbo.svg)](http://isitmaintained.com/project/apache/dubbo "Percentage of issues still open")
 [![Tweet](https://img.shields.io/twitter/url/http/shields.io.svg?style=social)](https://twitter.com/intent/tweet?text=Apache%20Dubbo%20is%20a%20high-performance%2C%20java%20based%2C%20open%20source%20RPC%20framework.&url=http://dubbo.apache.org/&via=ApacheDubbo&hashtags=rpc,java,dubbo,micro-service)
-[![](https://img.shields.io/twitter/follow/ApacheDubbo.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
+[![Twitter Follow](https://img.shields.io/twitter/follow/ApacheDubbo.svg?label=Follow&style=social&logoWidth=0)](https://twitter.com/intent/follow?screen_name=ApacheDubbo)
 [![Gitter](https://badges.gitter.im/alibaba/dubbo.svg)](https://gitter.im/alibaba/dubbo?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
 
-Apache Dubbo is a high-performance, Java based open source RPC framework. Please visit [official site](http://dubbo.apache.org) for quick start and documentations, as well as [Wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
+Apache Dubbo is a high-performance, Java-based open-source RPC framework. Please visit the [official site](http://dubbo.apache.org) for the quick start guide and documentation, as well as the [wiki](https://github.com/apache/dubbo/wiki) for news, FAQ, and release notes.
 
-We are now collecting dubbo user info in order to help us to improve Dubbo better, pls. kindly help us by providing yours on [issue#1012: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/1012), thanks :)
+We are now collecting Dubbo user info to help us to improve Dubbo further. Kindly support us by providing your usage information on [issue#1012: Wanted: who's using dubbo](https://github.com/apache/dubbo/issues/1012), thanks :)
 
 ## Architecture
 
-![Architecture](http://dubbo.apache.org/img/architecture.png)
+![Architecture](https://dubbo.apache.org/imgs/architecture.png)
 
 ## Features
 
@@ -29,14 +29,14 @@ We are now collecting dubbo user info in order to help us to improve Dubbo bette
 
 ## Getting started
 
-The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-api). You may clone the sample project and step into `dubbo-samples-api` sub directory before read on.
+The following code snippet comes from [Dubbo Samples](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api). You may clone the sample project and step into the `dubbo-samples-api` subdirectory before proceeding.
 
 ```bash
 # git clone https://github.com/apache/dubbo-samples.git
-# cd dubbo-samples/java/dubbo-samples-api
+# cd dubbo-samples/dubbo-samples-api
 ```
 
-There's a [README](https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. Read it and try this sample out by following the instructions.
+There's a [README](https://github.com/apache/dubbo-samples/tree/master/dubbo-samples-api/README.md) file under `dubbo-samples-api` directory. We recommend referencing the samples in that directory by following the below-mentioned instructions: 
 
 ### Maven dependency
 
@@ -44,7 +44,7 @@ There's a [README](https://github.com/apache/dubbo-samples/tree/master/java/dubb
 <properties>
     <dubbo.version>2.7.8</dubbo.version>
 </properties>
-    
+
 <dependencies>
     <dependency>
         <groupId>org.apache.dubbo</groupId>
@@ -70,7 +70,7 @@ public interface GreetingsService {
 }
 ```
 
-*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
+*See [api/GreetingsService.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/api/GreetingsService.java) on GitHub.*
 
 ### Implement service interface for the provider
 
@@ -87,7 +87,7 @@ public class GreetingsServiceImpl implements GreetingsService {
 }
 ```
 
-*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
+*See [provider/GreetingsServiceImpl.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/GreetingsServiceImpl.java) on GitHub.*
 
 ### Start service provider
 
@@ -119,7 +119,7 @@ public class Application {
 }
 ```
 
-*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
+*See [provider/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/provider/Application.java) on GitHub.*
 
 ### Build and run the provider
 
@@ -128,7 +128,7 @@ public class Application {
 # mvn -Djava.net.preferIPv4Stack=true -Dexec.mainClass=org.apache.dubbo.samples.provider.Application exec:java
 ```
 
-### Call remote service in consumer
+### Call remote service in the consumer
 
 ```java
 package org.apache.dubbo.samples.client;
@@ -153,7 +153,7 @@ public class Application {
     }
 }
 ```
-*See [consumer/Application.java](https://github.com/apache/dubbo-samples/blob/master/java/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
+*See [consumer/Application.java](https://github.com/apache/dubbo-samples/blob/master/dubbo-samples-api/src/main/java/org/apache/dubbo/samples/client/Application.java) on GitHub.*
 
 ### Build and run the consumer
 
@@ -167,14 +167,14 @@ The consumer will print out `hi, dubbo` on the screen.
 
 ### Next steps
 
-* [Your first Dubbo application](http://dubbo.apache.org/en-us/blog/dubbo-101.html) - A 101 tutorial to reveal more details, with the same code above.
-* [Dubbo user manual](http://dubbo.apache.org/en-us/docs/user/preface/background.html) - How to use Dubbo and all its features.
-* [Dubbo developer guide](http://dubbo.apache.org/en-us/docs/dev/build.html) - How to involve in Dubbo development.
-* [Dubbo admin manual](http://dubbo.apache.org/en-us/docs/admin/install/provider-demo.html) - How to admin and manage Dubbo services.
+* [Your first Dubbo application](http://dubbo.apache.org/blog/2018/08/07/dubbo-101/) - A 101 tutorial to reveal more details, with the same code above.
+* [Dubbo user manual](http://dubbo.apache.org/docs/v2.7/user/preface/background/) - How to use Dubbo and all its features.
+* [Dubbo developer guide](http://dubbo.apache.org/docs/v2.7/dev/build/) - How to involve in Dubbo development.
+* [Dubbo admin manual](http://dubbo.apache.org/docs/v2.7/admin/install/provider-demo/) - How to admin and manage Dubbo services.
 
 ## Building
 
-If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is required to build the master branch)
+If you want to try out the cutting-edge features, you can build with the following commands. (Java 1.8 is needed to build the master branch)
 
 ```
   mvn clean install
@@ -182,11 +182,11 @@ If you want to try out the cutting-edge features, you can build with the followi
 
 ## Contact
 
-* Mailing list: 
+* Mailing list:
   * dev list: for dev/user discussion. [subscribe](mailto:dev-subscribe@dubbo.apache.org), [unsubscribe](mailto:dev-unsubscribe@dubbo.apache.org), [archive](https://lists.apache.org/list.html?dev@dubbo.apache.org),  [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide)
-  
+
 * Bugs: [Issues](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
-* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo) 
+* Gitter: [Gitter channel](https://gitter.im/alibaba/dubbo)
 * Twitter: [@ApacheDubbo](https://twitter.com/ApacheDubbo)
 
 ## Contributing
@@ -195,18 +195,18 @@ See [CONTRIBUTING](https://github.com/apache/dubbo/blob/master/CONTRIBUTING.md)
 
 ### How can I contribute?
 
-* Take a look at issues with tag called [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
-* Join the discussion on mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
+* Take a look at issues with tags marked [`Good first issue`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) or [`Help wanted`](https://github.com/apache/dubbo/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22).
+* Join the discussion on the mailing list, subscription [guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide).
 * Answer questions on [issues](https://github.com/apache/dubbo/issues).
-* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us pull request.
+* Fix bugs reported on [issues](https://github.com/apache/dubbo/issues), and send us a pull request.
 * Review the existing [pull request](https://github.com/apache/dubbo/pulls).
 * Improve the [website](https://github.com/apache/dubbo-website), typically we need
   * blog post
   * translation on documentation
-  * use cases about how Dubbo is being used in enterprise system.
+  * use cases around the integration of Dubbo in enterprise systems.
 * Improve the [dubbo-admin/dubbo-monitor](https://github.com/apache/dubbo-admin).
 * Contribute to the projects listed in [ecosystem](https://github.com/dubbo).
-* Any form of contribution that is not mentioned above.
+* Other forms of contribution not explicitly enumerated above.
 * If you would like to contribute, please send an email to dev@dubbo.apache.org to let us know!
 
 ## Reporting bugs
@@ -215,7 +215,7 @@ Please follow the [template](https://github.com/apache/dubbo/issues/new?template
 
 ## Reporting a security vulnerability
 
-Please report security vulnerability to [us](mailto:security@dubbo.apache.org) privately.
+Please report security vulnerabilities to [us](mailto:security@dubbo.apache.org) privately.
 
 ## Dubbo ecosystem
 
@@ -228,12 +228,12 @@ Please report security vulnerability to [us](mailto:security@dubbo.apache.org) p
 
 #### Language
 
+* [Go](https://github.com/dubbo/dubbo-go) (recommended)
 * [Node.js](https://github.com/apache/dubbo-js)
 * [Python](https://github.com/dubbo/py-client-for-apache-dubbo)
 * [PHP](https://github.com/apache/dubbo-php-framework)
-* [Go](https://github.com/dubbo/dubbo-go)
 * [Erlang](https://github.com/apache/dubbo-erlang)
 
 ## License
 
-Apache Dubbo is under the Apache 2.0 license. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
+Apache Dubbo software is licenced under the Apache License Version 2.0. See the [LICENSE](https://github.com/apache/dubbo/blob/master/LICENSE) file for details.
diff --git a/SECURITY.md b/SECURITY.md
index ac0c2ad..b8b2a2c 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -2,7 +2,7 @@
 
 ## Supported Versions
 
-Below is a table that shows versions that accept security fix.
+Below is a table that shows versions that we accept security fixes.
 
 | Version | Supported          |
 | ------- | ------------------ |
@@ -15,11 +15,11 @@ Below is a table that shows versions that accept security fix.
 
 The Apache Software Foundation takes a rigorous standpoint in annihilating the security issues in its software projects. Apache Dubbo is highly sensitive and forthcoming to issues pertaining to its features and functionality.
 
-If you have apprehensions regarding Dubbo's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the Apache Dubbo Security Team by dropping a mail at security@dubbo.apache.org. In the mail, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Dubbo community will get back to you after assessing and analysing the findings.
+If you have apprehensions regarding Dubbo's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the Apache Dubbo Security Team by dropping a mail at security@dubbo.apache.org. In the email, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Dubbo community will get back to you after assessing and analysing the findings.
 
 PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain.
 
-## VULNERABILITY HANDLING
+## Vulnerability Handling
 
 An overview of the vulnerability handling process is:
 
diff --git a/dubbo-cluster/pom.xml b/dubbo-cluster/pom.xml
index 3055454..26b1295 100644
--- a/dubbo-cluster/pom.xml
+++ b/dubbo-cluster/pom.xml
@@ -54,5 +54,11 @@
             <artifactId>zookeeper</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-serialization-hessian2</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
index 948827a..1fdadf8 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java
@@ -22,7 +22,6 @@ import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
 
 /**
  * Cluster. (SPI, Singleton, ThreadSafe)
@@ -33,7 +32,8 @@ import org.apache.dubbo.rpc.cluster.support.FailoverCluster;
  */
 @SPI(Cluster.DEFAULT)
 public interface Cluster {
-    String DEFAULT = FailoverCluster.NAME;
+
+    String DEFAULT = "failover";
 
     /**
      * Merge the directory invokers to a virtual invoker.
@@ -56,4 +56,4 @@ public interface Cluster {
         }
         return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap);
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
index 0321113..b9935fc 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
@@ -106,4 +106,10 @@ public interface Constants {
     String PEER_KEY = "peer";
 
     String CONSUMER_URL_KEY = "CONSUMER_URL";
+
+    /**
+     * prefix of arguments router key
+     */
+    String ARGUMENTS = "arguments";
+
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
index a895677..f231036 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
@@ -16,16 +16,6 @@
  */
 package org.apache.dubbo.rpc.cluster;
 
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.stream.Collectors;
-
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.common.extension.ExtensionLoader;
@@ -44,6 +34,18 @@ import org.apache.dubbo.rpc.cluster.router.state.RouterCache;
 import org.apache.dubbo.rpc.cluster.router.state.StateRouter;
 import org.apache.dubbo.rpc.cluster.router.state.StateRouterFactory;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+import static org.apache.dubbo.rpc.cluster.Constants.ROUTER_KEY;
+
 /**
  * Router chain
  */
@@ -85,7 +87,7 @@ public class RouterChain<T> {
     private RouterChain(URL url) {
         loopPool = executorRepository.nextExecutorExecutor();
         List<RouterFactory> extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class)
-            .getActivateExtension(url, "router");
+            .getActivateExtension(url, ROUTER_KEY);
 
         List<Router> routers = extensionFactories.stream()
             .map(factory -> factory.getRouter(url))
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
index 4f27b08..751d284 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/AbstractConfigurator.java
@@ -47,6 +47,8 @@ import static org.apache.dubbo.rpc.cluster.Constants.OVERRIDE_PROVIDERS_KEY;
  */
 public abstract class AbstractConfigurator implements Configurator {
 
+    private static final String TILDE = "~";
+
     private final URL configuratorUrl;
 
     public AbstractConfigurator(URL url) {
@@ -76,7 +78,8 @@ public abstract class AbstractConfigurator implements Configurator {
             String configuratorSide = configuratorUrl.getSide();
             if (currentSide.equals(configuratorSide) && CONSUMER.equals(configuratorSide) && 0 == configuratorUrl.getPort()) {
                 url = configureIfMatch(NetUtils.getLocalHost(), url);
-            } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) && url.getPort() == configuratorUrl.getPort()) {
+            } else if (currentSide.equals(configuratorSide) && PROVIDER.equals(configuratorSide) &&
+                    url.getPort() == configuratorUrl.getPort()) {
                 url = configureIfMatch(url.getHost(), url);
             }
         }
@@ -137,10 +140,13 @@ public abstract class AbstractConfigurator implements Configurator {
                     for (Map.Entry<String, String> entry : configuratorUrl.getParameters().entrySet()) {
                         String key = entry.getKey();
                         String value = entry.getValue();
-                        if (key.startsWith("~") || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
-                            conditionKeys.add(key);
+                        boolean startWithTilde = startWithTilde(key);
+                        if (startWithTilde || APPLICATION_KEY.equals(key) || SIDE_KEY.equals(key)) {
+                            if (startWithTilde) {
+                                conditionKeys.add(key);
+                            }
                             if (value != null && !ANY_VALUE.equals(value)
-                                    && !value.equals(url.getParameter(key.startsWith("~") ? key.substring(1) : key))) {
+                                    && !value.equals(url.getParameter(startWithTilde ? key.substring(1) : key))) {
                                 return url;
                             }
                         }
@@ -152,6 +158,13 @@ public abstract class AbstractConfigurator implements Configurator {
         return url;
     }
 
+    private boolean startWithTilde(String key) {
+        if (StringUtils.isNotEmpty(key) && key.startsWith(TILDE)) {
+            return true;
+        }
+        return false;
+    }
+
     protected abstract URL doConfigure(URL currentUrl, URL configUrl);
 
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java
index 26b907d..76aaf39 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/configurator/parser/ConfigParser.java
@@ -90,12 +90,14 @@ public class ConfigParser {
 
             parseEnabled(item, config, urlBuilder);
 
-            urlBuilder.append("&category=").append(DYNAMIC_CONFIGURATORS_CATEGORY);
             urlBuilder.append("&configVersion=").append(config.getConfigVersion());
 
             List<String> apps = item.getApplications();
             if (CollectionUtils.isNotEmpty(apps)) {
-                apps.forEach(app -> urls.add(URL.valueOf(urlBuilder.append("&application=").append(app).toString())));
+                apps.forEach(app -> {
+                    StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
+                    urls.add(URL.valueOf(tmpUrlBuilder.append("&application=").append(app).toString()));
+                });
             } else {
                 urls.add(URL.valueOf(urlBuilder.toString()));
             }
@@ -118,17 +120,18 @@ public class ConfigParser {
                 services.add("*");
             }
             for (String s : services) {
-                urlBuilder.append(appendService(s));
-                urlBuilder.append(toParameterString(item));
+                StringBuilder tmpUrlBuilder = new StringBuilder(urlBuilder);
+                tmpUrlBuilder.append(appendService(s));
+                tmpUrlBuilder.append(toParameterString(item));
 
-                urlBuilder.append("&application=").append(config.getKey());
+                tmpUrlBuilder.append("&application=").append(config.getKey());
 
-                parseEnabled(item, config, urlBuilder);
+                parseEnabled(item, config, tmpUrlBuilder);
 
-                urlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
-                urlBuilder.append("&configVersion=").append(config.getConfigVersion());
+                tmpUrlBuilder.append("&category=").append(APP_DYNAMIC_CONFIGURATORS_CATEGORY);
+                tmpUrlBuilder.append("&configVersion=").append(config.getConfigVersion());
 
-                urls.add(URL.valueOf(urlBuilder.toString()));
+                urls.add(URL.valueOf(tmpUrlBuilder.toString()));
             }
         }
         return urls;
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 a8e5e18..aaa604f 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
@@ -35,7 +35,7 @@ public interface GovernanceRuleRepository {
     }
 
 
-    /*
+    /**
      * {@link #removeListener(String, String, ConfigurationListener)}
      *
      * @param key      the key to represent a configuration
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
index 855521f..4f5859d 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/ConsistentHashLoadBalance.java
@@ -17,13 +17,11 @@
 package org.apache.dubbo.rpc.cluster.loadbalance;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.io.Bytes;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.support.RpcUtils;
 
-import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -88,7 +86,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
             for (Invoker<T> invoker : invokers) {
                 String address = invoker.getUrl().getAddress();
                 for (int i = 0; i < replicaNumber / 4; i++) {
-                    byte[] digest = md5(address + i);
+                    byte[] digest = Bytes.getMD5(address + i);
                     for (int h = 0; h < 4; h++) {
                         long m = hash(digest, h);
                         virtualInvokers.put(m, invoker);
@@ -99,7 +97,7 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
 
         public Invoker<T> select(Invocation invocation) {
             String key = toKey(invocation.getArguments());
-            byte[] digest = md5(key);
+            byte[] digest = Bytes.getMD5(key);
             return selectForKey(hash(digest, 0));
         }
 
@@ -128,20 +126,6 @@ public class ConsistentHashLoadBalance extends AbstractLoadBalance {
                     | (digest[number * 4] & 0xFF))
                     & 0xFFFFFFFFL;
         }
-
-        private byte[] md5(String value) {
-            MessageDigest md5;
-            try {
-                md5 = MessageDigest.getInstance("MD5");
-            } catch (NoSuchAlgorithmException e) {
-                throw new IllegalStateException(e.getMessage(), e);
-            }
-            md5.reset();
-            byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
-            md5.update(bytes);
-            return md5.digest();
-        }
-
     }
 
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
index adfd04b..50215d6 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/loadbalance/RandomLoadBalance.java
@@ -49,20 +49,17 @@ public class RandomLoadBalance extends AbstractLoadBalance {
         int length = invokers.size();
         // Every invoker has the same weight?
         boolean sameWeight = true;
-        // the weight of every invokers
+        // the maxWeight of every invokers, the minWeight = 0 or the maxWeight of the last invoker
         int[] weights = new int[length];
-        // the first invoker's weight
-        int firstWeight = getWeight(invokers.get(0), invocation);
-        weights[0] = firstWeight;
         // The sum of weights
-        int totalWeight = firstWeight;
-        for (int i = 1; i < length; i++) {
+        int totalWeight = 0;
+        for (int i = 0; i < length; i++) {
             int weight = getWeight(invokers.get(i), invocation);
-            // save for later use
-            weights[i] = weight;
             // Sum
             totalWeight += weight;
-            if (sameWeight && weight != firstWeight) {
+            // save for later use
+            weights[i] = totalWeight;
+            if (sameWeight && totalWeight != weight * (i + 1)) {
                 sameWeight = false;
             }
         }
@@ -71,8 +68,7 @@ public class RandomLoadBalance extends AbstractLoadBalance {
             int offset = ThreadLocalRandom.current().nextInt(totalWeight);
             // Return a invoker based on the random value.
             for (int i = 0; i < length; i++) {
-                offset -= weights[i];
-                if (offset < 0) {
+                if (offset < weights[i]) {
                     return invokers.get(i);
                 }
             }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
index dbf32fd..f6cfec2 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
@@ -26,6 +26,7 @@ import org.apache.dubbo.common.utils.UrlUtils;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Constants;
 import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
 
 import java.text.ParseException;
@@ -50,13 +51,18 @@ import static org.apache.dubbo.rpc.cluster.Constants.RUNTIME_KEY;
 
 /**
  * ConditionRouter
- *
+ * It supports the conditional routing configured by "override://", in 2.6.x,
+ * refer to https://dubbo.apache.org/en/docs/v2.7/user/examples/routing-rule/ .
+ * For 2.7.x and later, please refer to {@link org.apache.dubbo.rpc.cluster.router.condition.config.ServiceRouter}
+ * and {@link org.apache.dubbo.rpc.cluster.router.condition.config.AppRouter}
+ * refer to https://dubbo.apache.org/zh/docs/v2.7/user/examples/routing-rule/ .
  */
 public class ConditionRouter extends AbstractRouter {
     public static final String NAME = "condition";
 
     private static final Logger logger = LoggerFactory.getLogger(ConditionRouter.class);
     protected static final Pattern ROUTE_PATTERN = Pattern.compile("([&!=,]*)\\s*([^&!=,\\s]+)");
+    protected static Pattern ARGUMENTS_PATTERN = Pattern.compile("arguments\\[([0-9]+)\\]");
     protected Map<String, MatchPair> whenCondition;
     protected Map<String, MatchPair> thenCondition;
 
@@ -65,7 +71,9 @@ public class ConditionRouter extends AbstractRouter {
     public ConditionRouter(String rule, boolean force, boolean enabled) {
         this.force = force;
         this.enabled = enabled;
-        this.init(rule);
+        if (enabled) {
+            this.init(rule);
+        }
     }
 
     public ConditionRouter(URL url) {
@@ -73,7 +81,9 @@ public class ConditionRouter extends AbstractRouter {
         this.priority = url.getParameter(PRIORITY_KEY, 0);
         this.force = url.getParameter(FORCE_KEY, false);
         this.enabled = url.getParameter(ENABLED_KEY, true);
-        init(url.getParameterAndDecoded(RULE_KEY));
+        if (enabled) {
+            init(url.getParameterAndDecoded(RULE_KEY));
+        }
     }
 
     public void init(String rule) {
@@ -226,6 +236,16 @@ public class ConditionRouter extends AbstractRouter {
         boolean result = false;
         for (Map.Entry<String, MatchPair> matchPair : condition.entrySet()) {
             String key = matchPair.getKey();
+
+            if (key.startsWith(Constants.ARGUMENTS)) {
+                if (!matchArguments(matchPair, invocation)) {
+                    return false;
+                } else {
+                    result = true;
+                    continue;
+                }
+            }
+
             String sampleValue;
             //get real invoked method name from invocation
             if (invocation != null && (METHOD_KEY.equals(key) || METHODS_KEY.equals(key))) {
@@ -258,6 +278,45 @@ public class ConditionRouter extends AbstractRouter {
         return result;
     }
 
+    /**
+     * analysis the arguments in the rule.
+     * Examples would be like this:
+     * "arguments[0]=1", whenCondition is that the first argument is equal to '1'.
+     * "arguments[1]=a", whenCondition is that the second argument is equal to 'a'.
+     * @param matchPair
+     * @param invocation
+     * @return
+     */
+    public boolean matchArguments(Map.Entry<String, MatchPair> matchPair, Invocation invocation) {
+        try {
+            // split the rule
+            String key = matchPair.getKey();
+            String[] expressArray = key.split("\\.");
+            String argumentExpress = expressArray[0];
+            final Matcher matcher = ARGUMENTS_PATTERN.matcher(argumentExpress);
+            if (!matcher.find()) {
+                return false;
+            }
+
+            //extract the argument index
+            int index = Integer.parseInt(matcher.group(1));
+            if (index < 0 || index > invocation.getArguments().length) {
+                return false;
+            }
+
+            //extract the argument value
+            Object object = invocation.getArguments()[index];
+
+            if (matchPair.getValue().isMatch(String.valueOf(object), null)) {
+                return true;
+            }
+        } catch (Exception e) {
+            logger.warn("Arguments match failed, matchPair[]" + matchPair + "] invocation[" + invocation + "]", e);
+        }
+
+        return false;
+    }
+
     protected static final class MatchPair {
         final Set<String> matches = new HashSet<String>();
         final Set<String> mismatches = new HashSet<String>();
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
index a616d8d..7701c4c 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterFactory.java
@@ -22,7 +22,7 @@ import org.apache.dubbo.rpc.cluster.RouterFactory;
 
 /**
  * ConditionRouterFactory
- *
+ * Load when "override://" is configured {@link ConditionRouter}
  */
 public class ConditionRouterFactory implements RouterFactory {
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
index 690ebf9..b0bfdc6 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
@@ -33,7 +33,6 @@ import org.apache.dubbo.rpc.cluster.router.AbstractRouter;
 import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule;
 import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
 
-import java.net.UnknownHostException;
 import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -160,7 +159,7 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
      * @return
      */
     private <T> List<Invoker<T>> filterUsingStaticTag(List<Invoker<T>> invokers, URL url, Invocation invocation) {
-        List<Invoker<T>> result = invokers;
+        List<Invoker<T>> result;
         // Dynamic param
         String tag = StringUtils.isEmpty(invocation.getAttachment(TAG_KEY)) ? url.getParameter(TAG_KEY) :
                 invocation.getAttachment(TAG_KEY);
@@ -188,19 +187,11 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
     }
 
     private boolean isForceUseTag(Invocation invocation) {
-        return Boolean.valueOf(invocation.getAttachment(FORCE_USE_TAG, url.getParameter(FORCE_USE_TAG, "false")));
+        return Boolean.parseBoolean(invocation.getAttachment(FORCE_USE_TAG, url.getParameter(FORCE_USE_TAG, "false")));
     }
 
     private <T> List<Invoker<T>> filterInvoker(List<Invoker<T>> invokers, Predicate<Invoker<T>> predicate) {
-        boolean filter = false;
-        for (int i = 0; i < invokers.size(); ++i) {
-            Invoker<T> invoker = invokers.get(i);
-            if (!predicate.test(invoker)) {
-                filter = true;
-                break;
-            }
-        }
-        if (!filter) {
+        if (invokers.stream().allMatch(predicate)) {
             return invokers;
         }
 
@@ -226,8 +217,6 @@ public class TagRouter extends AbstractRouter implements ConfigurationListener {
                 if ((ANYHOST_VALUE + ":" + port).equals(address)) {
                     return true;
                 }
-            } catch (UnknownHostException e) {
-                logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
             } catch (Exception e) {
                 logger.error("The format of ip address is invalid in tag route. Address :" + address, e);
             }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
index 450fa91..268140a 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/BroadcastClusterInvoker.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.rpc.cluster.support;
 
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.rpc.Invocation;
@@ -30,11 +31,13 @@ import java.util.List;
 
 /**
  * BroadcastClusterInvoker
- *
  */
 public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
 
     private static final Logger logger = LoggerFactory.getLogger(BroadcastClusterInvoker.class);
+    private static final String BROADCAST_FAIL_PERCENT_KEY = "broadcast.fail.percent";
+    private static final int MAX_BROADCAST_FAIL_PERCENT = 100;
+    private static final int MIN_BROADCAST_FAIL_PERCENT = 0;
 
     public BroadcastClusterInvoker(Directory<T> directory) {
         super(directory);
@@ -47,21 +50,67 @@ public class BroadcastClusterInvoker<T> extends AbstractClusterInvoker<T> {
         RpcContext.getServiceContext().setInvokers((List) invokers);
         RpcException exception = null;
         Result result = null;
+        URL url = getUrl();
+        // The value range of broadcast.fail.threshold must be 0~100.
+        // 100 means that an exception will be thrown last, and 0 means that as long as an exception occurs, it will be thrown.
+        // see https://github.com/apache/dubbo/pull/7174
+        int broadcastFailPercent = url.getParameter(BROADCAST_FAIL_PERCENT_KEY, MAX_BROADCAST_FAIL_PERCENT);
+
+        if (broadcastFailPercent < MIN_BROADCAST_FAIL_PERCENT || broadcastFailPercent > MAX_BROADCAST_FAIL_PERCENT) {
+            logger.info(String.format("The value corresponding to the broadcast.fail.percent parameter must be between 0 and 100. " +
+                    "The current setting is %s, which is reset to 100.", broadcastFailPercent));
+            broadcastFailPercent = MAX_BROADCAST_FAIL_PERCENT;
+        }
+
+        int failThresholdIndex = invokers.size() * broadcastFailPercent / MAX_BROADCAST_FAIL_PERCENT;
+        int failIndex = 0;
         for (Invoker<T> invoker : invokers) {
             try {
                 result = invokeWithContext(invoker, invocation);
-            } catch (RpcException e) {
-                exception = e;
-                logger.warn(e.getMessage(), e);
+                if (null != result && result.hasException()) {
+                    Throwable resultException = result.getException();
+                    if (null != resultException) {
+                        exception = getRpcException(result.getException());
+                        logger.warn(exception.getMessage(), exception);
+                        if (failIndex == failThresholdIndex) {
+                            break;
+                        } else {
+                            failIndex++;
+                        }
+                    }
+                }
             } catch (Throwable e) {
-                exception = new RpcException(e.getMessage(), e);
-                logger.warn(e.getMessage(), e);
+                exception = getRpcException(e);
+                logger.warn(exception.getMessage(), exception);
+                if (failIndex == failThresholdIndex) {
+                    break;
+                } else {
+                    failIndex++;
+                }
             }
         }
+
         if (exception != null) {
+            if (failIndex == failThresholdIndex) {
+                logger.debug(
+                        String.format("The number of BroadcastCluster call failures has reached the threshold %s", failThresholdIndex));
+            } else {
+                logger.debug(String.format("The number of BroadcastCluster call failures has not reached the threshold %s, fail size is %s",
+                        failIndex));
+            }
             throw exception;
         }
+
         return result;
     }
 
+    private RpcException getRpcException(Throwable throwable) {
+        RpcException rpcException = null;
+        if (throwable instanceof RpcException) {
+            rpcException = (RpcException) throwable;
+        } else {
+            rpcException = new RpcException(throwable.getMessage(), throwable);
+        }
+        return rpcException;
+    }
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
index b7a30ed..72def11 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java
@@ -29,6 +29,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
 import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
@@ -90,6 +91,9 @@ public class ClusterUtils {
             if(map.containsKey(VERSION_KEY)){
                 copyOfLocalMap.remove(VERSION_KEY);
             }
+            if (map.containsKey(GENERIC_KEY)) {
+                copyOfLocalMap.remove(GENERIC_KEY);
+            }
 
             copyOfLocalMap.remove(RELEASE_KEY);
             copyOfLocalMap.remove(DUBBO_VERSION_KEY);
@@ -99,20 +103,22 @@ public class ClusterUtils {
 
             map.putAll(copyOfLocalMap);
 
-            map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY));
+            if (remoteMap != null) {
+                map.put(REMOTE_APPLICATION_KEY, remoteMap.get(APPLICATION_KEY));
 
-            // Combine filters and listeners on Provider and Consumer
-            String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
-            String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
-            if (remoteFilter != null && remoteFilter.length() > 0
-                    && localFilter != null && localFilter.length() > 0) {
-                map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
-            }
-            String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
-            String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
-            if (remoteListener != null && remoteListener.length() > 0
-                    && localListener != null && localListener.length() > 0) {
-                map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
+                // Combine filters and listeners on Provider and Consumer
+                String remoteFilter = remoteMap.get(REFERENCE_FILTER_KEY);
+                String localFilter = copyOfLocalMap.get(REFERENCE_FILTER_KEY);
+                if (remoteFilter != null && remoteFilter.length() > 0
+                        && localFilter != null && localFilter.length() > 0) {
+                    map.put(REFERENCE_FILTER_KEY, remoteFilter + "," + localFilter);
+                }
+                String remoteListener = remoteMap.get(INVOKER_LISTENER_KEY);
+                String localListener = copyOfLocalMap.get(INVOKER_LISTENER_KEY);
+                if (remoteListener != null && remoteListener.length() > 0
+                        && localListener != null && localListener.length() > 0) {
+                    map.put(INVOKER_LISTENER_KEY, remoteListener + "," + localListener);
+                }
             }
         }
 
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
index 414deaa..a445d36 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvoker.java
@@ -58,10 +58,7 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
         List<Invoker<T>> copyInvokers = invokers;
         checkInvokers(copyInvokers, invocation);
         String methodName = RpcUtils.getMethodName(invocation);
-        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
-        if (len <= 0) {
-            len = 1;
-        }
+        int len = calculateInvokeTimes(methodName);
         // retry loop.
         RpcException le = null; // last exception.
         List<Invoker<T>> invoked = new ArrayList<Invoker<T>>(copyInvokers.size()); // invoked invokers.
@@ -113,4 +110,19 @@ public class FailoverClusterInvoker<T> extends AbstractClusterInvoker<T> {
                 + le.getMessage(), le.getCause() != null ? le.getCause() : le);
     }
 
+    private int calculateInvokeTimes(String methodName) {
+        int len = getUrl().getMethodParameter(methodName, RETRIES_KEY, DEFAULT_RETRIES) + 1;
+        RpcContext rpcContext = RpcContext.getClientAttachment();
+        Object retry = rpcContext.getObjectAttachment(RETRIES_KEY);
+        if (retry instanceof Number) {
+            len = ((Number) retry).intValue() + 1;
+            rpcContext.removeAttachment(RETRIES_KEY);
+        }
+        if (len <= 0) {
+            len = 1;
+        }
+
+        return len;
+    }
+
 }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
index 7bc1f94..95a7bd2 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java
@@ -113,7 +113,7 @@ public class MergeableClusterInvoker<T> extends AbstractClusterInvoker<T> {
         if (resultList.isEmpty()) {
             return AsyncRpcResult.newDefaultAsyncResult(invocation);
         } else if (resultList.size() == 1) {
-            return resultList.iterator().next();
+            return AsyncRpcResult.newDefaultAsyncResult(resultList.get(0).getValue(), invocation);
         }
 
         if (returnType == void.class) {
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
index f5043e3..97b7a0b 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/registry/ZoneAwareClusterInvoker.java
@@ -33,7 +33,6 @@ import java.util.List;
 import java.util.stream.Collectors;
 
 import static org.apache.dubbo.common.constants.CommonConstants.PREFERRED_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_FORCE;
 import static org.apache.dubbo.common.constants.RegistryConstants.ZONE_KEY;
@@ -62,7 +61,7 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
         for (Invoker<T> invoker : invokers) {
             ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
             if (clusterInvoker.isAvailable() && clusterInvoker.getRegistryUrl()
-                    .getParameter(REGISTRY_KEY + "." + PREFERRED_KEY, false)) {
+                    .getParameter(PREFERRED_KEY, false)) {
                 return clusterInvoker.invoke(invocation);
             }
         }
@@ -72,7 +71,7 @@ public class ZoneAwareClusterInvoker<T> extends AbstractClusterInvoker<T> {
         if (StringUtils.isNotEmpty(zone)) {
             for (Invoker<T> invoker : invokers) {
                 ClusterInvoker<T> clusterInvoker = (ClusterInvoker<T>) invoker;
-                if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(REGISTRY_KEY + "." + ZONE_KEY))) {
+                if (clusterInvoker.isAvailable() && zone.equals(clusterInvoker.getRegistryUrl().getParameter(ZONE_KEY))) {
                     return clusterInvoker.invoke(invocation);
                 }
             }
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 1c2d047..684f372 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
@@ -256,7 +256,7 @@ public abstract class AbstractCluster implements Cluster {
 
         @Override
         protected Result doInvoke(Invocation invocation, List<Invoker<T>> invokers, LoadBalance loadbalance) throws RpcException {
-            // The only purpose is to build a interceptor chain, so the cluster related logic doesn't matter.
+            // The only purpose is to build an interceptor chain, so the cluster related logic doesn't matter.
             return null;
         }
     }
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
index a682297..51d0a49 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/MockClusterInvoker.java
@@ -162,7 +162,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
     /**
      * Return MockInvoker
      * Contract:
-     * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is present in invocation, otherwise, a list of mock invokers will return.
+     * directory.list() will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
      * if directory.list() returns more than one mock invoker, only one of them will be used.
      *
      * @param invocation
@@ -174,7 +174,7 @@ public class MockClusterInvoker<T> implements ClusterInvoker<T> {
         if (invocation instanceof RpcInvocation) {
             //Note the implicit contract (although the description is added to the interface declaration, but extensibility is a problem. The practice placed in the attachment needs to be improved)
             ((RpcInvocation) invocation).setAttachment(INVOCATION_NEED_MOCK, Boolean.TRUE.toString());
-            //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is present in invocation, otherwise, a list of mock invokers will return.
+            //directory will return a list of normal invokers if Constants.INVOCATION_NEED_MOCK is absent or not true in invocation, otherwise, a list of mock invokers will return.
             try {
                 invokers = directory.list(invocation);
             } catch (RpcException e) {
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
index 8d77aa4..bb6260c 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/loadbalance/RoundRobinLoadBalanceTest.java
@@ -131,13 +131,7 @@ public class RoundRobinLoadBalanceTest extends LoadBalanceBaseTest {
                 recycleTimeField = RoundRobinLoadBalance.class.getDeclaredField("RECYCLE_PERIOD");
                 recycleTimeField.setAccessible(true);
                 recycleTimeField.setInt(RoundRobinLoadBalance.class, 10);
-            } catch (NoSuchFieldException e) {
-                Assertions.assertTrue(true, "getField failed");
-            } catch (SecurityException e) {
-                Assertions.assertTrue(true, "getField failed");
-            } catch (IllegalArgumentException e) {
-                Assertions.assertTrue(true, "getField failed");
-            } catch (IllegalAccessException e) {
+            } catch (NoSuchFieldException | IllegalAccessException | IllegalArgumentException | SecurityException e) {
                 Assertions.assertTrue(true, "getField failed");
             }
         }
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
index 204ce9a..4637976 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouterTest.java
@@ -311,4 +311,38 @@ public class ConditionRouterTest {
         Assertions.assertEquals(0, filteredInvokers.size());
     }
 
+    @Test
+    public void testRoute_Arguments() {
+        Router router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0] = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        List<Invoker<String>> invokers = new ArrayList<>();
+        Invoker<String> invoker1 = new MockInvoker<>(URL.valueOf("dubbo://10.20.3.3:20880/com.foo.BarService"));
+        Invoker<String> invoker2 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        Invoker<String> invoker3 = new MockInvoker<>(URL.valueOf("dubbo://" + LOCAL_HOST + ":20880/com.foo.BarService"));
+        invokers.add(invoker1);
+        invokers.add(invoker2);
+        invokers.add(invoker3);
+        RpcInvocation invocation = new RpcInvocation();
+        String p = "a";
+        invocation.setArguments(new Object[]{null});
+        List<Invoker<String>> fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        invocation.setArguments(new Object[]{p});
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(0, fileredInvokers.size());
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments = b " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[10].inner = a " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(3, fileredInvokers.size());
+
+        int integer = 1;
+        invocation.setArguments(new Object[]{integer});
+        router = new ConditionRouterFactory().getRouter(getRouteUrl("arguments[0].inner = 1 " + " => " + " host = 1.2.3.4").addParameter(FORCE_KEY, String.valueOf(true)));
+        fileredInvokers = router.route(invokers, URL.valueOf("consumer://" + LOCAL_HOST + "/com.foo.BarService"), invocation);
+        Assertions.assertEquals(0, fileredInvokers.size());
+    }
 }
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
index 613a527..a162526 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/FailoverClusterInvokerTest.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.rpc.AsyncRpcResult;
 import org.apache.dubbo.rpc.Invocation;
 import org.apache.dubbo.rpc.Invoker;
 import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcContext;
 import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.rpc.RpcInvocation;
 import org.apache.dubbo.rpc.cluster.Directory;
@@ -143,6 +144,33 @@ public class FailoverClusterInvokerTest {
     }
 
     @Test()
+    public void testInvoke_retryTimes2() {
+        int finalRetries = 1;
+        given(invoker1.invoke(invocation)).willThrow(new RpcException(RpcException.TIMEOUT_EXCEPTION));
+        given(invoker1.isAvailable()).willReturn(false);
+        given(invoker1.getUrl()).willReturn(url);
+        given(invoker1.getInterface()).willReturn(FailoverClusterInvokerTest.class);
+
+        given(invoker2.invoke(invocation)).willThrow(new RpcException());
+        given(invoker2.isAvailable()).willReturn(false);
+        given(invoker2.getUrl()).willReturn(url);
+        given(invoker2.getInterface()).willReturn(FailoverClusterInvokerTest.class);
+
+        RpcContext rpcContext = RpcContext.getContext();
+        rpcContext.setAttachment("retries", finalRetries);
+
+        FailoverClusterInvoker<FailoverClusterInvokerTest> invoker = new FailoverClusterInvoker<FailoverClusterInvokerTest>(dic);
+        try {
+            Result ret = invoker.invoke(invocation);
+            assertSame(result, ret);
+            fail();
+        } catch (RpcException expected) {
+            assertTrue((expected.isTimeout() || expected.getCode() == 0));
+            assertTrue(expected.getMessage().indexOf((finalRetries+1) + " times") > 0);
+        }
+    }
+
+    @Test()
     public void testNoInvoke() {
         dic = mock(Directory.class);
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/BaseServiceMetadata.java b/dubbo-common/src/main/java/org/apache/dubbo/common/BaseServiceMetadata.java
index f8a6516..9c04f9a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/BaseServiceMetadata.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/BaseServiceMetadata.java
@@ -18,11 +18,13 @@ package org.apache.dubbo.common;
 
 import org.apache.dubbo.common.utils.StringUtils;
 
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
+
 /**
  * 2019-10-10
  */
 public class BaseServiceMetadata {
-    public static final char COLON_SEPERATOR = ':';
+    public static final char COLON_SEPARATOR = ':';
 
     protected String serviceKey;
     protected String serviceInterfaceName;
@@ -48,7 +50,7 @@ public class BaseServiceMetadata {
     public static String versionFromServiceKey(String serviceKey) {
         int index = serviceKey.indexOf(":");
         if (index == -1) {
-            return null;
+            return DEFAULT_VERSION;
         }
         return serviceKey.substring(index + 1);
     }
@@ -77,7 +79,7 @@ public class BaseServiceMetadata {
     public String getDisplayServiceKey() {
         StringBuilder serviceNameBuilder = new StringBuilder();
         serviceNameBuilder.append(serviceInterfaceName);
-        serviceNameBuilder.append(COLON_SEPERATOR).append(version);
+        serviceNameBuilder.append(COLON_SEPARATOR).append(version);
         return serviceNameBuilder.toString();
     }
 
@@ -88,7 +90,7 @@ public class BaseServiceMetadata {
      * @return
      */
     public static BaseServiceMetadata revertDisplayServiceKey(String displayKey) {
-        String[] eles = StringUtils.split(displayKey, COLON_SEPERATOR);
+        String[] eles = StringUtils.split(displayKey, COLON_SEPARATOR);
         if (eles == null || eles.length < 1 || eles.length > 2) {
             return new BaseServiceMetadata();
         }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
index 90e3415..790c476 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Parameters.java
@@ -244,6 +244,9 @@ public class Parameters {
 
     @Override
     public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
         return parameters.equals(o);
     }
 
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 96383df..404fd72 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
@@ -48,7 +48,7 @@ import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Predicate;
 
-import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPERATOR;
+import static org.apache.dubbo.common.BaseServiceMetadata.COLON_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
@@ -1281,7 +1281,7 @@ class URL implements Serializable {
             return getServiceInterface();
         }
         return getServiceInterface() +
-                COLON_SEPERATOR + getVersion();
+                COLON_SEPARATOR + getVersion();
     }
 
     /**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URLStrParser.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URLStrParser.java
index 3ca1246..1b45b1f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/URLStrParser.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URLStrParser.java
@@ -221,7 +221,7 @@ public final class URLStrParser {
      */
     public static URL parseEncodedStr(String encodedURLStr, boolean modifiable) {
         Map<String, String> parameters = null;
-        int pathEndIdx = encodedURLStr.indexOf("%3F");// '?'
+        int pathEndIdx = encodedURLStr.toUpperCase().indexOf("%3F");// '?'
         if (pathEndIdx >= 0) {
             parameters = parseEncodedParams(encodedURLStr, pathEndIdx + 3);
         } else {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
index c6610cb..0b3da94 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beanutil/JavaBeanSerializeUtil.java
@@ -349,7 +349,7 @@ public final class JavaBeanSerializeUtil {
             }
         }
 
-        return cl.newInstance();
+        return cl.getDeclaredConstructor().newInstance();
     }
 
     public static Object getConstructorArg(Class<?> cl) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
index b81b7a3..252c3aa 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
@@ -340,9 +340,7 @@ public final class ClassGenerator {
             return mCtc.toClass(loader, pd);
         } catch (RuntimeException e) {
             throw e;
-        } catch (NotFoundException e) {
-            throw new RuntimeException(e.getMessage(), e);
-        } catch (CannotCompileException e) {
+        } catch (NotFoundException | CannotCompileException e) {
             throw new RuntimeException(e.getMessage(), e);
         }
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java
index 4afc886..e5f639d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/CustomizedLoaderClassPath.java
@@ -49,8 +49,9 @@ public class CustomizedLoaderClassPath implements ClassPath {
 
     public String toString() {
         Object cl = null;
-        if (clref != null)
+        if (clref != null) {
             cl = clref.get();
+        }
 
         return cl == null ? "<null>" : cl.toString();
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
index f7a8423..cd16d38 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Mixin.java
@@ -174,7 +174,7 @@ public abstract class Mixin {
             ccm.setSuperClass(Mixin.class.getName());
             ccm.addMethod("public Object newInstance(Object[] delegates){ return new " + micn + "($1); }");
             Class<?> mixin = ccm.toClass();
-            return (Mixin) mixin.newInstance();
+            return (Mixin) mixin.getDeclaredConstructor().newInstance();
         } catch (RuntimeException e) {
             throw e;
         } catch (Exception e) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
index c7fc5b2..4c435a8 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
@@ -187,9 +187,6 @@ public abstract class Proxy {
                     if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
                         continue;
                     }
-                    if (ics[i].isInterface() && Modifier.isStatic(method.getModifiers())) {
-                        continue;
-                    }
                     worked.add(desc);
 
                     int ix = methods.size();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
index 8f52a34..11257e9 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Wrapper.java
@@ -19,11 +19,15 @@ package org.apache.dubbo.common.bytecode;
 import org.apache.dubbo.common.utils.ClassUtils;
 import org.apache.dubbo.common.utils.ReflectUtils;
 
+import javassist.ClassPool;
+import javassist.CtMethod;
+
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -31,6 +35,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.regex.Matcher;
+import java.util.stream.Collectors;
 
 /**
  * Wrapper.
@@ -113,7 +118,7 @@ public abstract class Wrapper {
             return OBJECT_WRAPPER;
         }
 
-        return WRAPPER_MAP.computeIfAbsent(c, key -> makeWrapper(key));
+        return WRAPPER_MAP.computeIfAbsent(c, Wrapper::makeWrapper);
     }
 
     private static Wrapper makeWrapper(Class<?> c) {
@@ -150,10 +155,32 @@ public abstract class Wrapper {
             pts.put(fn, ft);
         }
 
-        Method[] methods = c.getMethods();
+        final ClassPool classPool = new ClassPool(ClassPool.getDefault());
+        classPool.appendClassPath(new CustomizedLoaderClassPath(cl));
+
+        List<String> allMethod = new ArrayList<>();
+        try {
+            final CtMethod[] ctMethods = classPool.get(c.getName()).getMethods();
+            for (CtMethod method : ctMethods) {
+                allMethod.add(ReflectUtils.getDesc(method));
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+
+        Method[] methods = Arrays.stream(c.getMethods())
+                                 .filter(method -> allMethod.contains(ReflectUtils.getDesc(method)))
+                                 .collect(Collectors.toList())
+                                 .toArray(new Method[] {});
         // get all public method.
         boolean hasMethod = hasMethods(methods);
         if (hasMethod) {
+            Map<String, Integer> sameNameMethodCount = new HashMap<>((int) (methods.length / 0.75f) + 1);
+            for (Method m : methods) {
+                sameNameMethodCount.compute(m.getName(),
+                        (key, oldValue) -> oldValue == null ? 1 : oldValue + 1);
+            }
+
             c3.append(" try{");
             for (Method m : methods) {
                 //ignore Object's method.
@@ -166,14 +193,8 @@ public abstract class Wrapper {
                 int len = m.getParameterTypes().length;
                 c3.append(" && ").append(" $3.length == ").append(len);
 
-                boolean override = false;
-                for (Method m2 : methods) {
-                    if (m != m2 && m.getName().equals(m2.getName())) {
-                        override = true;
-                        break;
-                    }
-                }
-                if (override) {
+                boolean overload = sameNameMethodCount.get(m.getName()) > 1;
+                if (overload) {
                     if (len > 0) {
                         for (int l = 0; l < len; l++) {
                             c3.append(" && ").append(" $3[").append(l).append("].getName().equals(\"")
@@ -226,7 +247,7 @@ public abstract class Wrapper {
             }
         }
         c1.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
-        c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or setter method in class " + c.getName() + ".\"); }");
+        c2.append(" throw new " + NoSuchPropertyException.class.getName() + "(\"Not found property \\\"\"+$2+\"\\\" field or getter method in class " + c.getName() + ".\"); }");
 
         // make class
         long id = WRAPPER_CLASS_COUNTER.getAndIncrement();
@@ -263,7 +284,7 @@ public abstract class Wrapper {
             for (Method m : ms.values()) {
                 wc.getField("mts" + ix++).set(null, m.getParameterTypes());
             }
-            return (Wrapper) wc.newInstance();
+            return (Wrapper) wc.getDeclaredConstructor().newInstance();
         } catch (RuntimeException e) {
             throw e;
         } catch (Throwable e) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
index 365cb7f..d09afad 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/ClassUtils.java
@@ -22,6 +22,7 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.lang.reflect.Array;
 import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
@@ -48,10 +49,8 @@ public class ClassUtils {
 
     public static Object newInstance(String name) {
         try {
-            return forName(name).newInstance();
-        } catch (InstantiationException e) {
-            throw new IllegalStateException(e.getMessage(), e);
-        } catch (IllegalAccessException e) {
+            return forName(name).getDeclaredConstructor().newInstance();
+        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
             throw new IllegalStateException(e.getMessage(), e);
         }
     }
@@ -64,7 +63,7 @@ public class ClassUtils {
                 for (String pkg : packages) {
                     try {
                         return classForName(pkg + "." + className);
-                    } catch (ClassNotFoundException e2) {
+                    } catch (ClassNotFoundException ignore) {
                     }
                 }
             }
@@ -123,7 +122,7 @@ public class ClassUtils {
             if (className.indexOf('.') == -1) {
                 try {
                     return arrayForName("java.lang." + className);
-                } catch (ClassNotFoundException e2) {
+                } catch (ClassNotFoundException ignore) {
                     // ignore, let the original exception be thrown
                 }
             }
@@ -431,7 +430,7 @@ public class ClassUtils {
         }
         return map;
     }
-    
+
     /**
      * get simple class name from qualified class name
      */
@@ -439,7 +438,6 @@ public class ClassUtils {
         if (null == qualifiedName) {
             return null;
         }
-        
         int i = qualifiedName.lastIndexOf('.');
         return i < 0 ? qualifiedName : qualifiedName.substring(i + 1);
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
index 0dc8f88..7e01df3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/CtClassBuilder.java
@@ -16,11 +16,6 @@
  */
 package org.apache.dubbo.common.compiler.support;
 
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 import javassist.CannotCompileException;
 import javassist.ClassPool;
 import javassist.CtClass;
@@ -30,6 +25,11 @@ import javassist.CtNewMethod;
 import javassist.LoaderClassPath;
 import javassist.NotFoundException;
 
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 /**
  * CtClassBuilder is builder for CtClass
  * <p>
@@ -43,17 +43,17 @@ public class CtClassBuilder {
 
     private String superClassName = "java.lang.Object";
 
-    private List<String> imports = new ArrayList<>();
+    private final List<String> imports = new ArrayList<>();
 
-    private Map<String, String> fullNames = new HashMap<>();
+    private final Map<String, String> fullNames = new HashMap<>();
 
-    private List<String> ifaces = new ArrayList<>();
+    private final List<String> ifaces = new ArrayList<>();
 
-    private List<String> constructors = new ArrayList<>();
+    private final List<String> constructors = new ArrayList<>();
 
-    private List<String> fields = new ArrayList<>();
+    private final List<String> fields = new ArrayList<>();
 
-    private List<String> methods = new ArrayList<>();
+    private final List<String> methods = new ArrayList<>();
 
     public String getClassName() {
         return className;
@@ -146,7 +146,7 @@ public class CtClassBuilder {
         CtClass ctClass = pool.makeClass(className, pool.get(superClassName));
 
         // add imported packages
-        imports.stream().forEach(pool::importPackage);
+        imports.forEach(pool::importPackage);
 
         // add implemented interfaces
         for (String iface : ifaces) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
index 59a764f..c82e48d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/JdkCompiler.java
@@ -61,14 +61,22 @@ public class JdkCompiler extends AbstractCompiler {
 
     private final JavaFileManagerImpl javaFileManager;
 
-    private volatile List<String> options;
+    private final List<String> options;
 
-    public JdkCompiler() {
-        options = new ArrayList<String>();
-        options.add("-source");
-        options.add("1.6");
-        options.add("-target");
-        options.add("1.6");
+    private static final String DEFAULT_JAVA_VERSION = "1.8";
+
+    private static List<String> buildDefaultOptions(String javaVersion) {
+        return Arrays.asList(
+                "-source", javaVersion, "-target", javaVersion
+        );
+    }
+
+    private static List<String> buildDefaultOptions() {
+        return buildDefaultOptions(DEFAULT_JAVA_VERSION);
+    }
+
+    public JdkCompiler(List<String> options) {
+        this.options = new ArrayList<>(options);
         StandardJavaFileManager manager = compiler.getStandardFileManager(diagnosticCollector, null, null);
         final ClassLoader loader = Thread.currentThread().getContextClassLoader();
         if (loader instanceof URLClassLoader
@@ -93,6 +101,14 @@ public class JdkCompiler extends AbstractCompiler {
         javaFileManager = new JavaFileManagerImpl(manager, classLoader);
     }
 
+    public JdkCompiler() {
+        this(buildDefaultOptions());
+    }
+
+    public JdkCompiler(String javaVersion) {
+        this(buildDefaultOptions(javaVersion));
+    }
+
     @Override
     public Class<?> doCompile(String name, String sourceCode) throws Throwable {
         int i = name.lastIndexOf('.');
@@ -102,7 +118,7 @@ public class JdkCompiler extends AbstractCompiler {
         javaFileManager.putFileForInput(StandardLocation.SOURCE_PATH, packageName,
                 className + ClassUtils.JAVA_EXTENSION, javaFileObject);
         Boolean result = compiler.getTask(null, javaFileManager, diagnosticCollector, options,
-                null, Arrays.asList(javaFileObject)).call();
+                null, Collections.singletonList(javaFileObject)).call();
         if (result == null || !result) {
             throw new IllegalStateException("Compilation failed. class: " + name + ", diagnostics: " + diagnosticCollector);
         }
@@ -234,7 +250,7 @@ public class JdkCompiler extends AbstractCompiler {
         }
     }
 
-    private final class ClassLoaderImpl extends ClassLoader {
+    private static final class ClassLoaderImpl extends ClassLoader {
 
         private final Map<String, JavaFileObject> classes = new HashMap<String, JavaFileObject>();
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
index 31c3684..0cc6af2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
@@ -130,7 +130,7 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
 
     @Override
     public boolean removeConfig(String key, String group) {
-        return execute(() -> doRemoveConfig(key, group), -1L);
+        return Boolean.TRUE.equals(execute(() -> doRemoveConfig(key, group), -1L));
     }
 
     /**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java
index 8195558..f7c2ec7 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEvent.java
@@ -74,8 +74,12 @@ public class ConfigChangedEvent extends EventObject {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof ConfigChangedEvent)) return false;
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof ConfigChangedEvent)) {
+            return false;
+        }
         ConfigChangedEvent that = (ConfigChangedEvent) o;
         return Objects.equals(getKey(), that.getKey()) &&
                 Objects.equals(getGroup(), that.getGroup()) &&
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
index d85f86b..c0a5d9e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.common.config.configcenter;
 
+@Deprecated
 public interface Constants {
     String CONFIG_CLUSTER_KEY = "config.cluster";
     String CONFIG_NAMESPACE_KEY = "config.namespace";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java
index 6ac9dd0..09296b6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java
@@ -26,7 +26,7 @@ import java.util.TreeSet;
 
 import static java.util.Collections.emptySortedSet;
 import static java.util.Collections.unmodifiableSortedSet;
-import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 import static org.apache.dubbo.common.utils.PathUtils.buildPath;
@@ -87,7 +87,7 @@ public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfig
     @Override
     public final boolean publishConfig(String key, String group, String content) {
         String pathKey = buildPathKey(group, key);
-        return execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout());
+        return Boolean.TRUE.equals(execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout()));
     }
 
     @Override
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/ClusterRules.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/ClusterRules.java
new file mode 100644
index 0000000..f5f8729
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/ClusterRules.java
@@ -0,0 +1,63 @@
+/*
+ * 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.constants;
+
+/**
+ *  constant for Cluster fault-tolerant mode
+ */
+public interface ClusterRules {
+
+    /**
+     *  When invoke fails, log the initial error and retry other invokers
+     *  (retry n times, which means at most n different invokers will be invoked)
+     **/
+    String FAIL_OVER = "failover";
+
+    /**
+     *  Execute exactly once, which means this policy will throw an exception immediately in case of an invocation error.
+     **/
+    String FAIL_FAST = "failfast";
+
+    /**
+     *  When invoke fails, log the error message and ignore this error by returning an empty Result.
+     **/
+    String FAIL_SAFE = "failsafe";
+
+    /**
+     *  When fails, record failure requests and schedule for retry on a regular interval.
+     **/
+    String FAIL_BACK = "failback";
+
+    /**
+     *  Invoke a specific number of invokers concurrently, usually used for demanding real-time operations, but need to waste more service resources.
+     **/
+    String FORKING = "forking";
+
+    /**
+     *  Call all providers by broadcast, call them one by one, and report an error if any one reports an error
+     **/
+    String BROADCAST = "broadcast";
+
+
+    String AVAILABLE = "available";
+
+    String MERGEABLE = "mergeable";
+
+    String EMPTY = "";
+
+
+}
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 9119f32..245dd1d 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
@@ -114,6 +114,8 @@ public interface CommonConstants {
 
     String IO_THREADS_KEY = "iothreads";
 
+    String KEEP_ALIVE_KEY = "keep.alive";
+
     int DEFAULT_QUEUES = 0;
 
     int DEFAULT_ALIVE = 60 * 1000;
@@ -207,6 +209,8 @@ public interface CommonConstants {
 
     String REMOTE_METADATA_STORAGE_TYPE = "remote";
 
+    String GENERIC_KEY = "generic";
+
     /**
      * The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
      * {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
@@ -249,6 +253,11 @@ public interface CommonConstants {
     String DUBBO_IP_TO_BIND = "DUBBO_IP_TO_BIND";
 
     /**
+     * broadcast cluster.
+     */
+    String BROADCAST_CLUSTER = "broadcast";
+
+    /**
      * The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
      * the Dubbo application prefers
      *
@@ -311,6 +320,8 @@ public interface CommonConstants {
 
     String GENERIC_SERIALIZATION_NATIVE_JAVA = "nativejava";
 
+    String GENERIC_SERIALIZATION_GSON = "gson";
+
     String GENERIC_SERIALIZATION_DEFAULT = "true";
 
     String GENERIC_SERIALIZATION_BEAN = "bean";
@@ -401,4 +412,9 @@ public interface CommonConstants {
     String CLUSTER_INTERCEPTOR_COMPATIBLE_KEY = "dubbo.application.cluster.interceptor.compatible";
 
     String UTF8ENCODE = "UTF-8";
+
+    /** Pseudo URL prefix for loading from the class path: "classpath:". */
+    String CLASSPATH_URL_PREFIX = "classpath:";
+
+    String DEFAULT_VERSION = "0.0.0";
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoadbalanceRules.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoadbalanceRules.java
new file mode 100644
index 0000000..c0e9285
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/LoadbalanceRules.java
@@ -0,0 +1,51 @@
+/*
+ * 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.constants;
+
+/**
+ *  constant for Loadbalance strategy
+ */
+public interface LoadbalanceRules {
+
+    /**
+     *  This class select one provider from multiple providers randomly.
+     **/
+    String RANDOM = "random";
+
+    /**
+     *  Round robin load balance.
+     **/
+    String ROUND_ROBIN = "roundrobin";
+
+    /**
+     *  Filter the number of invokers with the least number of active calls and count the weights and quantities of these invokers.
+     **/
+    String LEAST_ACTIVE = "leastactive";
+
+    /**
+     *  Consistent Hash, requests with the same parameters are always sent to the same provider.
+     **/
+    String CONSISTENT_HASH = "consistenthash";
+
+    /**
+     *  Filter the number of invokers with the shortest response time of success calls and count the weights and quantities of these invokers.
+     **/
+    String SHORTEST_RESPONSE = "shortestresponse";
+
+    String EMPTY = "";
+
+}
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 629eaef..a7bf66f 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
@@ -114,6 +114,11 @@ public class ExtensionLoader<T> {
 
     private static volatile LoadingStrategy[] strategies = loadLoadingStrategies();
 
+    /**
+     * Record all unacceptable exceptions when using SPI
+     */
+    private Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
+
     public static void setLoadingStrategies(LoadingStrategy... strategies) {
         if (ArrayUtils.isNotEmpty(strategies)) {
             ExtensionLoader.strategies = strategies;
@@ -624,26 +629,25 @@ public class ExtensionLoader<T> {
     }
 
     private IllegalStateException findException(String name) {
-        for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
-            if (entry.getKey().toLowerCase().contains(name.toLowerCase())) {
-                return entry.getValue();
-            }
-        }
         StringBuilder buf = new StringBuilder("No such extension " + type.getName() + " by name " + name);
 
-
         int i = 1;
         for (Map.Entry<String, IllegalStateException> entry : exceptions.entrySet()) {
-            if (i == 1) {
-                buf.append(", possible causes: ");
+            if (entry.getKey().toLowerCase().startsWith(name.toLowerCase())) {
+                if (i == 1) {
+                    buf.append(", possible causes: ");
+                }
+                buf.append("\r\n(");
+                buf.append(i++);
+                buf.append(") ");
+                buf.append(entry.getKey());
+                buf.append(":\r\n");
+                buf.append(StringUtils.toString(entry.getValue()));
             }
+        }
 
-            buf.append("\r\n(");
-            buf.append(i++);
-            buf.append(") ");
-            buf.append(entry.getKey());
-            buf.append(":\r\n");
-            buf.append(StringUtils.toString(entry.getValue()));
+        if (i == 1) {
+            buf.append(", no related exception was found, please check whether related SPI module is missing.");
         }
         return new IllegalStateException(buf.toString());
     }
@@ -651,13 +655,13 @@ public class ExtensionLoader<T> {
     @SuppressWarnings("unchecked")
     private T createExtension(String name, boolean wrap) {
         Class<?> clazz = getExtensionClasses().get(name);
-        if (clazz == null) {
+        if (clazz == null || unacceptableExceptions.contains(name)) {
             throw findException(name);
         }
         try {
             T instance = (T) EXTENSION_INSTANCES.get(clazz);
             if (instance == null) {
-                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.newInstance());
+                EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
                 instance = (T) EXTENSION_INSTANCES.get(clazz);
             }
             injectExtension(instance);
@@ -872,6 +876,7 @@ public class ExtensionLoader<T> {
         try {
             try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
                 String line;
+                String clazz = null;
                 while ((line = reader.readLine()) != null) {
                     final int ci = line.indexOf('#');
                     if (ci >= 0) {
@@ -884,10 +889,12 @@ public class ExtensionLoader<T> {
                             int i = line.indexOf('=');
                             if (i > 0) {
                                 name = line.substring(0, i).trim();
-                                line = line.substring(i + 1).trim();
+                                clazz = line.substring(i + 1).trim();
+                            } else {
+                                clazz = line;
                             }
-                            if (line.length() > 0 && !isExcluded(line, excludedPackages)) {
-                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name, overridden);
+                            if (StringUtils.isNotEmpty(clazz) && !isExcluded(clazz, excludedPackages)) {
+                                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);
@@ -961,6 +968,8 @@ public class ExtensionLoader<T> {
         if (c == null || overridden) {
             extensionClasses.put(name, clazz);
         } else if (c != clazz) {
+            // duplicate implementation is unacceptable
+            unacceptableExceptions.add(name);
             String duplicateMsg = "Duplicate extension " + type.getName() + " name " + name + " on " + c.getName() + " and " + clazz.getName();
             logger.error(duplicateMsg);
             throw new IllegalStateException(duplicateMsg);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Wrapper.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Wrapper.java
index 670aae6..2d5780d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Wrapper.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/Wrapper.java
@@ -16,9 +16,13 @@
  */
 package org.apache.dubbo.common.extension;
 
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
 /**
  * The annotated class will only work as a wrapper when the condition matches.
  */
+@Retention(RetentionPolicy.RUNTIME)
 public @interface Wrapper {
 
     /**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java
index 3aa3fd9..bc6e4e3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/json/J2oVisitor.java
@@ -259,9 +259,7 @@ class J2oVisitor implements JSONVisitor {
             try {
                 mValue = mType.newInstance();
                 mWrapper = Wrapper.getWrapper(mType);
-            } catch (IllegalAccessException e) {
-                throw new ParseException(StringUtils.toString(e));
-            } catch (InstantiationException e) {
+            } catch (IllegalAccessException | InstantiationException e) {
                 throw new ParseException(StringUtils.toString(e));
             }
         }
@@ -304,9 +302,7 @@ class J2oVisitor implements JSONVisitor {
                             field.setAccessible(true);
                         }
                         field.set(mValue, obj);
-                    } catch (NoSuchFieldException e) {
-                        throw new ParseException(StringUtils.toString(e));
-                    } catch (IllegalAccessException e) {
+                    } catch (NoSuchFieldException | IllegalAccessException e) {
                         throw new ParseException(StringUtils.toString(e));
                     }
                 } else if (!CLASS_PROPERTY.equals(name)) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
index babb3ed..76a6a0b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/Prioritized.java
@@ -63,7 +63,7 @@ public interface Prioritized extends Comparable<Prioritized> {
     /**
      * Get the priority
      *
-     * @return the default is {@link #MIN_PRIORITY minimum one}
+     * @return the default is {@link #NORMAL_PRIORITY}
      */
     default int getPriority() {
         return NORMAL_PRIORITY;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalRunnable.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalRunnable.java
new file mode 100644
index 0000000..6cc8db8
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalRunnable.java
@@ -0,0 +1,53 @@
+/*
+ * 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.threadlocal;
+
+
+/**
+ * InternalRunnable
+ * There is a risk of memory leak when using {@link InternalThreadLocal} without calling
+ * {@link InternalThreadLocal#removeAll()}.
+ * This design is learning from {@see io.netty.util.concurrent.FastThreadLocalRunnable} which is in Netty.
+ */
+public class InternalRunnable implements Runnable{
+    private final Runnable runnable;
+
+    public InternalRunnable(Runnable runnable){
+        this.runnable=runnable;
+    }
+
+    /**
+     * After the task execution is completed, it will call {@link InternalThreadLocal#removeAll()} to clear
+     * unnecessary variables in the thread.
+     */
+    @Override
+    public void run() {
+        try{
+            runnable.run();
+        }finally {
+            InternalThreadLocal.removeAll();
+        }
+    }
+
+    /**
+     * Wrap ordinary Runnable into {@link InternalThreadLocal}.
+     */
+     static Runnable Wrap(Runnable runnable){
+        return runnable instanceof InternalRunnable?runnable:new InternalRunnable(runnable);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java
index 8820f12..13c7463 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/InternalThreadLocal.java
@@ -58,7 +58,7 @@ public class InternalThreadLocal<V> {
             if (v != null && v != InternalThreadLocalMap.UNSET) {
                 Set<InternalThreadLocal<?>> variablesToRemove = (Set<InternalThreadLocal<?>>) v;
                 InternalThreadLocal<?>[] variablesToRemoveArray =
-                        variablesToRemove.toArray(new InternalThreadLocal[variablesToRemove.size()]);
+                        variablesToRemove.toArray(new InternalThreadLocal[0]);
                 for (InternalThreadLocal<?> tlv : variablesToRemoveArray) {
                     tlv.remove(threadLocalMap);
                 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactory.java
index 52b8d56..0bb305f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadlocal/NamedInternalThreadFactory.java
@@ -40,7 +40,7 @@ public class NamedInternalThreadFactory extends NamedThreadFactory {
     @Override
     public Thread newThread(Runnable runnable) {
         String name = mPrefix + mThreadNum.getAndIncrement();
-        InternalThread ret = new InternalThread(mGroup, runnable, name, 0);
+        InternalThread ret = new InternalThread(mGroup, InternalRunnable.Wrap(runnable), name, 0);
         ret.setDaemon(mDaemon);
         return ret;
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadlessExecutor.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadlessExecutor.java
index 0225132..bc9042c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadlessExecutor.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/ThreadlessExecutor.java
@@ -32,7 +32,7 @@ import java.util.concurrent.TimeoutException;
 /**
  * The most important difference between this Executor and other normal Executor is that this one doesn't manage
  * any thread.
- *
+ * <p>
  * Tasks submitted to this executor through {@link #execute(Runnable)} will not get scheduled to a specific thread, though normal executors always do the schedule.
  * Those tasks are stored in a blocking queue and will only be executed when a thread calls {@link #waitAndDrain()}, the thread executing the task
  * is exactly the same as the one calling waitAndDrain.
@@ -86,7 +86,13 @@ public class ThreadlessExecutor extends AbstractExecutorService {
             return;
         }
 
-        Runnable runnable = queue.take();
+        Runnable runnable;
+        try {
+            runnable = queue.take();
+        }catch (InterruptedException e){
+            waiting = false;
+            throw e;
+        }
 
         synchronized (lock) {
             waiting = false;
@@ -95,12 +101,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
 
         runnable = queue.poll();
         while (runnable != null) {
-            try {
-                runnable.run();
-            } catch (Throwable t) {
-                logger.info(t);
-
-            }
+            runnable.run();
             runnable = queue.poll();
         }
         // mark the status of ThreadlessExecutor as finished.
@@ -131,6 +132,7 @@ public class ThreadlessExecutor extends AbstractExecutorService {
      */
     @Override
     public void execute(Runnable runnable) {
+        runnable = new RunnableWrapper(runnable);
         synchronized (lock) {
             if (!waiting) {
                 sharedExecutor.execute(runnable);
@@ -180,4 +182,21 @@ public class ThreadlessExecutor extends AbstractExecutorService {
     public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
         return false;
     }
+
+    private static class RunnableWrapper implements Runnable {
+        private Runnable runnable;
+
+        public RunnableWrapper(Runnable runnable) {
+            this.runnable = runnable;
+        }
+
+        @Override
+        public void run() {
+            try {
+                runnable.run();
+            } catch (Throwable t) {
+                logger.info(t);
+            }
+        }
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java
index c6865eb..49fdd89 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReport.java
@@ -16,6 +16,14 @@
  */
 package org.apache.dubbo.common.threadpool.support;
 
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent;
+import org.apache.dubbo.common.utils.JVMUtil;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.event.EventDispatcher;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.text.SimpleDateFormat;
@@ -26,13 +34,7 @@ import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.ThreadPoolExecutor;
 
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.threadpool.event.ThreadPoolExhaustedEvent;
-import org.apache.dubbo.common.utils.JVMUtil;
-import org.apache.dubbo.event.EventDispatcher;
-
+import static java.lang.String.format;
 import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
 
 /**
@@ -61,6 +63,8 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
 
     private static Semaphore guard = new Semaphore(1);
 
+    private static final String USER_HOME = System.getProperty("user.home");
+
     public AbortPolicyWithReport(String threadName, URL url) {
         this.threadName = threadName;
         this.url = url;
@@ -104,7 +108,7 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
 
         ExecutorService pool = Executors.newSingleThreadExecutor();
         pool.execute(() -> {
-            String dumpPath = url.getParameter(DUMP_DIRECTORY, System.getProperty("user.home"));
+            String dumpPath = getDumpPath();
 
             SimpleDateFormat sdf;
 
@@ -134,4 +138,21 @@ public class AbortPolicyWithReport extends ThreadPoolExecutor.AbortPolicy {
 
     }
 
+    private String getDumpPath() {
+        final String dumpPath = url.getParameter(DUMP_DIRECTORY);
+        if (StringUtils.isEmpty(dumpPath)) {
+            return USER_HOME;
+        }
+        final File dumpDirectory = new File(dumpPath);
+        if (!dumpDirectory.exists()) {
+            if (dumpDirectory.mkdirs()) {
+                logger.info(format("Dubbo dump directory[%s] created", dumpDirectory.getAbsolutePath()));
+            } else {
+                logger.warn(format("Dubbo dump directory[%s] can't be created, use the 'user.home'[%s]",
+                        dumpDirectory.getAbsolutePath(), USER_HOME));
+                return USER_HOME;
+            }
+        }
+        return dumpPath;
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java
index d695b46..487cc74 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/timer/HashedWheelTimer.java
@@ -805,8 +805,10 @@ public class HashedWheelTimer implements Timer {
             return head;
         }
     }
-
+    
+    private static final boolean IS_OS_WINDOWS = System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
+    
     private boolean isWindows() {
-        return System.getProperty("os.name", "").toLowerCase(Locale.US).contains("win");
+    	return IS_OS_WINDOWS;
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/URLParam.java b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/URLParam.java
index 4c333ea..6110639 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/URLParam.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/url/component/URLParam.java
@@ -37,6 +37,7 @@ import java.util.StringJoiner;
 
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY_PREFIX;
 import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
 
 /**
  * A class which store parameters for {@link URL}
@@ -178,7 +179,7 @@ public class URLParam implements Serializable {
      * Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
      *
      * @param method method name
-     * @param key key
+     * @param key    key
      * @return value
      */
     public String getMethodParameter(String method, String key) {
@@ -191,7 +192,7 @@ public class URLParam implements Serializable {
      * Specially, in some situation like `method1.1.callback=true`, key is `1.callback`.
      *
      * @param method method name
-     * @param key key
+     * @param key    key
      * @return value
      */
     public String getMethodParameterStrict(String method, String key) {
@@ -853,10 +854,27 @@ public class URLParam implements Serializable {
             return false;
         }
         URLParam urlParam = (URLParam) o;
-        return Objects.equals(KEY, urlParam.KEY)
+
+        if (Objects.equals(KEY, urlParam.KEY)
                 && Objects.equals(DEFAULT_KEY, urlParam.DEFAULT_KEY)
-                && Arrays.equals(VALUE, urlParam.VALUE)
-                && Objects.equals(EXTRA_PARAMS, urlParam.EXTRA_PARAMS);
+                && Arrays.equals(VALUE, urlParam.VALUE)) {
+            if (CollectionUtils.isNotEmptyMap(EXTRA_PARAMS)) {
+                if (CollectionUtils.isEmptyMap(urlParam.EXTRA_PARAMS) || EXTRA_PARAMS.size() != urlParam.EXTRA_PARAMS.size()) {
+                    return false;
+                }
+                for (Map.Entry<String, String> entry : EXTRA_PARAMS.entrySet()) {
+                    if (TIMESTAMP_KEY.equals(entry.getKey())) {
+                        continue;
+                    }
+                    if (!entry.getValue().equals(urlParam.EXTRA_PARAMS.get(entry.getKey()))) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+            return CollectionUtils.isEmptyMap(urlParam.EXTRA_PARAMS);
+        }
+        return false;
     }
 
     private int hashCodeCache = -1;
@@ -864,7 +882,11 @@ public class URLParam implements Serializable {
     @Override
     public int hashCode() {
         if (hashCodeCache == -1) {
-            hashCodeCache = EXTRA_PARAMS.hashCode();
+            for (Map.Entry<String, String> entry : EXTRA_PARAMS.entrySet()) {
+                if (!TIMESTAMP_KEY.equals(entry.getKey())) {
+                    hashCodeCache = hashCodeCache * 31 + Objects.hashCode(entry);
+                }
+            }
             for (Integer value : VALUE) {
                 hashCodeCache = hashCodeCache * 31 + value;
             }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
index 600c8aa..8da5f1d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
@@ -22,6 +22,7 @@ import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
 import java.lang.annotation.Target;
 import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.LinkedHashSet;
@@ -40,6 +41,7 @@ import static org.apache.dubbo.common.function.Streams.filterFirst;
 import static org.apache.dubbo.common.utils.ClassUtils.getAllInheritedTypes;
 import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
 import static org.apache.dubbo.common.utils.CollectionUtils.first;
+import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
 import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
 
 /**
@@ -449,4 +451,32 @@ public interface AnnotationUtils {
                                           Class<? extends Annotation>... annotationTypes) {
         return isAnnotationPresent(type, false, annotationTypes);
     }
+
+
+    /**
+     * Get the default value of attribute on the specified annotation
+     *
+     * @param annotation    {@link Annotation} object
+     * @param attributeName the name of attribute
+     * @param <T>           the type of value
+     * @return <code>null</code> if not found
+     * @since 2.7.9
+     */
+    static <T> T getDefaultValue(Annotation annotation, String attributeName) {
+        return getDefaultValue(annotation.annotationType(), attributeName);
+    }
+
+    /**
+     * Get the default value of attribute on the specified annotation
+     *
+     * @param annotationType the type of {@link Annotation}
+     * @param attributeName  the name of attribute
+     * @param <T>            the type of value
+     * @return <code>null</code> if not found
+     * @since 2.7.9
+     */
+    static <T> T getDefaultValue(Class<? extends Annotation> annotationType, String attributeName) {
+        Method method = findMethod(annotationType, attributeName);
+        return (T) (method == null ? null : method.getDefaultValue());
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ArrayUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ArrayUtils.java
index 5be000d..e648598 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ArrayUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ArrayUtils.java
@@ -66,4 +66,16 @@ public final class ArrayUtils {
             return -1;
         }
     }
+
+    /**
+     * Convert from variable arguments to array
+     *
+     * @param values variable arguments
+     * @param <T>    The class
+     * @return array
+     * @since 2.7.9
+     */
+    public static <T> T[] of(T... values) {
+        return values;
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java
index 2fb515c..a437a7d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java
@@ -44,21 +44,6 @@ public class ClassUtils {
      */
     public static final String ARRAY_SUFFIX = "[]";
     /**
-     * Prefix for internal array class names: "[L"
-     */
-    private static final String INTERNAL_ARRAY_PREFIX = "[L";
-    /**
-     * Map with primitive type name as key and corresponding primitive type as
-     * value, for example: "int" -> "int.class".
-     */
-    private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new HashMap<String, Class<?>>(32);
-    /**
-     * Map with primitive wrapper type as key and corresponding primitive type
-     * as value, for example: Integer.class -> int.class.
-     */
-    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
-
-    /**
      * Simple Types including:
      * <ul>
      *     <li>{@link Void}</li>
@@ -94,7 +79,20 @@ public class ClassUtils {
             Date.class,
             Object.class
     );
-
+    /**
+     * Prefix for internal array class names: "[L"
+     */
+    private static final String INTERNAL_ARRAY_PREFIX = "[L";
+    /**
+     * Map with primitive type name as key and corresponding primitive type as
+     * value, for example: "int" -> "int.class".
+     */
+    private static final Map<String, Class<?>> PRIMITIVE_TYPE_NAME_MAP = new HashMap<String, Class<?>>(32);
+    /**
+     * Map with primitive wrapper type as key and corresponding primitive type
+     * as value, for example: Integer.class -> int.class.
+     */
+    private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
     private static final char PACKAGE_SEPARATOR_CHAR = '.';
 
     static {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
index 1b73370..13c55eb 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CollectionUtils.java
@@ -39,28 +39,25 @@ import static java.util.Collections.unmodifiableSet;
  */
 public class CollectionUtils {
 
-    private static final Comparator<String> SIMPLE_NAME_COMPARATOR = new Comparator<String>() {
-        @Override
-        public int compare(String s1, String s2) {
-            if (s1 == null && s2 == null) {
-                return 0;
-            }
-            if (s1 == null) {
-                return -1;
-            }
-            if (s2 == null) {
-                return 1;
-            }
-            int i1 = s1.lastIndexOf('.');
-            if (i1 >= 0) {
-                s1 = s1.substring(i1 + 1);
-            }
-            int i2 = s2.lastIndexOf('.');
-            if (i2 >= 0) {
-                s2 = s2.substring(i2 + 1);
-            }
-            return s1.compareToIgnoreCase(s2);
+    private static final Comparator<String> SIMPLE_NAME_COMPARATOR = (s1, s2) -> {
+        if (s1 == null && s2 == null) {
+            return 0;
         }
+        if (s1 == null) {
+            return -1;
+        }
+        if (s2 == null) {
+            return 1;
+        }
+        int i1 = s1.lastIndexOf('.');
+        if (i1 >= 0) {
+            s1 = s1.substring(i1 + 1);
+        }
+        int i2 = s2.lastIndexOf('.');
+        if (i2 >= 0) {
+            s2 = s2.substring(i2 + 1);
+        }
+        return s1.compareToIgnoreCase(s2);
     };
 
     private CollectionUtils() {
@@ -324,9 +321,7 @@ public class CollectionUtils {
 
         try {
             return one.containsAll(another);
-        } catch (ClassCastException unused) {
-            return false;
-        } catch (NullPointerException unused) {
+        } catch (ClassCastException | NullPointerException unused) {
             return false;
         }
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
index 5d5cc5c..fecec8b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CompatibleTypeUtils.java
@@ -21,6 +21,7 @@ import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
+import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -111,17 +112,23 @@ public class CompatibleTypeUtils {
                             + DATE_FORMAT + ", cause: " + e.getMessage(), e);
                 }
             }
-            if (type == java.time.LocalDateTime.class || type == java.time.LocalDate.class
-                    || type == java.time.LocalTime.class) {
-
-                LocalDateTime localDateTime = LocalDateTime.parse(string);
-                if (type == java.time.LocalDate.class) {
-                    return localDateTime.toLocalDate();
+            if (type == java.time.LocalDateTime.class) {
+                if (StringUtils.isEmpty(string)) {
+                    return null;
+                }
+                return LocalDateTime.parse(string);
+            }
+            if (type == java.time.LocalDate.class) {
+                if (StringUtils.isEmpty(string)) {
+                    return null;
                 }
-                if (type == java.time.LocalTime.class) {
-                    return localDateTime.toLocalTime();
+                return LocalDate.parse(string);
+            }
+            if (type == java.time.LocalTime.class) {
+                if (StringUtils.isEmpty(string)) {
+                    return null;
                 }
-                return localDateTime;
+                return LocalDateTime.parse(string).toLocalTime();
             }
             if (type == Class.class) {
                 try {
@@ -200,19 +207,19 @@ public class CompatibleTypeUtils {
             }
         }
         if (value.getClass().isArray() && Collection.class.isAssignableFrom(type)) {
+            int length = Array.getLength(value);
             Collection collection;
             if (!type.isInterface()) {
                 try {
                     collection = (Collection) type.newInstance();
                 } catch (Throwable e) {
-                    collection = new ArrayList<Object>();
+                    collection = new ArrayList<Object>(length);
                 }
             } else if (type == Set.class) {
-                collection = new HashSet<Object>();
+                collection = new HashSet<Object>(Math.max((int) (length/.75f) + 1, 16));
             } else {
-                collection = new ArrayList<Object>();
+                collection = new ArrayList<Object>(length);
             }
-            int length = Array.getLength(value);
             for (int i = 0; i < length; i++) {
                 collection.add(Array.get(value, i));
             }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ExecutorUtil.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ExecutorUtil.java
index 93a2a60..97f13a5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ExecutorUtil.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ExecutorUtil.java
@@ -60,9 +60,7 @@ public class ExecutorUtil {
         try {
             // Disable new tasks from being submitted
             es.shutdown();
-        } catch (SecurityException ex2) {
-            return;
-        } catch (NullPointerException ex2) {
+        } catch (SecurityException | NullPointerException ex2) {
             return;
         }
         try {
@@ -86,9 +84,7 @@ public class ExecutorUtil {
         final ExecutorService es = (ExecutorService) executor;
         try {
             es.shutdownNow();
-        } catch (SecurityException ex2) {
-            return;
-        } catch (NullPointerException ex2) {
+        } catch (SecurityException | NullPointerException ex2) {
             return;
         }
         try {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/FieldUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/FieldUtils.java
index a619239..5c24ce1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/FieldUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/FieldUtils.java
@@ -62,6 +62,11 @@ public interface FieldUtils {
                 break;
             }
         }
+
+        if (field == null) {
+           throw new IllegalStateException(String.format("cannot find field %s,field is null", fieldName));
+        }
+
         return field;
     }
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java
index 02ec00b..b7e2616 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/IOUtils.java
@@ -16,9 +16,12 @@
  */
 package org.apache.dubbo.common.utils;
 
+import org.apache.dubbo.common.constants.CommonConstants;
+
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -30,6 +33,8 @@ import java.io.Reader;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.Writer;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -228,4 +233,38 @@ public class IOUtils {
         writeLines(new FileOutputStream(file, true), lines);
     }
 
+
+    /**
+     * use like spring code
+     * @param resourceLocation
+     * @return
+     */
+    public static URL getURL(String resourceLocation) throws FileNotFoundException {
+        Assert.notNull(resourceLocation, "Resource location must not be null");
+        if (resourceLocation.startsWith(CommonConstants.CLASSPATH_URL_PREFIX)) {
+            String path = resourceLocation.substring(CommonConstants.CLASSPATH_URL_PREFIX.length());
+            ClassLoader cl = ClassUtils.getClassLoader();
+            URL url = (cl != null ? cl.getResource(path) : ClassLoader.getSystemResource(path));
+            if (url == null) {
+                String description = "class path resource [" + path + "]";
+                throw new FileNotFoundException(description +
+                        " cannot be resolved to URL because it does not exist");
+            }
+            return url;
+        }
+        try {
+            // try URL
+            return new URL(resourceLocation);
+        }
+        catch (MalformedURLException ex) {
+            // no URL -> treat as file path
+            try {
+                return new File(resourceLocation).toURI().toURL();
+            }
+            catch (MalformedURLException ex2) {
+                throw new FileNotFoundException("Resource location [" + resourceLocation +
+                        "] is neither a URL not a well-formed file path");
+            }
+        }
+    }
 }
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java
index a4c3732..8230bd6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/LFUCache.java
@@ -30,12 +30,12 @@ public class LFUCache<K, V> {
     private int curSize = 0;
 
     private final ReentrantLock lock = new ReentrantLock();
-    private static final int DEFAULT_LOAD_FACTOR = 1000;
+    private static final int DEFAULT_INITIAL_CAPACITY = 1000;
 
-    private static final float DEFAULT_EVICTION_CAPACITY = 0.75f;
+    private static final float DEFAULT_EVICTION_FACTOR = 0.75f;
 
     public LFUCache() {
-        this(DEFAULT_LOAD_FACTOR, DEFAULT_EVICTION_CAPACITY);
+        this(DEFAULT_INITIAL_CAPACITY, DEFAULT_EVICTION_FACTOR);
     }
 
     /**
@@ -46,12 +46,13 @@ public class LFUCache<K, V> {
      * @param maxCapacity    cache max capacity
      * @param evictionFactor cache proceedEviction factor
      */
+    @SuppressWarnings("unchecked")
     public LFUCache(final int maxCapacity, final float evictionFactor) {
         if (maxCapacity <= 0) {
             throw new IllegalArgumentException("Illegal initial capacity: " +
                     maxCapacity);
         }
-        boolean factorInRange = evictionFactor <= 1 || evictionFactor < 0;
+        boolean factorInRange = evictionFactor <= 1 && evictionFactor > 0;
         if (!factorInRange || Float.isNaN(evictionFactor)) {
             throw new IllegalArgumentException("Illegal eviction factor value:"
                     + evictionFactor);
@@ -61,7 +62,7 @@ public class LFUCache<K, V> {
         this.map = new HashMap<>();
         this.freqTable = new CacheDeque[capacity + 1];
         for (int i = 0; i <= capacity; i++) {
-            freqTable[i] = new CacheDeque<K, V>();
+            freqTable[i] = new CacheDeque<>();
         }
         for (int i = 0; i < capacity; i++) {
             freqTable[i].nextDeque = freqTable[i + 1];
@@ -77,11 +78,9 @@ public class LFUCache<K, V> {
         CacheNode<K, V> node;
         lock.lock();
         try {
-            if (map.containsKey(key)) {
-                node = map.get(key);
-                if (node != null) {
-                    CacheNode.withdrawNode(node);
-                }
+            node = map.get(key);
+            if (node != null) {
+                CacheNode.withdrawNode(node);
                 node.value = value;
                 freqTable[0].addLastNode(node);
                 map.put(key, node);
@@ -171,7 +170,7 @@ public class LFUCache<K, V> {
         CacheNode<K, V> next;
         K key;
         V value;
-        CacheDeque owner;
+        CacheDeque<K, V> owner;
 
         CacheNode() {
         }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java
index 27262b4..a885fb7 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodUtils.java
@@ -34,6 +34,7 @@ import static org.apache.dubbo.common.utils.MemberUtils.isPrivate;
 import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
 import static org.apache.dubbo.common.utils.ReflectUtils.EMPTY_CLASS_ARRAY;
 import static org.apache.dubbo.common.utils.ReflectUtils.resolveTypes;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
 
 /**
  * Miscellaneous method utility methods.
@@ -50,7 +51,7 @@ public interface MethodUtils {
      * @param method the method to check
      * @return whether the given method is setter method
      */
-    public static boolean isSetter(Method method) {
+    static boolean isSetter(Method method) {
         return method.getName().startsWith("set")
                 && !"set".equals(method.getName())
                 && Modifier.isPublic(method.getModifiers())
@@ -65,7 +66,7 @@ public interface MethodUtils {
      * @param method the method to check
      * @return whether the given method is getter method
      */
-    public static boolean isGetter(Method method) {
+    static boolean isGetter(Method method) {
         String name = method.getName();
         return (name.startsWith("get") || name.startsWith("is"))
                 && !"get".equals(name) && !"is".equals(name)
@@ -82,7 +83,7 @@ public interface MethodUtils {
      * @param method the method to check
      * @return whether the given method is meta method
      */
-    public static boolean isMetaMethod(Method method) {
+    static boolean isMetaMethod(Method method) {
         String name = method.getName();
         if (!(name.startsWith("get") || name.startsWith("is"))) {
             return false;
@@ -113,12 +114,11 @@ public interface MethodUtils {
      * @param method the method to check
      * @return whether the given method is deprecated method
      */
-    public static boolean isDeprecated(Method method) {
+    static boolean isDeprecated(Method method) {
         return method.getAnnotation(Deprecated.class) != null;
     }
 
 
-
     /**
      * Create an instance of {@link Predicate} for {@link Method} to exclude the specified declared class
      *
@@ -252,7 +252,9 @@ public interface MethodUtils {
     static Method findMethod(Class type, String methodName, Class<?>... parameterTypes) {
         Method method = null;
         try {
-            method = type.getDeclaredMethod(methodName, parameterTypes);
+            if (type != null && isNotEmpty(methodName)) {
+                method = type.getDeclaredMethod(methodName, parameterTypes);
+            }
         } catch (NoSuchMethodException e) {
         }
         return method;
@@ -274,6 +276,10 @@ public interface MethodUtils {
         Method method = findMethod(type, methodName, parameterTypes);
         T value = null;
 
+        if (method == null) {
+            throw new IllegalStateException(String.format("cannot find method %s,class: %s", methodName, type.getName()));
+        }
+
         try {
             final boolean isAccessible = method.isAccessible();
 
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 1845514..01855f4 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
@@ -235,7 +235,9 @@ public class NetUtils {
             return configIp;
         }
 
-        return getIpByHost(getLocalAddress().getHostName());
+        InetAddress localAddress = getLocalAddress();
+        String hostName = localAddress == null ? LOCALHOST_VALUE : localAddress.getHostName();
+        return getIpByHost(hostName);
     }
 
     /**
@@ -471,10 +473,8 @@ public class NetUtils {
 
     public static void setInterface(MulticastSocket multicastSocket, boolean preferIpv6) throws IOException {
         boolean interfaceSet = false;
-        Enumeration interfaces = NetworkInterface.getNetworkInterfaces();
-        while (interfaces.hasMoreElements()) {
-            NetworkInterface i = (NetworkInterface) interfaces.nextElement();
-            Enumeration addresses = i.getInetAddresses();
+        for (NetworkInterface networkInterface : getValidNetworkInterfaces()) {
+            Enumeration addresses = networkInterface.getInetAddresses();
             while (addresses.hasMoreElements()) {
                 InetAddress address = (InetAddress) addresses.nextElement();
                 if (preferIpv6 && address instanceof Inet6Address) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
index 145550c..b940d04 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PojoUtils.java
@@ -173,6 +173,7 @@ public class PojoUtils {
         }
         for (Method method : pojo.getClass().getMethods()) {
             if (ReflectUtils.isBeanPropertyReadMethod(method)) {
+                ReflectUtils.makeAccessible(method);
                 try {
                     map.put(ReflectUtils.getPropertyNameFromBeanReadMethod(method), generalize(method.invoke(pojo), history));
                 } catch (Exception e) {
@@ -588,11 +589,7 @@ public class PojoUtils {
                 constructor.setAccessible(true);
                 Object[] parameters = Arrays.stream(constructor.getParameterTypes()).map(PojoUtils::getDefaultValue).toArray();
                 return constructor.newInstance(parameters);
-            } catch (InstantiationException e) {
-                throw new RuntimeException(e.getMessage(), e);
-            } catch (IllegalAccessException e) {
-                throw new RuntimeException(e.getMessage(), e);
-            } catch (InvocationTargetException e) {
+            } catch (InstantiationException | InvocationTargetException | IllegalAccessException e) {
                 throw new RuntimeException(e.getMessage(), e);
             }
         }
@@ -608,9 +605,15 @@ public class PojoUtils {
         if ("char".equals(parameterType.getName())) {
             return Character.MIN_VALUE;
         }
-        if ("bool".equals(parameterType.getName())) {
+        if ("boolean".equals(parameterType.getName())) {
             return false;
         }
+        if ("byte".equals(parameterType.getName())) {
+            return (byte) 0;
+        }
+        if ("short".equals(parameterType.getName())) {
+            return (short) 0;
+        }
         return parameterType.isPrimitive() ? 0 : null;
     }
 
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
index ea8d51f..c73df9a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
@@ -31,6 +31,7 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
 import java.net.URL;
 import java.security.CodeSource;
 import java.security.ProtectionDomain;
@@ -154,8 +155,8 @@ public final class ReflectUtils {
     }
 
     public static boolean isPrimitives(Class<?> cls) {
-        if (cls.isArray()) {
-            return isPrimitive(cls.getComponentType());
+        while (cls.isArray()) {
+            cls = cls.getComponentType();
         }
         return isPrimitive(cls);
     }
@@ -904,7 +905,9 @@ public final class ReflectUtils {
      * @throws NoSuchMethodException
      * @throws ClassNotFoundException
      * @throws IllegalStateException  when multiple methods are found (overridden method when parameter info is not provided)
+     * @deprecated Recommend {@link MethodUtils#findMethod(Class, String, Class[])}
      */
+    @Deprecated
     public static Method findMethodByMethodSignature(Class<?> clazz, String methodName, String[] parameterTypes)
             throws NoSuchMethodException, ClassNotFoundException {
         String signature = clazz.getName() + "." + methodName;
@@ -943,6 +946,16 @@ public final class ReflectUtils {
         return method;
     }
 
+    /**
+     * @param clazz      Target class to find method
+     * @param methodName Method signature, e.g.: method1(int, String). It is allowed to provide method name only, e.g.: method2
+     * @return target method
+     * @throws NoSuchMethodException
+     * @throws ClassNotFoundException
+     * @throws IllegalStateException  when multiple methods are found (overridden method when parameter info is not provided)
+     * @deprecated Recommend {@link MethodUtils#findMethod(Class, String, Class[])}
+     */
+    @Deprecated
     public static Method findMethodByMethodName(Class<?> clazz, String methodName)
             throws NoSuchMethodException, ClassNotFoundException {
         return findMethodByMethodSignature(clazz, methodName, null);
@@ -1051,7 +1064,7 @@ public final class ReflectUtils {
         try {
             Object value = emptyInstances.get(returnType);
             if (value == null) {
-                value = returnType.newInstance();
+                value = returnType.getDeclaredConstructor().newInstance();
                 emptyInstances.put(returnType, value);
             }
             Class<?> cls = value.getClass();
@@ -1190,6 +1203,9 @@ public final class ReflectUtils {
                 if (actualArgType instanceof ParameterizedType) {
                     returnType = (Class<?>) ((ParameterizedType) actualArgType).getRawType();
                     genericReturnType = actualArgType;
+                } else if (actualArgType instanceof TypeVariable) {
+                    returnType = (Class<?>) ((TypeVariable<?>) actualArgType).getBounds()[0];
+                    genericReturnType = actualArgType;
                 } else {
                     returnType = (Class<?>) actualArgType;
                     genericReturnType = returnType;
@@ -1217,16 +1233,14 @@ public final class ReflectUtils {
 
         Set<ParameterizedType> parameterizedTypes = genericTypes.stream()
                 .filter(type -> type instanceof ParameterizedType)// filter ParameterizedType
-                .map(type -> ParameterizedType.class.cast(type))  // cast to ParameterizedType
+                .map(ParameterizedType.class::cast)  // cast to ParameterizedType
                 .collect(Collectors.toSet());
 
         if (parameterizedTypes.isEmpty()) { // If not found, try to search super types recursively
             genericTypes.stream()
                     .filter(type -> type instanceof Class)
-                    .map(type -> Class.class.cast(type))
-                    .forEach(superClass -> {
-                        parameterizedTypes.addAll(findParameterizedTypes(superClass));
-                    });
+                    .map(Class.class::cast)
+                    .forEach(superClass -> parameterizedTypes.addAll(findParameterizedTypes(superClass)));
         }
 
         return unmodifiableSet(parameterizedTypes);                     // build as a Set
@@ -1316,4 +1330,21 @@ public final class ReflectUtils {
 
         return types;
     }
-}
\ No newline at end of file
+
+    /**
+     * Copy from org.springframework.util.ReflectionUtils.
+     * Make the given method accessible, explicitly setting it accessible if
+     * necessary. The {@code setAccessible(true)} method is only called
+     * when actually necessary, to avoid unnecessary conflicts with a JVM
+     * SecurityManager (if active).
+     * @param method the method to make accessible
+     * @see java.lang.reflect.Method#setAccessible
+     */
+    @SuppressWarnings("deprecation")  // on JDK 9
+    public static void makeAccessible(Method method) {
+        if ((!Modifier.isPublic(method.getModifiers()) ||
+                !Modifier.isPublic(method.getDeclaringClass().getModifiers())) && !method.isAccessible()) {
+            method.setAccessible(true);
+        }
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ServiceAnnotationResolver.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ServiceAnnotationResolver.java
index 58e5e7a..c49b3a3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ServiceAnnotationResolver.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ServiceAnnotationResolver.java
@@ -16,11 +16,15 @@
  */
 package org.apache.dubbo.common.utils;
 
+import org.apache.dubbo.config.annotation.DubboService;
 import org.apache.dubbo.config.annotation.Service;
 
 import java.lang.annotation.Annotation;
+import java.util.List;
 
 import static java.lang.String.format;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableList;
 import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
 import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
 import static org.apache.dubbo.common.utils.ClassUtils.isGenericClass;
@@ -36,6 +40,13 @@ import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
  */
 public class ServiceAnnotationResolver {
 
+    /**
+     * The annotation {@link Class classes} of Dubbo Service (read-only)
+     *
+     * @since 2.7.9
+     */
+    public static List<Class<? extends Annotation>> SERVICE_ANNOTATION_CLASSES = unmodifiableList(asList(DubboService.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
+
     private final Annotation serviceAnnotation;
 
     private final Class<?> serviceType;
@@ -47,16 +58,18 @@ public class ServiceAnnotationResolver {
 
     private Annotation getServiceAnnotation(Class<?> serviceType) {
 
-        Annotation serviceAnnotation = serviceType.getAnnotation(Service.class);
+        Annotation serviceAnnotation = null;
 
-        if (serviceAnnotation == null) {
-            serviceAnnotation = serviceType.getAnnotation(com.alibaba.dubbo.config.annotation.Service.class);
+        for (Class<? extends Annotation> serviceAnnotationClass : SERVICE_ANNOTATION_CLASSES) {
+            serviceAnnotation = serviceType.getAnnotation(serviceAnnotationClass);
+            if (serviceAnnotation != null) {
+                break;
+            }
         }
 
         if (serviceAnnotation == null) {
-            throw new IllegalArgumentException(format("@%s or @%s can't be found in the service type[%s].",
-                    Service.class.getName(),
-                    com.alibaba.dubbo.config.annotation.Service.class.getName(),
+            throw new IllegalArgumentException(format("Any annotation of [%s] can't be annotated in the service type[%s].",
+                    SERVICE_ANNOTATION_CLASSES,
                     serviceType.getName()
             ));
         }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
index 968dc7e..3f21374 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
@@ -200,11 +200,7 @@ public class UrlUtils {
                     if (version != null && version.length() > 0) {
                         name = name + ":" + version;
                     }
-                    Map<String, String> newUrls = newRegister.get(name);
-                    if (newUrls == null) {
-                        newUrls = new HashMap<String, String>();
-                        newRegister.put(name, newUrls);
-                    }
+                    Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<>());
                     newUrls.put(serviceUrl, StringUtils.toQueryString(params));
                 }
             } else {
@@ -261,11 +257,7 @@ public class UrlUtils {
                         params.put("version", name.substring(i + 1));
                         name = name.substring(0, i);
                     }
-                    Map<String, String> newUrls = newRegister.get(name);
-                    if (newUrls == null) {
-                        newUrls = new HashMap<String, String>();
-                        newRegister.put(name, newUrls);
-                    }
+                    Map<String, String> newUrls = newRegister.computeIfAbsent(name, k -> new HashMap<String, String>());
                     newUrls.put(serviceUrl, StringUtils.toQueryString(params));
                 }
             } else {
@@ -324,11 +316,7 @@ public class UrlUtils {
                             if (version != null && version.length() > 0) {
                                 name = name + ":" + version;
                             }
-                            Map<String, String> newUrls = newNotify.get(name);
-                            if (newUrls == null) {
-                                newUrls = new HashMap<String, String>();
-                                newNotify.put(name, newUrls);
-                            }
+                            Map<String, String> newUrls = newNotify.computeIfAbsent(name, k -> new HashMap<String, String>());
                             newUrls.put(url, StringUtils.toQueryString(params));
                         }
                     }
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 3e0c9f6..97ae6a1 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
@@ -34,6 +34,7 @@ import org.apache.dubbo.rpc.model.AsyncMethodInfo;
 
 import javax.annotation.PostConstruct;
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.Arrays;
@@ -86,6 +87,11 @@ public abstract class AbstractConfig implements Serializable {
 
     protected final AtomicBoolean refreshed = new AtomicBoolean(false);
 
+    /**
+     * Is default or not
+     */
+    protected Boolean isDefault;
+
     private static String convertLegacyValue(String key, String value) {
         if (value != null && value.length() > 0) {
             if ("dubbo.service.max.retry.providers".equals(key)) {
@@ -373,6 +379,7 @@ public abstract class AbstractConfig implements Serializable {
         Method[] methods = annotationClass.getMethods();
         for (Method method : methods) {
             if (method.getDeclaringClass() != Object.class
+                    && method.getDeclaringClass()!= Annotation.class
                     && method.getReturnType() != void.class
                     && method.getParameterTypes().length == 0
                     && Modifier.isPublic(method.getModifiers())
@@ -536,7 +543,7 @@ public abstract class AbstractConfig implements Serializable {
                             buf.append(" ");
                             buf.append(key);
                             buf.append("=\"");
-                            buf.append(value);
+                            buf.append(key.equals("password") ? "******" : value);
                             buf.append("\"");
                         }
                     }
@@ -628,4 +635,12 @@ public abstract class AbstractConfig implements Serializable {
 
         return hashCode;
     }
+
+    public Boolean isDefault() {
+        return isDefault;
+    }
+
+    public void setDefault(Boolean isDefault) {
+        this.isDefault = isDefault;
+    }
 }
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 e141668..bf1497d 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
@@ -26,6 +26,7 @@ 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.ServiceMetadata;
 
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -53,6 +54,21 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     private static final long serialVersionUID = -1559314110797223229L;
 
     /**
+     * The interface name of the exported service
+     */
+    protected String interfaceName;
+    /**
+     * The remote service version the customer/provider side will reference
+     */
+    protected String version;
+
+    /**
+     * The remote service group the customer/provider side will reference
+     */
+    protected String group;
+    
+    protected ServiceMetadata serviceMetadata;
+    /**
      * Local impl class name for the service interface
      */
     protected String local;
@@ -312,6 +328,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
 
     }
 
+    protected boolean notHasSelfRegistryProperty() {
+        return CollectionUtils.isEmpty(registries) && StringUtils.isEmpty(registryIds);
+    }
+
     public void completeCompoundConfigs(AbstractInterfaceConfig interfaceConfig) {
         if (interfaceConfig != null) {
             if (application == null) {
@@ -320,15 +340,16 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             if (module == null) {
                 setModule(interfaceConfig.getModule());
             }
-            if (registries == null) {
+            if (notHasSelfRegistryProperty()) {
                 setRegistries(interfaceConfig.getRegistries());
+                setRegistryIds(interfaceConfig.getRegistryIds());
             }
             if (monitor == null) {
                 setMonitor(interfaceConfig.getMonitor());
             }
         }
         if (module != null) {
-            if (registries == null) {
+            if (notHasSelfRegistryProperty()) {
                 setRegistries(module.getRegistries());
             }
             if (monitor == null) {
@@ -336,8 +357,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
             }
         }
         if (application != null) {
-            if (registries == null) {
+            if (notHasSelfRegistryProperty()) {
                 setRegistries(application.getRegistries());
+                setRegistryIds(application.getRegistryIds());
             }
             if (monitor == null) {
                 setMonitor(application.getMonitor());
@@ -346,10 +368,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     }
     
     protected void computeValidRegistryIds() {
-        if (StringUtils.isEmpty(getRegistryIds())) {
-            if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryIds())) {
-                setRegistryIds(getApplication().getRegistryIds());
-            }
+        if (application != null && notHasSelfRegistryProperty()) {
+            setRegistries(application.getRegistries());
+            setRegistryIds(application.getRegistryIds());
         }
     }
 
@@ -691,4 +712,46 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     public SslConfig getSslConfig() {
         return ApplicationModel.getConfigManager().getSsl().orElse(null);
     }
+    
+    public void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
+        serviceMetadata.setVersion(getVersion(interfaceConfig));
+        serviceMetadata.setGroup(getGroup(interfaceConfig));
+        serviceMetadata.setDefaultGroup(getGroup(interfaceConfig));
+        serviceMetadata.setServiceInterfaceName(getInterface());
+    }
+    
+    public String getGroup(AbstractInterfaceConfig interfaceConfig) {
+        return StringUtils.isEmpty(this.group) ? (interfaceConfig != null ? interfaceConfig.getGroup() : this.group) : this.group;
+    }
+
+    public String getVersion(AbstractInterfaceConfig interfaceConfig) {
+        return StringUtils.isEmpty(this.version) ? (interfaceConfig != null ? interfaceConfig.getVersion() : this.version) : this.version;
+    }
+    
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+    
+    public String getInterface() {
+        return interfaceName;
+    }
+    
+    public void setInterface(String interfaceName) {
+        this.interfaceName = interfaceName;
+//         if (StringUtils.isEmpty(id)) {
+//             id = interfaceName;
+//         }
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
index 27d4ddc..f2038a1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractReferenceConfig.java
@@ -71,15 +71,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
     //TODO solve merge problem
     protected Boolean stubevent;//= Constants.DEFAULT_STUB_EVENT;
 
-    /**
-     * The remote service version the customer side will reference
-     */
-    protected String version;
 
-    /**
-     * The remote service group the customer side will reference
-     */
-    protected String group;
 
     /**
      * declares which app or service this interface belongs to
@@ -212,21 +204,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
         this.sticky = sticky;
     }
 
-    public String getVersion() {
-        return version;
-    }
-
-    public void setVersion(String version) {
-        this.version = version;
-    }
 
-    public String getGroup() {
-        return group;
-    }
-
-    public void setGroup(String group) {
-        this.group = group;
-    }
 
     @Parameter(key = "provided-by")
     public String getProvidedBy() {
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 a95a16f..25b9d9b 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
@@ -113,11 +113,6 @@ public class ApplicationConfig extends AbstractConfig {
     private MonitorConfig monitor;
 
     /**
-     * Is default or not
-     */
-    private Boolean isDefault;
-
-    /**
      * Directory for saving thread dump
      */
     private String dumpDirectory;
@@ -320,14 +315,6 @@ public class ApplicationConfig extends AbstractConfig {
         LoggerFactory.setLoggerAdapter(logger);
     }
 
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     @Parameter(key = DUMP_DIRECTORY)
     public String getDumpDirectory() {
         return dumpDirectory;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java
index 894f138..cfc45d9 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/Constants.java
@@ -119,4 +119,6 @@ public interface Constants {
     String MULTI_SERIALIZATION_KEY = "serialize.multiple";
 
     String[] DOT_COMPATIBLE_KEYS = new String[]{"qos-enable", "qos-port", "qos-accept-foreign-ip"};
+
+    String IGNORE_CHECK_KEYS = "ignoreCheckKeys";
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java
index 25f2c77..53e63d2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConsumerConfig.java
@@ -28,11 +28,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
     private static final long serialVersionUID = 2827274711143680600L;
 
     /**
-     * Whether to use the default protocol
-     */
-    private Boolean isDefault;
-
-    /**
      * Networking framework client uses: netty, mina, etc.
      */
     private String client;
@@ -72,11 +67,7 @@ public class ConsumerConfig extends AbstractReferenceConfig {
             System.setProperty("sun.rmi.transport.tcp.responseTimeout", String.valueOf(timeout));
         }
     }
-
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
+    
     public String getClient() {
         return client;
     }
@@ -93,14 +84,6 @@ public class ConsumerConfig extends AbstractReferenceConfig {
         this.threadpool = threadpool;
     }
 
-    public Boolean getDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     public Integer getCorethreads() {
         return corethreads;
     }
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 0be5089..4187488 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
@@ -85,6 +85,12 @@ public class MetadataReportConfig extends AbstractConfig {
      */
     private String registry;
 
+    /**
+     * File for saving metadata center dynamic list
+     */
+    private String file;
+
+
     public MetadataReportConfig() {
     }
 
@@ -225,4 +231,12 @@ public class MetadataReportConfig extends AbstractConfig {
     public void setRegistry(String registry) {
         this.registry = registry;
     }
+
+    public String getFile() {
+        return file;
+    }
+
+    public void setFile(String file) {
+        this.file = file;
+    }
 }
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 d239c4a..968b61f 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
@@ -139,15 +139,28 @@ public class MethodConfig extends AbstractMethodConfig {
 
         this.setReturn(method.isReturn());
 
-        //TODO callback method processing is not completed
-        if(!"".equals(method.oninvoke())){
-            this.setOninvoke(method.oninvoke());
+        String split = ".";
+
+        if (!"".equals(method.oninvoke()) && method.oninvoke().lastIndexOf(split) > 0) {
+            int index = method.oninvoke().lastIndexOf(split);
+            String ref = method.oninvoke().substring(0, index);
+            String methodName = method.oninvoke().substring(index + 1);
+            this.setOninvoke(ref);
+            this.setOninvokeMethod(methodName);
         }
-        if(!"".equals(method.onreturn())){
-            this.setOnreturn(method.onreturn());
+        if (!"".equals(method.onreturn()) && method.onreturn().lastIndexOf(split) > 0) {
+            int index = method.onreturn().lastIndexOf(split);
+            String ref = method.onreturn().substring(0, index);
+            String methodName = method.onreturn().substring(index + 1);
+            this.setOnreturn(ref);
+            this.setOnreturnMethod(methodName);
         }
-        if(!"".equals(method.onthrow())){
-            this.setOnthrow(method.onthrow());
+        if (!"".equals(method.onthrow()) && method.onthrow().lastIndexOf(split) > 0) {
+            int index = method.onthrow().lastIndexOf(split);
+            String ref = method.onthrow().substring(0, index);
+            String methodName = method.onthrow().substring(index + 1);
+            this.setOnthrow(ref);
+            this.setOnthrowMethod(methodName);
         }
 
         if (method.arguments() != null && method.arguments().length != 0) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ModuleConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ModuleConfig.java
index 064310b..3104013 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ModuleConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ModuleConfig.java
@@ -62,11 +62,6 @@ public class ModuleConfig extends AbstractConfig {
      */
     private MonitorConfig monitor;
 
-    /**
-     * If it's default
-     */
-    private Boolean isDefault;
-
     public ModuleConfig() {
     }
 
@@ -142,12 +137,4 @@ public class ModuleConfig extends AbstractConfig {
         this.monitor = new MonitorConfig(monitor);
     }
 
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/MonitorConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/MonitorConfig.java
index 8bd7bed..ed8beb1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/MonitorConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/MonitorConfig.java
@@ -63,11 +63,6 @@ public class MonitorConfig extends AbstractConfig {
      */
     private Map<String, String> parameters;
 
-    /**
-     * If it's default
-     */
-    private Boolean isDefault;
-
     public MonitorConfig() {
     }
 
@@ -135,14 +130,6 @@ public class MonitorConfig extends AbstractConfig {
         this.parameters = parameters;
     }
 
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     public String getInterval() {
         return interval;
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java
index 25cca82..b8af63c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ProtocolConfig.java
@@ -80,6 +80,11 @@ public class ProtocolConfig extends AbstractConfig {
     private Integer iothreads;
 
     /**
+     * Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
+     */
+    private Integer alive;
+
+    /**
      * Thread pool's queue length
      */
     private Integer queues;
@@ -193,11 +198,6 @@ public class ProtocolConfig extends AbstractConfig {
      */
     private Map<String, String> parameters;
 
-    /**
-     * If it's default
-     */
-    private Boolean isDefault;
-
     private Boolean sslEnabled;
 
     public ProtocolConfig() {
@@ -300,6 +300,14 @@ public class ProtocolConfig extends AbstractConfig {
         this.iothreads = iothreads;
     }
 
+    public Integer getAlive() {
+        return alive;
+    }
+
+    public void setAlive(Integer alive) {
+        this.alive = alive;
+    }
+
     public Integer getQueues() {
         return queues;
     }
@@ -482,14 +490,6 @@ public class ProtocolConfig extends AbstractConfig {
         this.parameters = parameters;
     }
 
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     @Parameter(key = SSL_ENABLED_KEY)
     public Boolean getSslEnabled() {
         return sslEnabled;
@@ -540,4 +540,46 @@ public class ProtocolConfig extends AbstractConfig {
     public boolean isValid() {
         return StringUtils.isNotEmpty(name);
     }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("ProtocolConfig{");
+        sb.append("name='").append(name).append('\'');
+        sb.append(", host='").append(host).append('\'');
+        sb.append(", port=").append(port);
+        sb.append(", contextpath='").append(contextpath).append('\'');
+        sb.append(", threadpool='").append(threadpool).append('\'');
+        sb.append(", threadname='").append(threadname).append('\'');
+        sb.append(", corethreads=").append(corethreads);
+        sb.append(", threads=").append(threads);
+        sb.append(", iothreads=").append(iothreads);
+        sb.append(", alive=").append(alive);
+        sb.append(", queues=").append(queues);
+        sb.append(", accepts=").append(accepts);
+        sb.append(", codec='").append(codec).append('\'');
+        sb.append(", serialization='").append(serialization).append('\'');
+        sb.append(", charset='").append(charset).append('\'');
+        sb.append(", payload=").append(payload);
+        sb.append(", buffer=").append(buffer);
+        sb.append(", heartbeat=").append(heartbeat);
+        sb.append(", accesslog='").append(accesslog).append('\'');
+        sb.append(", transporter='").append(transporter).append('\'');
+        sb.append(", exchanger='").append(exchanger).append('\'');
+        sb.append(", dispatcher='").append(dispatcher).append('\'');
+        sb.append(", networker='").append(networker).append('\'');
+        sb.append(", server='").append(server).append('\'');
+        sb.append(", client='").append(client).append('\'');
+        sb.append(", telnet='").append(telnet).append('\'');
+        sb.append(", prompt='").append(prompt).append('\'');
+        sb.append(", status='").append(status).append('\'');
+        sb.append(", register=").append(register);
+        sb.append(", keepAlive=").append(keepAlive);
+        sb.append(", optimizer='").append(optimizer).append('\'');
+        sb.append(", extension='").append(extension).append('\'');
+        sb.append(", parameters=").append(parameters);
+        sb.append(", isDefault=").append(isDefault);
+        sb.append(", sslEnabled=").append(sslEnabled);
+        sb.append('}');
+        return sb.toString();
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java
index 7b38a75..62eb377 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ProviderConfig.java
@@ -70,6 +70,11 @@ public class ProviderConfig extends AbstractServiceConfig {
     private Integer iothreads;
 
     /**
+     * Thread pool keepAliveTime, default unit TimeUnit.MILLISECONDS
+     */
+    private Integer alive;
+
+    /**
      * Thread pool queue length
      */
     private Integer queues;
@@ -149,26 +154,17 @@ public class ProviderConfig extends AbstractServiceConfig {
      */
     private Integer wait;
 
-    /**
-     * Whether to use the default protocol
-     */
-    private Boolean isDefault;
-
     @Deprecated
     public void setProtocol(String protocol) {
         this.protocols = new ArrayList<>(Arrays.asList(new ProtocolConfig(protocol)));
     }
 
+    @Override
     @Parameter(excluded = true)
     public Boolean isDefault() {
         return isDefault;
     }
 
-    @Deprecated
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     @Parameter(excluded = true)
     public String getHost() {
         return host;
@@ -240,6 +236,14 @@ public class ProviderConfig extends AbstractServiceConfig {
         this.iothreads = iothreads;
     }
 
+    public Integer getAlive() {
+        return alive;
+    }
+
+    public void setAlive(Integer alive) {
+        this.alive = alive;
+    }
+
     public Integer getQueues() {
         return queues;
     }
@@ -425,4 +429,35 @@ public class ProviderConfig extends AbstractServiceConfig {
         this.wait = wait;
     }
 
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("ProviderConfig{");
+        sb.append("host='").append(host).append('\'');
+        sb.append(", port=").append(port);
+        sb.append(", contextpath='").append(contextpath).append('\'');
+        sb.append(", threadpool='").append(threadpool).append('\'');
+        sb.append(", threadname='").append(threadname).append('\'');
+        sb.append(", threads=").append(threads);
+        sb.append(", iothreads=").append(iothreads);
+        sb.append(", alive=").append(alive);
+        sb.append(", queues=").append(queues);
+        sb.append(", accepts=").append(accepts);
+        sb.append(", codec='").append(codec).append('\'');
+        sb.append(", charset='").append(charset).append('\'');
+        sb.append(", payload=").append(payload);
+        sb.append(", buffer=").append(buffer);
+        sb.append(", transporter='").append(transporter).append('\'');
+        sb.append(", exchanger='").append(exchanger).append('\'');
+        sb.append(", dispatcher='").append(dispatcher).append('\'');
+        sb.append(", networker='").append(networker).append('\'');
+        sb.append(", server='").append(server).append('\'');
+        sb.append(", client='").append(client).append('\'');
+        sb.append(", telnet='").append(telnet).append('\'');
+        sb.append(", prompt='").append(prompt).append('\'');
+        sb.append(", status='").append(status).append('\'');
+        sb.append(", wait=").append(wait);
+        sb.append(", isDefault=").append(isDefault);
+        sb.append('}');
+        return sb.toString();
+    }
 }
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 e52b060..e5ab4c3 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
@@ -43,11 +43,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
     private static final long serialVersionUID = -5864351140409987595L;
 
     /**
-     * The interface name of the reference service
-     */
-    protected String interfaceName;
-
-    /**
      * The interface class of the reference service
      */
     protected Class<?> interfaceClass;
@@ -72,7 +67,6 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
      */
     protected String protocol;
 
-    protected ServiceMetadata serviceMetadata;
 
     public ReferenceConfigBase() {
         serviceMetadata = new ServiceMetadata();
@@ -268,12 +262,14 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
 
     @Override
     protected void computeValidRegistryIds() {
-        super.computeValidRegistryIds();
-        if (StringUtils.isEmpty(getRegistryIds())) {
-            if (getConsumer() != null && StringUtils.isNotEmpty(getConsumer().getRegistryIds())) {
-                setRegistryIds(getConsumer().getRegistryIds());
+        if (consumer != null) {
+            if (notHasSelfRegistryProperty()) {
+                setRegistries(consumer.getRegistries());
+                setRegistryIds(consumer.getRegistryIds());
             }
         }
+
+        super.computeValidRegistryIds();
     }
 
     @Parameter(excluded = true)
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 c84f20a..9fcdec2 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
@@ -140,11 +140,6 @@ public class RegistryConfig extends AbstractConfig {
     private Map<String, String> parameters;
 
     /**
-     * Whether it's default
-     */
-    private Boolean isDefault;
-
-    /**
      * Simple the registry. both useful for provider and consumer
      *
      * @since 2.7.0
@@ -456,14 +451,6 @@ public class RegistryConfig extends AbstractConfig {
         }
     }
 
-    public Boolean isDefault() {
-        return isDefault;
-    }
-
-    public void setDefault(Boolean isDefault) {
-        this.isDefault = isDefault;
-    }
-
     public Boolean getSimplified() {
         return simplified;
     }
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 f1b14d6..e6705ef 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
@@ -43,10 +43,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
 
     private static final long serialVersionUID = 3033787999037024738L;
 
-    /**
-     * The interface name of the exported service
-     */
-    protected String interfaceName;
+
 
     /**
      * The interface class of the exported service
@@ -78,7 +75,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
      */
     protected volatile String generic;
 
-    protected ServiceMetadata serviceMetadata;
+
 
     public ServiceConfigBase() {
         serviceMetadata = new ServiceMetadata();
@@ -202,32 +199,35 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
     }
 
     public void checkProtocol() {
+        if (provider != null && notHasSelfProtocolProperty()) {
+            setProtocols(provider.getProtocols());
+            setProtocolIds(provider.getProtocolIds());
+        }
+
         if (CollectionUtils.isEmpty(protocols) && provider != null) {
             setProtocols(provider.getProtocols());
         }
         convertProtocolIdsToProtocols();
     }
 
+    private boolean notHasSelfProtocolProperty() {
+        return CollectionUtils.isEmpty(protocols) && StringUtils.isEmpty(protocolIds);
+    }
+
     public void completeCompoundConfigs() {
         super.completeCompoundConfigs(provider);
         if (provider != null) {
-            if (protocols == null) {
+            if (notHasSelfProtocolProperty()) {
                 setProtocols(provider.getProtocols());
+                setProtocolIds(provider.getProtocolIds());
             }
             if (configCenter == null) {
                 setConfigCenter(provider.getConfigCenter());
             }
-            if (StringUtils.isEmpty(registryIds)) {
-                setRegistryIds(provider.getRegistryIds());
-            }
-            if (StringUtils.isEmpty(protocolIds)) {
-                setProtocolIds(provider.getProtocolIds());
-            }
         }
     }
 
     private void convertProtocolIdsToProtocols() {
-        computeValidProtocolIds();
         if (StringUtils.isEmpty(protocolIds)) {
             if (CollectionUtils.isEmpty(protocols)) {
                 List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
@@ -292,9 +292,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
         setInterface(interfaceClass);
     }
 
-    public String getInterface() {
-        return interfaceName;
-    }
+
 
     public void setInterface(Class<?> interfaceClass) {
         if (interfaceClass != null && !interfaceClass.isInterface()) {
@@ -304,14 +302,6 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
         setInterface(interfaceClass == null ? null : interfaceClass.getName());
     }
 
-    public void setInterface(String interfaceName) {
-        this.interfaceName = interfaceName;
-        // FIXME, add id strategy in ConfigManager
-//        if (StringUtils.isEmpty(id)) {
-//            id = interfaceName;
-//        }
-    }
-
     public T getRef() {
         return ref;
     }
@@ -413,22 +403,14 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
         return StringUtils.isEmpty(this.version) ? (provider != null ? provider.getVersion() : this.version) : this.version;
     }
 
-    private void computeValidProtocolIds() {
-        if (StringUtils.isEmpty(getProtocolIds())) {
-            if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getProtocolIds())) {
-                setProtocolIds(getProvider().getProtocolIds());
-            }
-        }
-    }
-
     @Override
     protected void computeValidRegistryIds() {
-        super.computeValidRegistryIds();
-        if (StringUtils.isEmpty(getRegistryIds())) {
-            if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getRegistryIds())) {
-                setRegistryIds(getProvider().getRegistryIds());
-            }
+        if (provider != null && notHasSelfRegistryProperty()) {
+            setRegistries(provider.getRegistries());
+            setRegistryIds(provider.getRegistryIds());
         }
+
+        super.computeValidRegistryIds();
     }
 
     public abstract void export();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java
index 3be7d3e..83f8659 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/SslConfig.java
@@ -18,10 +18,10 @@ package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.IOUtils;
 import org.apache.dubbo.config.support.Parameter;
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.io.InputStream;
 import java.util.concurrent.atomic.AtomicBoolean;
 
@@ -120,9 +120,9 @@ public class SslConfig extends AbstractConfig {
         this.clientTrustCertCollectionPath = clientTrustCertCollectionPath;
     }
 
-    public InputStream getServerKeyCertChainPathStream() throws FileNotFoundException {
+    public InputStream getServerKeyCertChainPathStream() throws IOException {
         if (serverKeyCertChainPath != null) {
-            serverKeyCertChainPathStream = new FileInputStream(serverKeyCertChainPath);
+            serverKeyCertChainPathStream = IOUtils.getURL(serverKeyCertChainPath).openStream();
         }
         return serverKeyCertChainPathStream;
     }
@@ -131,9 +131,9 @@ public class SslConfig extends AbstractConfig {
         this.serverKeyCertChainPathStream = serverKeyCertChainPathStream;
     }
 
-    public InputStream getServerPrivateKeyPathStream() throws FileNotFoundException {
+    public InputStream getServerPrivateKeyPathStream() throws IOException {
         if (serverPrivateKeyPath != null) {
-            serverPrivateKeyPathStream = new FileInputStream(serverPrivateKeyPath);
+            serverPrivateKeyPathStream = IOUtils.getURL(serverPrivateKeyPath).openStream();
         }
         return serverPrivateKeyPathStream;
     }
@@ -142,9 +142,9 @@ public class SslConfig extends AbstractConfig {
         this.serverPrivateKeyPathStream = serverPrivateKeyPathStream;
     }
 
-    public InputStream getServerTrustCertCollectionPathStream() throws FileNotFoundException {
+    public InputStream getServerTrustCertCollectionPathStream() throws IOException {
         if (serverTrustCertCollectionPath != null) {
-            serverTrustCertCollectionPathStream = new FileInputStream(serverTrustCertCollectionPath);
+            serverTrustCertCollectionPathStream = IOUtils.getURL(serverTrustCertCollectionPath).openStream();
         }
         return serverTrustCertCollectionPathStream;
     }
@@ -153,9 +153,9 @@ public class SslConfig extends AbstractConfig {
         this.serverTrustCertCollectionPathStream = serverTrustCertCollectionPathStream;
     }
 
-    public InputStream getClientKeyCertChainPathStream() throws FileNotFoundException {
+    public InputStream getClientKeyCertChainPathStream() throws IOException {
         if (clientKeyCertChainPath != null) {
-            clientKeyCertChainPathStream = new FileInputStream(clientKeyCertChainPath);
+            clientKeyCertChainPathStream = IOUtils.getURL(clientKeyCertChainPath).openStream();
         }
         return clientKeyCertChainPathStream;
     }
@@ -164,9 +164,9 @@ public class SslConfig extends AbstractConfig {
         this.clientKeyCertChainPathStream = clientKeyCertChainPathStream;
     }
 
-    public InputStream getClientPrivateKeyPathStream() throws FileNotFoundException {
+    public InputStream getClientPrivateKeyPathStream() throws IOException {
         if (clientPrivateKeyPath != null) {
-            clientPrivateKeyPathStream = new FileInputStream(clientPrivateKeyPath);
+            clientPrivateKeyPathStream = IOUtils.getURL(clientPrivateKeyPath).openStream();
         }
         return clientPrivateKeyPathStream;
     }
@@ -175,9 +175,9 @@ public class SslConfig extends AbstractConfig {
         this.clientPrivateKeyPathStream = clientPrivateKeyPathStream;
     }
 
-    public InputStream getClientTrustCertCollectionPathStream() throws FileNotFoundException {
+    public InputStream getClientTrustCertCollectionPathStream() throws IOException {
         if (clientTrustCertCollectionPath != null) {
-            clientTrustCertCollectionPathStream = new FileInputStream(clientTrustCertCollectionPath);
+            clientTrustCertCollectionPathStream = IOUtils.getURL(clientTrustCertCollectionPath).openStream();
         }
         return clientTrustCertCollectionPathStream;
     }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
index 404c454..44fbab5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.config.annotation;
 
+import org.apache.dubbo.common.constants.ClusterRules;
+import org.apache.dubbo.common.constants.LoadbalanceRules;
 import org.apache.dubbo.common.constants.RegistryConstants;
 import org.apache.dubbo.config.ReferenceConfigBase;
 
@@ -163,8 +165,9 @@ public @interface DubboReference {
 
     /**
      * Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
+     * you can use {@link org.apache.dubbo.common.constants.ClusterRules#FAIL_FAST} ……
      */
-    String cluster() default "";
+    String cluster() default ClusterRules.EMPTY;
 
     /**
      * Maximum connections service provider can accept, default value is 0 - connection is shared
@@ -207,10 +210,9 @@ public @interface DubboReference {
 
     /**
      * Load balance strategy, legal values include: random, roundrobin, leastactive
-     * <p>
-     * see Constants#DEFAULT_LOADBALANCE
+     * you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM} ……
      */
-    String loadbalance() default "";
+    String loadbalance() default LoadbalanceRules.EMPTY;
 
     /**
      * Whether to enable async invocation, default value is false
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java
index 33178ed..3eeaa71 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboService.java
@@ -17,6 +17,8 @@
 package org.apache.dubbo.config.annotation;
 
 
+import org.apache.dubbo.common.constants.ClusterRules;
+
 import java.lang.annotation.Documented;
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Inherited;
@@ -123,8 +125,9 @@ public @interface DubboService {
 
     /**
      * Cluster strategy, legal values include: failover, failfast, failsafe, failback, forking
+     * you can use {@link org.apache.dubbo.common.constants.ClusterRules#FAIL_FAST} ……
      */
-    String cluster() default "";
+    String cluster() default ClusterRules.EMPTY;
 
     /**
      * How the proxy is generated, legal values include: jdk, javassist
@@ -173,9 +176,9 @@ public @interface DubboService {
     /**
      * Load balance strategy, legal values include: random, roundrobin, leastactive
      *
-     * @see org.apache.dubbo.common.constants.CommonConstants#DEFAULT_LOADBALANCE
+     * you can use {@link org.apache.dubbo.common.constants.LoadbalanceRules#RANDOM} ……
      */
-    String loadbalance() default "";
+    String loadbalance() default ClusterRules.EMPTY;
 
     /**
      * Whether to enable async invocation, default value is false
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigConfigurationAdapter.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigConfigurationAdapter.java
index dca7978..3251f63 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigConfigurationAdapter.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigConfigurationAdapter.java
@@ -32,7 +32,7 @@ public class ConfigConfigurationAdapter implements Configuration {
 
     public ConfigConfigurationAdapter(AbstractConfig config) {
         Map<String, String> configMetadata = config.getMetaData();
-        metaData = new HashMap<>(configMetadata.size());
+        metaData = new HashMap<>(configMetadata.size(), 1.0f);
         for (Map.Entry<String, String> entry : configMetadata.entrySet()) {
             String prefix = config.getPrefix().endsWith(".") ? config.getPrefix() : config.getPrefix() + ".";
             String id = StringUtils.isEmpty(config.getId()) ? "" : config.getId() + ".";
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 e62ef97..39dacbb 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
@@ -46,6 +46,7 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -386,9 +387,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
     }
 
     public void clear() {
-        write(() -> {
-            this.configsCache.clear();
-        });
+        write(this.configsCache::clear);
     }
 
     /**
@@ -442,6 +441,18 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
 //                throw new IllegalStateException("No such " + configType.getName() + " is found");
                 return null;
             } else if (size > 1) {
+                AtomicReference<C> defaultConfig = new AtomicReference<>();
+                configsMap.forEach((str, config) -> {
+                    if (Boolean.TRUE.equals(config.isDefault())) {
+                        defaultConfig.compareAndSet(null, config);
+                    }
+                });
+
+                if (defaultConfig.get() != null) {
+                    return defaultConfig.get();
+                }
+
+
                 if (configWarnLogEnabled && warnLogStatus.get(configType) == null) {
                     logger.warn("Expected single matching of " + configType + ", but found " + size + " instances, will randomly pick the first one.");
                     warnLogStatus.put(configType, true);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java b/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
index 773f532..de14ef2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
@@ -23,6 +23,7 @@ package org.apache.dubbo.event;
  * @since 2.7.5
  */
 public final class DirectEventDispatcher extends AbstractEventDispatcher {
+    public static final String NAME = "direct";
 
     public DirectEventDispatcher() {
         super(DIRECT_EXECUTOR);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/EventDispatcher.java b/dubbo-common/src/main/java/org/apache/dubbo/event/EventDispatcher.java
index 53e0813..f6f2631 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/EventDispatcher.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/event/EventDispatcher.java
@@ -29,7 +29,7 @@ import java.util.concurrent.Executor;
  * @see DirectEventDispatcher
  * @since 2.7.5
  */
-@SPI("direct")
+@SPI(DirectEventDispatcher.NAME)
 public interface EventDispatcher extends Listenable<EventListener<?>> {
 
     /**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/ParallelEventDispatcher.java b/dubbo-common/src/main/java/org/apache/dubbo/event/ParallelEventDispatcher.java
index 082bb99..7a7e725 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/ParallelEventDispatcher.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/event/ParallelEventDispatcher.java
@@ -25,6 +25,7 @@ import java.util.concurrent.ForkJoinPool;
  * @since 2.7.5
  */
 public class ParallelEventDispatcher extends AbstractEventDispatcher {
+    public static final String NAME = "parallel";
 
     public ParallelEventDispatcher() {
         super(ForkJoinPool.commonPool());
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
index 85920e2..7b983be 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/support/ProtocolUtils.java
@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentMap;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_RAW_RETURN;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_BEAN;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_DEFAULT;
+import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_GSON;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_NATIVE_JAVA;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_PROTOBUF;
 
@@ -56,6 +57,7 @@ public class ProtocolUtils {
                 || GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic) /* Streaming generalization call supporting jdk serialization */
                 || GENERIC_SERIALIZATION_BEAN.equalsIgnoreCase(generic)
                 || GENERIC_SERIALIZATION_PROTOBUF.equalsIgnoreCase(generic)
+                || GENERIC_SERIALIZATION_GSON.equalsIgnoreCase(generic)
                 || GENERIC_RAW_RETURN.equalsIgnoreCase(generic));
 
     }
@@ -75,6 +77,11 @@ public class ProtocolUtils {
                 && GENERIC_SERIALIZATION_NATIVE_JAVA.equalsIgnoreCase(generic);
     }
 
+    public static boolean isGsonGenericSerialization(String generic) {
+        return isGeneric(generic)
+                && GENERIC_SERIALIZATION_GSON.equalsIgnoreCase(generic);
+    }
+
     public static boolean isBeanGenericSerialization(String generic) {
         return isGeneric(generic) && GENERIC_SERIALIZATION_BEAN.equals(generic);
     }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java
new file mode 100644
index 0000000..1075aec
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/BaseServiceMetadataTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_VERSION;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+public class BaseServiceMetadataTest {
+
+    @Test
+    public void test() {
+        BaseServiceMetadata baseServiceMetadata = new BaseServiceMetadata();
+        baseServiceMetadata.setGroup("group1");
+        baseServiceMetadata.setServiceInterfaceName("org.apache.dubbo.common.TestInterface");
+        baseServiceMetadata.setVersion("1.0.0");
+        baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", "group1", "1.0.0"));
+
+        assertEquals(baseServiceMetadata.getGroup(), "group1");
+        assertEquals(baseServiceMetadata.getServiceInterfaceName(), "org.apache.dubbo.common.TestInterface");
+        assertEquals(baseServiceMetadata.getVersion(), "1.0.0");
+        assertEquals(baseServiceMetadata.getServiceKey(), "group1/org.apache.dubbo.common.TestInterface:1.0.0");
+        assertEquals(baseServiceMetadata.getDisplayServiceKey(), "org.apache.dubbo.common.TestInterface:1.0.0");
+
+        baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", null, null));
+        assertEquals(baseServiceMetadata.getServiceKey(), "org.apache.dubbo.common.TestInterface");
+        baseServiceMetadata.setServiceKey(BaseServiceMetadata.buildServiceKey("org.apache.dubbo.common.TestInterface", "", ""));
+        assertEquals(baseServiceMetadata.getServiceKey(), "org.apache.dubbo.common.TestInterface");
+
+
+        baseServiceMetadata.setVersion("2.0.0");
+        baseServiceMetadata.generateServiceKey();
+        assertEquals(baseServiceMetadata.getServiceKey(), "group1/org.apache.dubbo.common.TestInterface:2.0.0");
+
+        assertEquals(BaseServiceMetadata.versionFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "1.0.0");
+        assertEquals(BaseServiceMetadata.groupFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "group1");
+        assertEquals(BaseServiceMetadata.interfaceFromServiceKey("group1/org.apache.dubbo.common.TestInterface:1.0.0"), "org.apache.dubbo.common.TestInterface");
+
+        assertEquals(DEFAULT_VERSION, BaseServiceMetadata.versionFromServiceKey(""));
+        assertNull(BaseServiceMetadata.groupFromServiceKey(""));
+        assertEquals(BaseServiceMetadata.interfaceFromServiceKey(""), "");
+
+        assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0").getDisplayServiceKey(),
+                "org.apache.dubbo.common.TestInterface:1.0.0");
+        assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface").getDisplayServiceKey(),
+                "org.apache.dubbo.common.TestInterface:null");
+        assertEquals(BaseServiceMetadata.revertDisplayServiceKey(null).getDisplayServiceKey(),"null:null");
+        assertEquals(BaseServiceMetadata.revertDisplayServiceKey("org.apache.dubbo.common.TestInterface:1.0.0:1").getDisplayServiceKey(),"null:null");
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/PojoUtilsForNonPublicStaticTest.java
similarity index 54%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/PojoUtilsForNonPublicStaticTest.java
index 051363b..8e1e5a56 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/PojoUtilsForNonPublicStaticTest.java
@@ -14,29 +14,37 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.common;
 
-import org.junit.jupiter.api.Test;
+import org.apache.dubbo.common.utils.PojoUtils;
 
-import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
 
-/**
- * {@link MemberUtils} Test
- *
- * @since 2.7.6
- */
-public class MemberUtilsTest {
+public class PojoUtilsForNonPublicStaticTest {
 
     @Test
-    public void testIsStatic() throws NoSuchMethodException {
-
-        assertFalse(isStatic(getClass().getMethod("testIsStatic")));
-        assertTrue(isStatic(getClass().getMethod("staticMethod")));
+    public void testNonPublicStaticClass() {
+        NonPublicStaticData nonPublicStaticData = new NonPublicStaticData("horizon");
+        PojoUtils.generalize(nonPublicStaticData);
     }
 
-    public static void staticMethod() {
+    /**
+     * the static class need is not same package with PojoUtils, so define it here.
+     */
+    static class NonPublicStaticData {
+
+        private String name;
+
+        public NonPublicStaticData(String name) {
+            this.name = name;
+        }
+
+        public String getName() {
+            return name;
+        }
 
+        public void setName(String name) {
+            this.name = name;
+        }
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/URLStrParserTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/URLStrParserTest.java
index 3ca62ce..f295de9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/URLStrParserTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/URLStrParserTest.java
@@ -16,8 +16,13 @@
  */
 package org.apache.dubbo.common;
 
+import net.bytebuddy.utility.RandomString;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import java.util.HashSet;
+import java.util.Set;
+
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
 
@@ -25,16 +30,53 @@ import static org.hamcrest.MatcherAssert.assertThat;
  * Created by LinShunkang on 2020/03/12
  */
 public class URLStrParserTest {
+    private static Set<String> testCases = new HashSet<>(16);
+    private static Set<String> errorDecodedCases = new HashSet<>(8);
+    private static Set<String> errorEncodedCases = new HashSet<>(8);
+
+    static {
+        testCases.add("dubbo://192.168.1.1");
+        testCases.add("dubbo://192.168.1.1?");
+        testCases.add("dubbo://127.0.0.1?test=中文测试");
+        testCases.add("dubbo://admin:admin123@192.168.1.41:28113/org.test.api.DemoService$Iface?anyhost=true&application=demo-service&dubbo=2.6.1&generic=false&interface=org.test.api.DemoService$Iface&methods=orbCompare,checkText,checkPicture&pid=65557&revision=1.4.17&service.filter=bootMetrics&side=provider&status=server&threads=200&timestamp=1583136298859&version=1.0.0");
+        // super long text test
+        testCases.add("dubbo://192.168.1.1/" + RandomString.make(10240));
+        testCases.add("file:/path/to/file.txt");
+        testCases.add("dubbo://fe80:0:0:0:894:aeec:f37d:23e1%en0/path?abc=abc");
+
+        errorDecodedCases.add("dubbo:192.168.1.1");
+        errorDecodedCases.add("://192.168.1.1");
+        errorDecodedCases.add(":/192.168.1.1");
+
+        errorEncodedCases.add("dubbo%3a%2f%2f192.168.1.41%3fabc%3");
+        errorEncodedCases.add("dubbo%3a192.168.1.1%3fabc%3dabc");
+        errorEncodedCases.add("%3a%2f%2f192.168.1.1%3fabc%3dabc");
+        errorEncodedCases.add("%3a%2f192.168.1.1%3fabc%3dabc");
+        errorEncodedCases.add("dubbo%3a%2f%2f127.0.0.1%3ftest%3d%e2%96%b2%e2%96%bc%e2%97%80%e2%96%b6%e2%86%90%e2%86%91%e2%86%92%e2%86%93%e2%86%94%e2%86%95%e2%88%9e%c2%b1%e9%be%98%e9%9d%90%e9%bd%89%9%d%b");
+    }
 
     @Test
-    public void test() {
-        String str = "dubbo%3A%2F%2Fadmin%3Aadmin123%40192.168.1.41%3A28113%2Forg.test.api.DemoService%24Iface%3Fanyhost%3Dtrue%26application%3Ddemo-service%26dubbo%3D2.6.1%26generic%3Dfalse%26interface%3Dorg.test.api.DemoService%24Iface%26methods%3DorbCompare%2CcheckText%2CcheckPicture%26pid%3D65557%26revision%3D1.4.17%26service.filter%3DbootMetrics%26side%3Dprovider%26status%3Dserver%26threads%3D200%26timestamp%3D1583136298859%26version%3D1.0.0";
-        System.out.println(URLStrParser.parseEncodedStr(str));
-
-        String decodeStr = URL.decode(str);
-        URL originalUrl = URL.valueOf(decodeStr);
-        assertThat(URLStrParser.parseEncodedStr(str), equalTo(originalUrl));
-        assertThat(URLStrParser.parseDecodedStr(decodeStr), equalTo(originalUrl));
+    public void testEncoded() {
+        testCases.forEach(testCase -> {
+            assertThat(URLStrParser.parseEncodedStr(URL.encode(testCase)), equalTo(URL.valueOf(testCase)));
+        });
+
+        errorEncodedCases.forEach(errorCase -> {
+            Assertions.assertThrows(RuntimeException.class,
+                    () -> URLStrParser.parseEncodedStr(errorCase));
+        });
+    }
+
+    @Test
+    public void testDecoded() {
+        testCases.forEach(testCase -> {
+            assertThat(URLStrParser.parseDecodedStr(testCase), equalTo(URL.valueOf(testCase)));
+        });
+
+        errorDecodedCases.forEach(errorCase -> {
+            Assertions.assertThrows(RuntimeException.class,
+                    () -> URLStrParser.parseDecodedStr(errorCase));
+        });
     }
 
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
index e8932c3..a34045e 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
@@ -32,6 +32,8 @@ import static org.hamcrest.CoreMatchers.anyOf;
 import static org.hamcrest.CoreMatchers.equalTo;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -929,5 +931,115 @@ public class URLTest {
 
         URL url5 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&weight=10&group=group&version=1.0.0");
         Assertions.assertEquals(url4, url5);
+
+        URL url6 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=1599556506417");
+        URL url7 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertEquals(url6, url7);
+
+        URL url8 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertNotEquals(url7, url8);
+
+        URL url9 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertNotEquals(url8, url9);
+
+    }
+
+
+    @Test
+    public void testEqualsWithPassword() {
+        URL url1 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url2 = URL.valueOf("ad@min:hello@4321@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url3 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+
+        boolean actual1 = url1.equals(url2);
+        boolean actual2 = url1.equals(url3);
+        assertFalse(actual1);
+        assertTrue(actual2);
+    }
+
+    @Test
+    public void testEqualsWithPath() {
+        URL url1 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path1?version=1.0.0&application=morgan");
+        URL url2 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path2?version=1.0.0&application=morgan");
+        URL url3 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path1?version=1.0.0&application=morgan");
+
+        boolean actual1 = url1.equals(url2);
+        boolean actual2 = url1.equals(url3);
+        assertFalse(actual1);
+        assertTrue(actual2);
+    }
+
+    @Test
+    public void testEqualsWithPort() {
+        URL url1 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url2 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20881/context/path?version=1.0.0&application=morgan");
+        URL url3 = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+
+        boolean actual1 = url1.equals(url2);
+        boolean actual2 = url1.equals(url3);
+        assertFalse(actual1);
+        assertTrue(actual2);
     }
+
+    @Test
+    public void testEqualsWithProtocol() {
+        URL url1 = URL.valueOf("dubbo://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url2 = URL.valueOf("file://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url3 = URL.valueOf("dubbo://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+
+        boolean actual1 = url1.equals(url2);
+        boolean actual2 = url1.equals(url3);
+        assertFalse(actual1);
+        assertTrue(actual2);
+    }
+
+    @Test
+    public void testEqualsWithUser() {
+        URL url1 = URL.valueOf("ad@min1:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url2 = URL.valueOf("ad@min2:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+        URL url3 = URL.valueOf("ad@min1:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+
+        boolean actual1 = url1.equals(url2);
+        boolean actual2 = url1.equals(url3);
+        assertFalse(actual1);
+        assertTrue(actual2);
+    }
+    @Test
+    public void testHashcode() {
+        URL url1 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=1599556506417");
+        URL url2 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&generic=true&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertEquals(url1.hashCode(), url2.hashCode());
+
+        URL url3 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=false&dubbo=2.0.2&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertNotEquals(url2.hashCode(), url3.hashCode());
+
+        URL url4 = URL.valueOf("consumer://30.225.20.150/org.apache.dubbo.rpc.service.GenericService?application=" +
+                "dubbo-demo-api-consumer&category=consumers&check=true&dubbo=2.0.2&interface=" +
+                "org.apache.dubbo.demo.DemoService&pid=7375&side=consumer&sticky=false&timestamp=2299556506417");
+        assertNotEquals(url3.hashCode(), url4.hashCode());
+    }
+
+    @Test
+    public void testParameterContainPound() {
+        URL url = URL.valueOf(
+                "dubbo://ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&pound=abcd#efg&protocol=registry");
+        Assertions.assertEquals("abcd#efg", url.getParameter("pound"));
+        Assertions.assertEquals("registry", url.getParameter("protocol"));
+    }
+
+
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java
index d3c4d90..cc246f8 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/bytecode/WrapperTest.java
@@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.fail;
 
 public class WrapperTest {
@@ -114,6 +115,26 @@ public class WrapperTest {
     }
 
     @Test
+    public void testOverloadMethod() throws Exception {
+        Wrapper w = Wrapper.getWrapper(I2.class);
+        assertEquals(2, w.getMethodNames().length);
+
+        Impl2 impl = new Impl2();
+
+        w.invokeMethod(impl, "setFloat", new Class[]{float.class}, new Object[]{1F});
+        assertEquals(1F, impl.getFloat1());
+        assertNull(impl.getFloat2());
+
+        w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{2f});
+        assertEquals(1F, impl.getFloat1());
+        assertEquals(2F, impl.getFloat2());
+
+        w.invokeMethod(impl, "setFloat", new Class[]{Float.class}, new Object[]{null});
+        assertEquals(1F, impl.getFloat1());
+        assertNull(impl.getFloat2());
+    }
+
+    @Test
     public void test_getDeclaredMethodNames_ContainExtendsParentMethods() throws Exception {
         assertArrayEquals(new String[]{"hello",}, Wrapper.getWrapper(Parent1.class).getMethodNames());
 
@@ -141,6 +162,12 @@ public class WrapperTest {
         void setFloat(float f);
     }
 
+    public interface I2 {
+        void setFloat(float f);
+
+        void setFloat(Float f);
+    }
+
     public interface EmptyService {
     }
 
@@ -191,6 +218,29 @@ public class WrapperTest {
         }
     }
 
+    public static class Impl2 implements I2 {
+        private float float1;
+        private Float float2;
+
+        @Override
+        public void setFloat(float f) {
+            this.float1 = f;
+        }
+
+        @Override
+        public void setFloat(Float f) {
+            this.float2 = f;
+        }
+
+        public float getFloat1() {
+            return float1;
+        }
+
+        public Float getFloat2() {
+            return float2;
+        }
+    }
+
     public static class EmptyServiceImpl implements EmptyService {
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JdkCompilerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JdkCompilerTest.java
index b95e645..e0bc3a9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JdkCompilerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/JdkCompilerTest.java
@@ -53,4 +53,35 @@ public class JdkCompilerTest extends JavaCodeTest {
             Assertions.assertEquals("Hello world!", sayHello.invoke(instance));
         });
     }
+
+    @Test
+    public void test_compileJavaClass_java8() throws Exception {
+        JdkCompiler compiler = new JdkCompiler("1.8");
+        Class<?> clazz = compiler.compile(getSimpleCode(), JdkCompiler.class.getClassLoader());
+        Object instance = clazz.newInstance();
+        Method sayHello = instance.getClass().getMethod("sayHello");
+        Assertions.assertEquals("Hello world!", sayHello.invoke(instance));
+    }
+
+    @Test
+    public void test_compileJavaClass0_java8() throws Exception {
+        Assertions.assertThrows(IllegalStateException.class, () -> {
+            JdkCompiler compiler = new JdkCompiler("1.8");
+            Class<?> clazz = compiler.compile(getSimpleCodeWithoutPackage(), JdkCompiler.class.getClassLoader());
+            Object instance = clazz.newInstance();
+            Method sayHello = instance.getClass().getMethod("sayHello");
+            Assertions.assertEquals("Hello world!", sayHello.invoke(instance));
+        });
+    }
+
+    @Test
+    public void test_compileJavaClass1_java8() throws Exception {
+        Assertions.assertThrows(IllegalStateException.class, () -> {
+            JdkCompiler compiler = new JdkCompiler("1.8");
+            Class<?> clazz = compiler.compile(getSimpleCodeWithSyntax(), JdkCompiler.class.getClassLoader());
+            Object instance = clazz.newInstance();
+            Method sayHello = instance.getClass().getMethod("sayHello");
+            Assertions.assertEquals("Hello world!", sayHello.invoke(instance));
+        });
+    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEventTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEventTest.java
index 9154927..7725399 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEventTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/ConfigChangedEventTest.java
@@ -28,28 +28,28 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
  */
 public class ConfigChangedEventTest {
 
-    private static final String key = "k";
+    private static final String KEY = "k";
 
-    private static final String group = "g";
+    private static final String GROUP = "g";
 
-    private static final String content = "c";
+    private static final String CONTENT = "c";
 
     @Test
     public void testGetter() {
 
-        ConfigChangedEvent event = new ConfigChangedEvent(key, group, content);
+        ConfigChangedEvent event = new ConfigChangedEvent(KEY, GROUP, CONTENT);
 
-        assertEquals(key, event.getKey());
-        assertEquals(group, event.getGroup());
-        assertEquals(content, event.getContent());
+        assertEquals(KEY, event.getKey());
+        assertEquals(GROUP, event.getGroup());
+        assertEquals(CONTENT, event.getContent());
         assertEquals(ConfigChangeType.MODIFIED, event.getChangeType());
         assertEquals("k,g", event.getSource());
 
-        event = new ConfigChangedEvent(key, group, content, ConfigChangeType.ADDED);
+        event = new ConfigChangedEvent(KEY, GROUP, CONTENT, ConfigChangeType.ADDED);
 
-        assertEquals(key, event.getKey());
-        assertEquals(group, event.getGroup());
-        assertEquals(content, event.getContent());
+        assertEquals(KEY, event.getKey());
+        assertEquals(GROUP, event.getGroup());
+        assertEquals(CONTENT, event.getContent());
         assertEquals(ConfigChangeType.ADDED, event.getChangeType());
         assertEquals("k,g", event.getSource());
     }
@@ -57,15 +57,15 @@ public class ConfigChangedEventTest {
     @Test
     public void testEqualsAndHashCode() {
         for (ConfigChangeType type : ConfigChangeType.values()) {
-            assertEquals(new ConfigChangedEvent(key, group, content, type), new ConfigChangedEvent(key, group, content, type));
-            assertEquals(new ConfigChangedEvent(key, group, content, type).hashCode(), new ConfigChangedEvent(key, group, content, type).hashCode());
-            assertEquals(new ConfigChangedEvent(key, group, content, type).toString(), new ConfigChangedEvent(key, group, content, type).toString());
+            assertEquals(new ConfigChangedEvent(KEY, GROUP, CONTENT, type), new ConfigChangedEvent(KEY, GROUP, CONTENT, type));
+            assertEquals(new ConfigChangedEvent(KEY, GROUP, CONTENT, type).hashCode(), new ConfigChangedEvent(KEY, GROUP, CONTENT, type).hashCode());
+            assertEquals(new ConfigChangedEvent(KEY, GROUP, CONTENT, type).toString(), new ConfigChangedEvent(KEY, GROUP, CONTENT, type).toString());
         }
     }
 
     @Test
     public void testToString() {
-        ConfigChangedEvent event = new ConfigChangedEvent(key, group, content);
+        ConfigChangedEvent event = new ConfigChangedEvent(KEY, GROUP, CONTENT);
         assertNotNull(event.toString());
     }
 }
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 746cab7..e3be4f1 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
@@ -32,6 +32,8 @@ import org.apache.dubbo.common.extension.activate.impl.ValueActivateExtImpl;
 import org.apache.dubbo.common.extension.convert.String2BooleanConverter;
 import org.apache.dubbo.common.extension.convert.String2DoubleConverter;
 import org.apache.dubbo.common.extension.convert.String2IntegerConverter;
+import org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt;
+import org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt;
 import org.apache.dubbo.common.extension.ext1.SimpleExt;
 import org.apache.dubbo.common.extension.ext1.impl.SimpleExtImpl1;
 import org.apache.dubbo.common.extension.ext1.impl.SimpleExtImpl2;
@@ -256,6 +258,7 @@ public class ExtensionLoaderTest {
 
         assertThat(ext, instanceOf(AddExt1_ManualAdd1.class));
         assertEquals("Manual1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd1.class));
+        ExtensionLoader.resetExtensionLoader(AddExt1.class);
     }
 
     @Test
@@ -325,6 +328,7 @@ public class ExtensionLoaderTest {
             assertThat(ext, instanceOf(AddExt1_ManualAdd2.class));
             assertEquals("impl1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd2.class));
         }
+        ExtensionLoader.resetExtensionLoader(AddExt1.class);
     }
 
     @Test
@@ -338,6 +342,7 @@ public class ExtensionLoaderTest {
 
         adaptive = loader.getAdaptiveExtension();
         assertTrue(adaptive instanceof AddExt3_ManualAdaptive);
+        ExtensionLoader.resetExtensionLoader(AddExt3.class);
     }
 
     @Test
@@ -375,7 +380,7 @@ public class ExtensionLoaderTest {
             fail();
         } catch (IllegalStateException expected) {
             assertThat(expected.getMessage(), containsString("Failed to load extension class (interface: interface org.apache.dubbo.common.extension.ext7.InitErrorExt"));
-            assertThat(expected.getCause(), instanceOf(ExceptionInInitializerError.class));
+            assertThat(expected.getMessage(), containsString("java.lang.ExceptionInInitializerError"));
         }
     }
 
@@ -531,4 +536,88 @@ public class ExtensionLoaderTest {
         assertEquals(ServicesLoadingStrategy.class, loadingStrategy.getClass());
         assertEquals(Prioritized.MIN_PRIORITY, loadingStrategy.getPriority());
     }
+
+    @Test
+    public void testDuplicatedImplWithoutOverriddenStrategy() {
+        List<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
+        ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(false),
+                new DubboInternalLoadingStrategyTest(false));
+        ExtensionLoader<DuplicatedWithoutOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedWithoutOverriddenExt.class);
+        try {
+            extensionLoader.getExtension("duplicated");
+            fail();
+        } catch (IllegalStateException expected) {
+            assertThat(expected.getMessage(), containsString("Failed to load extension class (interface: interface org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt"));
+            assertThat(expected.getMessage(), containsString("cause: Duplicate extension org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt name duplicated"));
+        }finally {
+            //recover the loading strategies
+            ExtensionLoader.setLoadingStrategies(loadingStrategies.toArray(new LoadingStrategy[loadingStrategies.size()]));
+        }
+    }
+
+    @Test
+    public void testDuplicatedImplWithOverriddenStrategy() {
+        List<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
+        ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(true),
+                new DubboInternalLoadingStrategyTest(true));
+        ExtensionLoader<DuplicatedOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedOverriddenExt.class);
+        DuplicatedOverriddenExt duplicatedOverriddenExt = extensionLoader.getExtension("duplicated");
+        assertEquals("DuplicatedOverriddenExt1", duplicatedOverriddenExt.echo());
+        //recover the loading strategies
+        ExtensionLoader.setLoadingStrategies(loadingStrategies.toArray(new LoadingStrategy[loadingStrategies.size()]));
+    }
+
+    /**
+     * The external {@link LoadingStrategy}, which can set if it support overridden
+     */
+    private static class DubboExternalLoadingStrategyTest implements LoadingStrategy {
+
+        public DubboExternalLoadingStrategyTest(boolean overridden) {
+            this.overridden = overridden;
+        }
+
+        private boolean overridden;
+
+        @Override
+        public String directory() {
+            return "META-INF/dubbo/external/";
+        }
+
+        @Override
+        public boolean overridden() {
+            return this.overridden;
+        }
+
+        @Override
+        public int getPriority() {
+            return MAX_PRIORITY + 1;
+        }
+    }
+
+    /**
+     * The internal {@link LoadingStrategy}, which can set if it support overridden
+     */
+    private static class DubboInternalLoadingStrategyTest implements LoadingStrategy {
+
+        public DubboInternalLoadingStrategyTest(boolean overridden) {
+            this.overridden = overridden;
+        }
+
+        private boolean overridden;
+
+        @Override
+        public String directory() {
+            return "META-INF/dubbo/internal/";
+        }
+
+        @Override
+        public boolean overridden() {
+            return this.overridden;
+        }
+
+        @Override
+        public int getPriority() {
+            return MAX_PRIORITY;
+        }
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedOverriddenExt.java
similarity index 74%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedOverriddenExt.java
index d85f86b..628be21 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedOverriddenExt.java
@@ -14,11 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.duplicated;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ * This is an interface for testing duplicated extension
+ */
+@SPI
+public interface DuplicatedOverriddenExt {
+
+    String echo();
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedWithoutOverriddenExt.java
similarity index 72%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedWithoutOverriddenExt.java
index d85f86b..5a0cc0b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/DuplicatedWithoutOverriddenExt.java
@@ -14,11 +14,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.duplicated;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ * This is an interface for testing duplicated extension
+ * see issue: https://github.com/apache/dubbo/issues/3575
+ */
+@SPI
+public interface DuplicatedWithoutOverriddenExt {
+
+    String echo();
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt1.java
similarity index 72%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt1.java
index d85f86b..99e4db5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt1.java
@@ -14,11 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.duplicated.impl;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt;
+
+public class DuplicatedOverriddenExt1 implements DuplicatedOverriddenExt {
+
+    @Override
+    public String echo() {
+        return "DuplicatedOverriddenExt1";
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt2.java
similarity index 72%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt2.java
index d85f86b..2c9fd4e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedOverriddenExt2.java
@@ -14,11 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.duplicated.impl;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt;
+
+public class DuplicatedOverriddenExt2 implements DuplicatedOverriddenExt {
+
+    @Override
+    public String echo() {
+        return "DuplicatedOverriddenExt2";
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt1.java
similarity index 71%
copy from dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt1.java
index 773f532..ce08a86 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt1.java
@@ -14,17 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.event;
+package org.apache.dubbo.common.extension.duplicated.impl;
 
-/**
- * Direct {@link EventDispatcher} implementation uses current thread execution model
- *
- * @see EventDispatcher
- * @since 2.7.5
- */
-public final class DirectEventDispatcher extends AbstractEventDispatcher {
+import org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt;
+
+public class DuplicatedWithoutOverriddenExt1 implements DuplicatedWithoutOverriddenExt {
 
-    public DirectEventDispatcher() {
-        super(DIRECT_EXECUTOR);
+    @Override
+    public String echo() {
+        return "DuplicatedWithoutOverriddenExt1";
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt2.java
similarity index 71%
copy from dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt2.java
index 773f532..1aed1e5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/duplicated/impl/DuplicatedWithoutOverriddenExt2.java
@@ -14,17 +14,14 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.event;
+package org.apache.dubbo.common.extension.duplicated.impl;
 
-/**
- * Direct {@link EventDispatcher} implementation uses current thread execution model
- *
- * @see EventDispatcher
- * @since 2.7.5
- */
-public final class DirectEventDispatcher extends AbstractEventDispatcher {
+import org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt;
+
+public class DuplicatedWithoutOverriddenExt2 implements DuplicatedWithoutOverriddenExt {
 
-    public DirectEventDispatcher() {
-        super(DIRECT_EXECUTOR);
+    @Override
+    public String echo() {
+        return "DuplicatedWithoutOverriddenExt2";
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/Demo.java
similarity index 74%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/Demo.java
index d85f86b..b51e3e1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/Demo.java
@@ -14,11 +14,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.wrapper;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.SPI;
+
+@SPI("demo")
+public interface Demo {
+    String echo(String msg);
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/WrapperTest.java
similarity index 57%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/WrapperTest.java
index 051363b..a6f1a56 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/WrapperTest.java
@@ -14,29 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.common.extension.wrapper;
+
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.wrapper.impl.DemoWrapper;
+import org.apache.dubbo.common.extension.wrapper.impl.DemoWrapper2;
 
 import org.junit.jupiter.api.Test;
 
-import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
-import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
- * {@link MemberUtils} Test
+ * {@link org.apache.dubbo.common.extension.Wrapper} Test
  *
- * @since 2.7.6
+ * @since 2.7.5
  */
-public class MemberUtilsTest {
+public class WrapperTest {
 
     @Test
-    public void testIsStatic() throws NoSuchMethodException {
-
-        assertFalse(isStatic(getClass().getMethod("testIsStatic")));
-        assertTrue(isStatic(getClass().getMethod("staticMethod")));
-    }
-
-    public static void staticMethod() {
-
+    public void testWrapper() {
+        Demo demoWrapper = ExtensionLoader.getExtensionLoader(Demo.class).getExtension("demo");
+        assertTrue(demoWrapper instanceof DemoWrapper);
+        Demo demoWrapper2 = ExtensionLoader.getExtensionLoader(Demo.class).getExtension("demo2");
+        assertTrue(demoWrapper2 instanceof DemoWrapper2);
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoImpl.java
similarity index 74%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoImpl.java
index d85f86b..abcd5e6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/Constants.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoImpl.java
@@ -14,11 +14,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.config.configcenter;
+package org.apache.dubbo.common.extension.wrapper.impl;
 
-public interface Constants {
-    String CONFIG_CLUSTER_KEY = "config.cluster";
-    String CONFIG_NAMESPACE_KEY = "config.namespace";
-    String CONFIG_GROUP_KEY = "config.group";
-    String CONFIG_CHECK_KEY = "config.check";
+import org.apache.dubbo.common.extension.wrapper.Demo;
+
+public class DemoImpl implements Demo {
+    @Override
+    public String echo(String msg) {
+        return msg;
+    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper.java
similarity index 66%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper.java
index 36ceb4d..44ec737 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper.java
@@ -14,24 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.common.extension.wrapper.impl;
 
-import org.junit.jupiter.api.Test;
+import org.apache.dubbo.common.extension.Wrapper;
+import org.apache.dubbo.common.extension.wrapper.Demo;
 
-import java.util.List;
+@Wrapper(matches = {"demo"}, mismatches = "demo2")
+public class DemoWrapper implements Demo {
+    private Demo demo;
 
-import static java.util.Arrays.asList;
-
-/**
- * {@link DefaultPage}
- *
- * @since 2.7.5
- */
-public class DefaultPageTest {
+    public DemoWrapper(Demo demo) {
+        this.demo = demo;
+    }
 
-    @Test
-    public void test() {
-        List<Integer> data = asList(1, 2, 3, 4, 5);
-        DefaultPage page = new DefaultPage(0, 1, data.subList(0, 1), data.size());
+    public String echo(String msg) {
+        return demo.echo(msg);
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper2.java
similarity index 66%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper2.java
index 36ceb4d..c8e4385 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/wrapper/impl/DemoWrapper2.java
@@ -14,24 +14,20 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.common.extension.wrapper.impl;
 
-import org.junit.jupiter.api.Test;
+import org.apache.dubbo.common.extension.Wrapper;
+import org.apache.dubbo.common.extension.wrapper.Demo;
 
-import java.util.List;
+@Wrapper(matches = {"demo2"}, mismatches = {"demo"})
+public class DemoWrapper2 implements Demo {
+    private Demo demo;
 
-import static java.util.Arrays.asList;
-
-/**
- * {@link DefaultPage}
- *
- * @since 2.7.5
- */
-public class DefaultPageTest {
+    public DemoWrapper2(Demo demo) {
+        this.demo = demo;
+    }
 
-    @Test
-    public void test() {
-        List<Integer> data = asList(1, 2, 3, 4, 5);
-        DefaultPage page = new DefaultPage(0, 1, data.subList(0, 1), data.size());
+    public String echo(String msg) {
+        return demo.echo(msg);
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/model/SerializablePerson.java b/dubbo-common/src/test/java/org/apache/dubbo/common/model/SerializablePerson.java
index d78c592..730d2cb 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/model/SerializablePerson.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/model/SerializablePerson.java
@@ -27,6 +27,9 @@ public class SerializablePerson implements Serializable {
 
     private String[] value = {"value1", "value2"};
 
+    public SerializablePerson(char description , boolean adult){
+
+    }
     public String getName() {
         return name;
     }
@@ -94,4 +97,4 @@ public class SerializablePerson implements Serializable {
             return false;
         return true;
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java
index df0b908..8df34f8 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadlocal/InternalThreadLocalTest.java
@@ -79,6 +79,7 @@ public class InternalThreadLocalTest {
         final InternalThreadLocal<String> internalThreadLocalString = new InternalThreadLocal<String>();
         internalThreadLocalString.set("value");
         Assertions.assertEquals(2, InternalThreadLocal.size(), "size method is wrong!");
+        InternalThreadLocal.removeAll();
     }
 
     @Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/ThreadlessExecutorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/ThreadlessExecutorTest.java
new file mode 100644
index 0000000..a17b462
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/ThreadlessExecutorTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.threadpool;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+
+public class ThreadlessExecutorTest {
+    private static ThreadlessExecutor executor;
+
+    static {
+        URL url = URL.valueOf("dubbo://127.0.0.1:12345");
+        ExecutorService sharedExecutor =
+                ExtensionLoader.getExtensionLoader(ExecutorRepository.class)
+                        .getDefaultExtension().createExecutorIfAbsent(url);
+        executor = new ThreadlessExecutor(sharedExecutor);
+    }
+
+    @Test
+    public void test() throws InterruptedException {
+        for (int i = 0; i < 10; i++) {
+            executor.execute(()->{throw new RuntimeException("test");});
+        }
+
+        CompletableFuture<Object> stubFuture = new CompletableFuture<>();
+        executor.setWaitingFuture(stubFuture);
+        Assertions.assertEquals(executor.getWaitingFuture(),stubFuture);
+
+        executor.waitAndDrain();
+
+        executor.execute(()->{});
+
+        executor.waitAndDrain();
+
+        executor.shutdown();
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepositoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepositoryTest.java
new file mode 100644
index 0000000..bb3fe4e
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/manager/ExecutorRepositoryTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.threadpool.manager;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+
+public class ExecutorRepositoryTest {
+    private ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+
+    @Test
+    public void testGetExecutor() {
+        testGet(URL.valueOf("dubbo://127.0.0.1:23456"));
+        testGet(URL.valueOf("dubbo://127.0.0.1:23456?side=consumer"));
+
+        Assertions.assertNotNull(executorRepository.getSharedExecutor());
+        Assertions.assertNotNull(executorRepository.getServiceExporterExecutor());
+        executorRepository.nextScheduledExecutor();
+    }
+
+    private void testGet(URL url) {
+        Assertions.assertNull(executorRepository.getExecutor(url));
+
+        ExecutorService executorService = executorRepository.createExecutorIfAbsent(url);
+        executorService.shutdown();
+        executorService = executorRepository.createExecutorIfAbsent(url);
+        Assertions.assertFalse(executorService.isShutdown());
+
+        Assertions.assertEquals(executorService, executorRepository.getExecutor(url));
+        executorService.shutdown();
+        Assertions.assertNotEquals(executorService, executorRepository.getExecutor(url));
+    }
+
+    @Test
+    public void testUpdateExecutor() {
+        URL url = URL.valueOf("dubbo://127.0.0.1:23456?threads=5");
+        ThreadPoolExecutor executorService = (ThreadPoolExecutor) executorRepository.createExecutorIfAbsent(url);
+
+        executorService.setCorePoolSize(3);
+        executorRepository.updateThreadpool(url, executorService);
+
+        executorService.setCorePoolSize(3);
+        executorService.setMaximumPoolSize(3);
+        executorRepository.updateThreadpool(url, executorService);
+
+        executorService.setMaximumPoolSize(20);
+        executorService.setCorePoolSize(10);
+        executorRepository.updateThreadpool(url, executorService);
+
+        executorService.setCorePoolSize(10);
+        executorService.setMaximumPoolSize(10);
+        executorRepository.updateThreadpool(url, executorService);
+
+        executorService.setCorePoolSize(5);
+        executorRepository.updateThreadpool(url, executorService);
+
+
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java
index ea54e9f..4add905 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/AbortPolicyWithReportTest.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
 
 import org.junit.jupiter.api.Test;
 
+import java.util.UUID;
 import java.util.concurrent.Executors;
 import java.util.concurrent.RejectedExecutionException;
 import java.util.concurrent.ThreadPoolExecutor;
@@ -31,6 +32,25 @@ public class AbortPolicyWithReportTest {
         AbortPolicyWithReport abortPolicyWithReport = new AbortPolicyWithReport("Test", url);
 
         try {
+            abortPolicyWithReport.rejectedExecution(() -> System.out.println("hello"), (ThreadPoolExecutor) Executors.newFixedThreadPool(1));
+        } catch (RejectedExecutionException rj) {
+            // ignore
+        }
+
+        Thread.sleep(1000);
+
+    }
+
+    @Test
+    public void jStackDumpTest_dumpDirectoryNotExists_cannotBeCreatedTakeUserHome() throws InterruptedException {
+        final String dumpDirectory = dumpDirectoryCannotBeCreated();
+
+        URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?dump.directory="
+                + dumpDirectory
+                + "&version=1.0.0&application=morgan&noValue=true");
+        AbortPolicyWithReport abortPolicyWithReport = new AbortPolicyWithReport("Test", url);
+
+        try {
             abortPolicyWithReport.rejectedExecution(new Runnable() {
                 @Override
                 public void run() {
@@ -42,6 +62,38 @@ public class AbortPolicyWithReportTest {
         }
 
         Thread.sleep(1000);
+    }
+
+    private String dumpDirectoryCannotBeCreated() {
+        final String os = System.getProperty("os.name").toLowerCase();
+        if (os.contains("win")) {
+            // "con" is one of Windows reserved names, https://docs.microsoft.com/en-us/windows/win32/fileio/naming-a-file
+            return "con";
+        } else {
+            return "/dev/full/" + UUID.randomUUID().toString();
+        }
+    }
 
+    @Test
+    public void jStackDumpTest_dumpDirectoryNotExists_canBeCreated() throws InterruptedException {
+        final String dumpDirectory = UUID.randomUUID().toString();
+
+        URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?dump.directory="
+                + dumpDirectory
+                + "&version=1.0.0&application=morgan&noValue=true");
+        AbortPolicyWithReport abortPolicyWithReport = new AbortPolicyWithReport("Test", url);
+
+        try {
+            abortPolicyWithReport.rejectedExecution(new Runnable() {
+                @Override
+                public void run() {
+                    System.out.println("hello");
+                }
+            }, (ThreadPoolExecutor) Executors.newFixedThreadPool(1));
+        } catch (RejectedExecutionException rj) {
+            // ignore
+        }
+
+        Thread.sleep(1000);
     }
 }
\ No newline at end of file
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPoolTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPoolTest.java
index 2754635..f345970 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPoolTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/cached/CachedThreadPoolTest.java
@@ -60,14 +60,11 @@ public class CachedThreadPoolTest {
                 Matchers.<RejectedExecutionHandler>instanceOf(AbortPolicyWithReport.class));
 
         final CountDownLatch latch = new CountDownLatch(1);
-        executor.execute(new Runnable() {
-            @Override
-            public void run() {
-                Thread thread = Thread.currentThread();
-                assertThat(thread, instanceOf(InternalThread.class));
-                assertThat(thread.getName(), startsWith("demo"));
-                latch.countDown();
-            }
+        executor.execute(() -> {
+            Thread thread = Thread.currentThread();
+            assertThat(thread, instanceOf(InternalThread.class));
+            assertThat(thread.getName(), startsWith("demo"));
+            latch.countDown();
         });
 
         latch.await();
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java
index 7846c0e..f8fdbfb 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolExecutorTest.java
@@ -76,16 +76,13 @@ public class EagerThreadPoolExecutorTest {
 
         for (int i = 0; i < 15; i++) {
             Thread.sleep(50);
-            executor.execute(new Runnable() {
-                @Override
-                public void run() {
-                    System.out.println("thread number in current pool:" + executor.getPoolSize() + ",  task number in task queue:" + executor.getQueue()
-                            .size() + " executor size: " + executor.getPoolSize());
-                    try {
-                        Thread.sleep(1000);
-                    } catch (InterruptedException e) {
-                        e.printStackTrace();
-                    }
+            executor.execute(() -> {
+                System.out.println("thread number in current pool:" + executor.getPoolSize() + ",  task number in task queue:" + executor.getQueue()
+                        .size() + " executor size: " + executor.getPoolSize());
+                try {
+                    Thread.sleep(1000);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
                 }
             });
         }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolTest.java
index 95e4187..cb8e9e2 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/threadpool/support/eager/EagerThreadPoolTest.java
@@ -62,14 +62,11 @@ public class EagerThreadPoolTest {
                 Matchers.<RejectedExecutionHandler>instanceOf(AbortPolicyWithReport.class));
 
         final CountDownLatch latch = new CountDownLatch(1);
-        executor.execute(new Runnable() {
-            @Override
-            public void run() {
-                Thread thread = Thread.currentThread();
-                assertThat(thread, instanceOf(InternalThread.class));
-                assertThat(thread.getName(), startsWith("demo"));
-                latch.countDown();
-            }
+        executor.execute(() -> {
+            Thread thread = Thread.currentThread();
+            assertThat(thread, instanceOf(InternalThread.class));
+            assertThat(thread.getName(), startsWith("demo"));
+            latch.countDown();
         });
 
         latch.await();
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java
index 0223514..9b9c5ee 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/timer/HashedWheelTimerTest.java
@@ -18,55 +18,181 @@
 package org.apache.dubbo.common.timer;
 
 import org.apache.dubbo.common.utils.NamedThreadFactory;
+
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import java.time.LocalDateTime;
-import java.time.format.DateTimeFormatter;
+import java.lang.ref.WeakReference;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
 public class HashedWheelTimerTest {
+    private CountDownLatch tryStopTaskCountDownLatch = new CountDownLatch(1);
+    private CountDownLatch errorTaskCountDownLatch = new CountDownLatch(1);
+
+    private static class EmptyTask implements TimerTask {
+        @Override
+        public void run(Timeout timeout) {
+        }
+    }
+
+    private static class BlockTask implements TimerTask {
+        @Override
+        public void run(Timeout timeout) throws InterruptedException {
+            this.wait();
+        }
+    }
 
-    private class PrintTask implements TimerTask {
+    private class ErrorTask implements TimerTask {
+        @Override
+        public void run(Timeout timeout) {
+            errorTaskCountDownLatch.countDown();
+            throw new RuntimeException("Test");
+        }
+    }
+
+    private class TryStopTask implements TimerTask {
+        private Timer timer;
+
+        public TryStopTask(Timer timer) {
+            this.timer = timer;
+        }
 
         @Override
         public void run(Timeout timeout) {
-            final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
-            System.out.println("task :" + LocalDateTime.now().format(formatter));
+            Assertions.assertThrows(RuntimeException.class, () -> timer.stop());
+            tryStopTaskCountDownLatch.countDown();
         }
     }
 
     @Test
-    public void newTimeout() throws InterruptedException {
-        final Timer timer = newTimer();
-        for (int i = 0; i < 10; i++) {
-            timer.newTimeout(new PrintTask(), 1, TimeUnit.SECONDS);
-            Thread.sleep(1000);
+    public void constructorTest() {
+        // use weak reference to let gc work every time
+        // which can check finalize method and reduce memory usage in time
+        WeakReference<Timer> timer = new WeakReference<>(new HashedWheelTimer());
+        timer = new WeakReference<>(new HashedWheelTimer(100, TimeUnit.MILLISECONDS));
+        timer = new WeakReference<>(new HashedWheelTimer(100, TimeUnit.MILLISECONDS, 8));
+
+        // to cover arg check branches
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    null,
+                    100,
+                    TimeUnit.MILLISECONDS,
+                    8, -1);
+        });
+
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    new NamedThreadFactory("dubbo-future-timeout", true),
+                    0,
+                    TimeUnit.MILLISECONDS,
+                    8, -1);
+        });
+
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    new NamedThreadFactory("dubbo-future-timeout", true),
+                    100,
+                    null,
+                    8, -1);
+        });
+
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    new NamedThreadFactory("dubbo-future-timeout", true),
+                    100,
+                    TimeUnit.MILLISECONDS,
+                    0, -1);
+        });
+
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    new NamedThreadFactory("dubbo-future-timeout", true),
+                    Long.MAX_VALUE,
+                    TimeUnit.MILLISECONDS,
+                    8, -1);
+        });
+
+        Assertions.assertThrows(RuntimeException.class, () -> {
+            new HashedWheelTimer(
+                    new NamedThreadFactory("dubbo-future-timeout", true),
+                    100,
+                    TimeUnit.MILLISECONDS,
+                    Integer.MAX_VALUE, -1);
+        });
+
+        for (int i = 0; i < 128; i++) {
+            // to trigger INSTANCE_COUNT_LIMIT
+            timer = new WeakReference<>(new HashedWheelTimer());
         }
-        Thread.sleep(5000);
+
+        System.gc();
     }
 
     @Test
-    public void stop() throws InterruptedException {
-        final Timer timer = newTimer();
-        for (int i = 0; i < 10; i++) {
-            timer.newTimeout(new PrintTask(), 5, TimeUnit.SECONDS);
-            Thread.sleep(100);
+    public void createTaskTest() throws InterruptedException {
+        HashedWheelTimer timer = new HashedWheelTimer(
+                new NamedThreadFactory("dubbo-future-timeout", true),
+                10,
+                TimeUnit.MILLISECONDS,
+                8, 8);
+
+        Assertions.assertThrows(RuntimeException.class,
+                () -> timer.newTimeout(null, 5, TimeUnit.SECONDS));
+        Assertions.assertThrows(RuntimeException.class,
+                () -> timer.newTimeout(new EmptyTask(), 5, null));
+
+        Timeout timeout = timer.newTimeout(new ErrorTask(), 10, TimeUnit.MILLISECONDS);
+        errorTaskCountDownLatch.await();
+        Assertions.assertFalse(timeout.cancel());
+        Assertions.assertFalse(timeout.isCancelled());
+        Assertions.assertNotNull(timeout.toString());
+        Assertions.assertEquals(timeout.timer(), timer);
+
+        timeout = timer.newTimeout(new EmptyTask(), 1000, TimeUnit.SECONDS);
+        timeout.cancel();
+        Assertions.assertTrue(timeout.isCancelled());
+
+        List<Timeout> timeouts = new LinkedList<>();
+        for (; timer.pendingTimeouts() < 8; ) {
+            // to trigger maxPendingTimeouts
+            timeout = timer.newTimeout(new BlockTask(), -1, TimeUnit.MILLISECONDS);
+            timeouts.add(timeout);
+            Assertions.assertNotNull(timeout.toString());
         }
-        //stop timer
+        Assertions.assertEquals(timer.pendingTimeouts(), 8);
+
+        // this will throw an exception because of maxPendingTimeouts
+        Assertions.assertThrows(RuntimeException.class,
+                () -> timer.newTimeout(new BlockTask(), 1, TimeUnit.MILLISECONDS));
+
+        timeout = timeouts.get(2);
+        // wait until the task expired
+        Thread.sleep(100);
+        Assertions.assertTrue(timeout.isExpired());
+
         timer.stop();
+    }
+
+    @Test
+    public void stopTaskTest() throws InterruptedException {
+        Timer timer = new HashedWheelTimer(new NamedThreadFactory("dubbo-future-timeout", true));
+        timer.newTimeout(new TryStopTask(timer), 10, TimeUnit.MILLISECONDS);
+        tryStopTaskCountDownLatch.await();
 
-        try {
-            //this will throw a exception
-            timer.newTimeout(new PrintTask(), 5, TimeUnit.SECONDS);
-        } catch (Exception e) {
-            e.printStackTrace();
+        for (int i = 0; i < 8; i++) {
+            timer.newTimeout(new EmptyTask(), 0, TimeUnit.SECONDS);
         }
-    }
+        // stop timer
+        timer.stop();
+        Assertions.assertTrue(timer.isStop());
+
+        // this will throw an exception
+        Assertions.assertThrows(RuntimeException.class,
+                () -> timer.newTimeout(new EmptyTask(), 5, TimeUnit.SECONDS));
 
-    private Timer newTimer() {
-        return new HashedWheelTimer(
-                new NamedThreadFactory("dubbo-future-timeout", true),
-                100,
-                TimeUnit.MILLISECONDS);
     }
 }
\ No newline at end of file
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java
index 36af51d..d65e92e 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CollectionUtilsTest.java
@@ -141,7 +141,7 @@ public class CollectionUtilsTest {
 
     @Test
     public void testJoinList() throws Exception {
-        List<String> list = Arrays.asList();
+        List<String> list = emptyList();
         assertEquals("", CollectionUtils.join(list, "/"));
 
         list = Arrays.asList("x");
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
index 85e7180..6a838c7 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/CompatibleTypeUtilsTest.java
@@ -84,7 +84,7 @@ public class CompatibleTypeUtilsTest {
             result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalTime.class);
             assertEquals(DateTimeFormatter.ofPattern("HH:mm:ss").format((java.time.LocalTime) result), "12:24:12");
 
-            result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11T12:24:12.047", java.time.LocalDate.class);
+            result = CompatibleTypeUtils.compatibleTypeConvert("2011-12-11", java.time.LocalDate.class);
             assertEquals(DateTimeFormatter.ofPattern("yyyy-MM-dd").format((java.time.LocalDate) result), "2011-12-11");
 
             result = CompatibleTypeUtils.compatibleTypeConvert("ab", char[].class);
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
index 1f82a52..2324e27 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
@@ -91,7 +91,7 @@ public class ConfigUtilsTest {
     @Test
     public void testMergeValuesDeleteDefault() {
         List<String> merged = ConfigUtils.mergeValues(ThreadPool.class, "-default", asList("fixed", "default.limited", "cached"));
-        assertEquals(asList(), merged);
+        assertEquals(Collections.emptyList(), merged);
     }
 
     @Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
index 36ceb4d..41c0e03 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DefaultPageTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.common.utils;
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
 import java.util.List;
@@ -32,6 +33,12 @@ public class DefaultPageTest {
     @Test
     public void test() {
         List<Integer> data = asList(1, 2, 3, 4, 5);
-        DefaultPage page = new DefaultPage(0, 1, data.subList(0, 1), data.size());
+        DefaultPage<Integer> page = new DefaultPage<>(0, 1, data.subList(0, 1), data.size());
+        Assertions.assertEquals(page.getOffset(), 0);
+        Assertions.assertEquals(page.getPageSize(), 1);
+        Assertions.assertEquals(page.getTotalSize(), data.size());
+        Assertions.assertEquals(page.getData(), data.subList(0, 1));
+        Assertions.assertEquals(page.getTotalPages(), 5);
+        Assertions.assertTrue(page.hasNext());
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LFUCacheTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LFUCacheTest.java
index 3453524..d7a7250 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LFUCacheTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LFUCacheTest.java
@@ -16,16 +16,19 @@
  */
 package org.apache.dubbo.common.utils;
 
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
-import static org.hamcrest.Matchers.equalTo;
+import java.io.IOException;
+
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
 
 public class LFUCacheTest {
 
     @Test
     public void testCacheEviction() throws Exception {
-        LFUCache<String, Integer> cache = new LFUCache<String, Integer>(8, 0.8f);
+        LFUCache<String, Integer> cache = new LFUCache<>(8, 0.8f);
         cache.put("one", 1);
         cache.put("two", 2);
         cache.put("three", 3);
@@ -46,7 +49,7 @@ public class LFUCacheTest {
 
     @Test
     public void testCacheRemove() throws Exception {
-        LFUCache<String, Integer> cache = new LFUCache<String, Integer>(8, 0.8f);
+        LFUCache<String, Integer> cache = new LFUCache<>(8, 0.8f);
         cache.put("one", 1);
         cache.put("two", 2);
         cache.put("three", 3);
@@ -65,8 +68,16 @@ public class LFUCacheTest {
     }
 
     @Test
-    public void testCapacity() throws Exception {
-        LFUCache<String, Integer> cache = new LFUCache<String, Integer>();
+    public void testDefaultCapacity() throws Exception {
+        LFUCache<String, Integer> cache = new LFUCache<>();
         assertThat(cache.getCapacity(), equalTo(1000));
     }
+
+    @Test
+    public void testErrorConstructArguments() throws IOException {
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new LFUCache<>(0, 0.8f));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new LFUCache<>(-1, 0.8f));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new LFUCache<>(100, 0.0f));
+        Assertions.assertThrows(IllegalArgumentException.class, () -> new LFUCache<>(100, -0.1f));
+    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LogTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LogTest.java
index 203cadb..39b60ab 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LogTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/LogTest.java
@@ -18,39 +18,68 @@
 package org.apache.dubbo.common.utils;
 
 import org.apache.log4j.Level;
+import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
+import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
 
 public class LogTest {
     @Test
     public void testLogName() throws Exception {
-        Log log = new Log();
-        log.setLogName("log-name");
-        assertThat(log.getLogName(), equalTo("log-name"));
+        Log log1 = new Log();
+        Log log2 = new Log();
+        Log log3 = new Log();
+        log1.setLogName("log-name");
+        log2.setLogName("log-name");
+        log3.setLogName("log-name-other");
+        assertThat(log1.getLogName(), equalTo("log-name"));
+        Assertions.assertEquals(log1, log2);
+        Assertions.assertEquals(log1.hashCode(), log2.hashCode());
+        Assertions.assertNotEquals(log1, log3);
     }
 
     @Test
     public void testLogLevel() throws Exception {
-        Log log = new Log();
-        log.setLogLevel(Level.ALL);
-        assertThat(log.getLogLevel(), is(Level.ALL));
+        Log log1 = new Log();
+        Log log2 = new Log();
+        Log log3 = new Log();
+        log1.setLogLevel(Level.ALL);
+        log2.setLogLevel(Level.ALL);
+        log3.setLogLevel(Level.DEBUG);
+        assertThat(log1.getLogLevel(), is(Level.ALL));
+        Assertions.assertEquals(log1, log2);
+        Assertions.assertEquals(log1.hashCode(), log2.hashCode());
+        Assertions.assertNotEquals(log1, log3);
     }
 
     @Test
     public void testLogMessage() throws Exception {
-        Log log = new Log();
-        log.setLogMessage("log-message");
-        assertThat(log.getLogMessage(), equalTo("log-message"));
+        Log log1 = new Log();
+        Log log2 = new Log();
+        Log log3 = new Log();
+        log1.setLogMessage("log-message");
+        log2.setLogMessage("log-message");
+        log3.setLogMessage("log-message-other");
+        assertThat(log1.getLogMessage(), equalTo("log-message"));
+        Assertions.assertEquals(log1, log2);
+        Assertions.assertEquals(log1.hashCode(), log2.hashCode());
+        Assertions.assertNotEquals(log1, log3);
     }
 
     @Test
     public void testLogThread() throws Exception {
-        Log log = new Log();
-        log.setLogThread("log-thread");
-        assertThat(log.getLogThread(), equalTo("log-thread"));
+        Log log1 = new Log();
+        Log log2 = new Log();
+        Log log3 = new Log();
+        log1.setLogThread("log-thread");
+        log2.setLogThread("log-thread");
+        log3.setLogThread("log-thread-other");
+        assertThat(log1.getLogThread(), equalTo("log-thread"));
+        Assertions.assertEquals(log1, log2);
+        Assertions.assertEquals(log1.hashCode(), log2.hashCode());
+        Assertions.assertNotEquals(log1, log3);
     }
 
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
index 051363b..a5a78cc 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
@@ -18,6 +18,8 @@ package org.apache.dubbo.common.utils;
 
 import org.junit.jupiter.api.Test;
 
+import static org.apache.dubbo.common.utils.MemberUtils.isPrivate;
+import static org.apache.dubbo.common.utils.MemberUtils.isPublic;
 import static org.apache.dubbo.common.utils.MemberUtils.isStatic;
 import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -34,9 +36,19 @@ public class MemberUtilsTest {
 
         assertFalse(isStatic(getClass().getMethod("testIsStatic")));
         assertTrue(isStatic(getClass().getMethod("staticMethod")));
+        assertTrue(isPrivate(getClass().getDeclaredMethod("privateMethod")));
+        assertTrue(isPublic(getClass().getMethod("publicMethod")));
     }
 
     public static void staticMethod() {
 
     }
+
+    private void privateMethod() {
+
+    }
+
+    public void publicMethod() {
+
+    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java
index 7cb143e..e8eb7f1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MethodUtilsTest.java
@@ -21,6 +21,17 @@ import org.junit.jupiter.api.Test;
 
 import java.lang.reflect.Method;
 
+import static org.apache.dubbo.common.utils.MethodUtils.excludedDeclaredClass;
+import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
+import static org.apache.dubbo.common.utils.MethodUtils.findNearestOverriddenMethod;
+import static org.apache.dubbo.common.utils.MethodUtils.findOverriddenMethod;
+import static org.apache.dubbo.common.utils.MethodUtils.getAllDeclaredMethods;
+import static org.apache.dubbo.common.utils.MethodUtils.getAllMethods;
+import static org.apache.dubbo.common.utils.MethodUtils.getDeclaredMethods;
+import static org.apache.dubbo.common.utils.MethodUtils.getMethods;
+import static org.apache.dubbo.common.utils.MethodUtils.invokeMethod;
+import static org.apache.dubbo.common.utils.MethodUtils.overrides;
+
 public class MethodUtilsTest {
 
     @Test
@@ -53,6 +64,38 @@ public class MethodUtilsTest {
         Assertions.assertFalse(MethodUtils.isDeprecated(MethodTestClazz.class.getMethod("getValue")));
     }
 
+    @Test
+    public void testIsMetaMethod() {
+        boolean containMetaMethod = false;
+        for (Method method : MethodTestClazz.class.getMethods()) {
+            if (MethodUtils.isMetaMethod(method)) {
+                containMetaMethod = true;
+            }
+        }
+        Assertions.assertTrue(containMetaMethod);
+    }
+
+    @Test
+    public void testGetMethods() throws NoSuchMethodException {
+        Assertions.assertTrue(getDeclaredMethods(MethodTestClazz.class, excludedDeclaredClass(String.class)).size() > 0);
+        Assertions.assertTrue(getMethods(MethodTestClazz.class).size() > 0);
+        Assertions.assertTrue(getAllDeclaredMethods(MethodTestClazz.class).size() > 0);
+        Assertions.assertTrue(getAllMethods(MethodTestClazz.class).size() > 0);
+        Assertions.assertNotNull(findMethod(MethodTestClazz.class, "getValue"));
+
+        MethodTestClazz methodTestClazz = new MethodTestClazz();
+        invokeMethod(methodTestClazz, "setValue", "Test");
+        Assertions.assertEquals(methodTestClazz.getValue(), "Test");
+
+        Assertions.assertTrue(overrides(MethodOverrideClazz.class.getMethod("get"),
+                MethodTestClazz.class.getMethod("get")));
+        Assertions.assertEquals(findNearestOverriddenMethod(MethodOverrideClazz.class.getMethod("get")),
+                MethodTestClazz.class.getMethod("get"));
+        Assertions.assertEquals(findOverriddenMethod(MethodOverrideClazz.class.getMethod("get"), MethodOverrideClazz.class),
+                MethodTestClazz.class.getMethod("get"));
+
+    }
+
     public class MethodTestClazz {
         private String value;
 
@@ -64,10 +107,21 @@ public class MethodUtilsTest {
             this.value = value;
         }
 
+        public MethodTestClazz get() {
+            return this;
+        }
+
         @Deprecated
         public Boolean deprecatedMethod() {
             return true;
         }
     }
 
+    public class MethodOverrideClazz extends MethodTestClazz {
+        @Override
+        public MethodTestClazz get() {
+            return this;
+        }
+    }
+
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
index ea2c54e..b6416aa 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsTest.java
@@ -35,6 +35,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
 import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -193,11 +194,15 @@ public class NetUtilsTest {
     public void testIsValidV6Address() {
         String saved = System.getProperty("java.net.preferIPv6Addresses", "false");
         System.setProperty("java.net.preferIPv6Addresses", "true");
+
         InetAddress address = NetUtils.getLocalAddress();
-        if (address instanceof Inet6Address) {
-            assertThat(NetUtils.isPreferIPV6Address(), equalTo(true));
-        }
+        boolean isPreferIPV6Address = NetUtils.isPreferIPV6Address();
+
+        // Restore system property to previous value before executing test
         System.setProperty("java.net.preferIPv6Addresses", saved);
+
+        assumeTrue(address instanceof Inet6Address);
+        assertThat(isPreferIPV6Address, equalTo(true));
     }
 
     /**
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
index 24cb292..e615dd9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
@@ -133,12 +133,13 @@ public class PojoUtilsTest {
     @Test
     public void test_pojo() throws Exception {
         assertObject(new Person());
-        assertObject(new SerializablePerson());
+        assertObject(new BasicTestData(false, '\0', (byte) 0, (short) 0, 0, 0L, 0F, 0D));
+        assertObject(new SerializablePerson(Character.MIN_VALUE, false));
     }
 
     @Test
     public void test_has_no_nullary_constructor_pojo() {
-        assertObject(new User(1,"fibbery"));
+        assertObject(new User(1, "fibbery"));
     }
 
     @Test
@@ -147,7 +148,7 @@ public class PojoUtilsTest {
 
         List<Object> list = new ArrayList<Object>();
         list.add(new Person());
-        list.add(new SerializablePerson());
+        list.add(new SerializablePerson(Character.MIN_VALUE, false));
 
         map.put("k", list);
 
@@ -198,6 +199,11 @@ public class PojoUtilsTest {
         assertArrayObject(new Float[]{37F, -39F, 123456.7F});
 
         assertArrayObject(new Double[]{37D, -39D, 123456.7D});
+
+        assertObject(new int[][]{{37, -39, 12456}});
+        assertObject(new Integer[][][]{{{37, -39, 12456}}});
+
+        assertArrayObject(new Integer[]{37, -39, 12456});
     }
 
     @Test
@@ -287,7 +293,7 @@ public class PojoUtilsTest {
         JSONObject jsonObject = new JSONObject();
         jsonObject.put("1", "test");
         @SuppressWarnings("unchecked")
-        Map<Integer, Object> value = (Map<Integer, Object>)PojoUtils.realize(jsonObject,
+        Map<Integer, Object> value = (Map<Integer, Object>) PojoUtils.realize(jsonObject,
                 method.getParameterTypes()[0],
                 method.getGenericParameterTypes()[0]);
         method.invoke(new PojoUtilsTest(), value);
@@ -303,7 +309,7 @@ public class PojoUtilsTest {
         List<JSONObject> list = new ArrayList<>(1);
         list.add(jsonObject);
         @SuppressWarnings("unchecked")
-        List<Map<Integer, Object>> result = (List<Map<Integer, Object>>)PojoUtils.realize(
+        List<Map<Integer, Object>> result = (List<Map<Integer, Object>>) PojoUtils.realize(
                 list,
                 method.getParameterTypes()[0],
                 method.getGenericParameterTypes()[0]);
@@ -311,9 +317,11 @@ public class PojoUtilsTest {
         assertEquals("test", result.get(0).get(1));
     }
 
-    public void setMap(Map<Integer, Object> map) {}
+    public void setMap(Map<Integer, Object> map) {
+    }
 
-    public void setListMap(List<Map<Integer, Object>> list) {}
+    public void setListMap(List<Map<Integer, Object>> list) {
+    }
 
     @Test
     public void testException() throws Exception {
@@ -756,6 +764,78 @@ public class PojoUtilsTest {
         SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
     }
 
+    public static class BasicTestData {
+
+        public boolean a;
+        public char b;
+        public byte c;
+        public short d;
+        public int e;
+        public long f;
+        public float g;
+        public double h;
+
+        public BasicTestData(boolean a, char b, byte c, short d, int e, long f, float g, double h) {
+            this.a = a;
+            this.b = b;
+            this.c = c;
+            this.d = d;
+            this.e = e;
+            this.f = f;
+            this.g = g;
+            this.h = h;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + (a ? 1 : 2);
+            result = prime * result + b;
+            result = prime * result + c;
+            result = prime * result + c;
+            result = prime * result + e;
+            result = (int) (prime * result + f);
+            result = (int) (prime * result + g);
+            result = (int) (prime * result + h);
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            BasicTestData other = (BasicTestData) obj;
+            if (a != other.a) {
+                return false;
+            }
+            if (b != other.b) {
+                return false;
+            }
+            if (c != other.c) {
+                return false;
+            }
+            if (e != other.e) {
+                return false;
+            }
+            if (f != other.f) {
+                return false;
+            }
+            if (g != other.g) {
+                return false;
+            }
+            if (h != other.h) {
+                return false;
+            }
+            return true;
+        }
+
+    }
+
     public static class Parent {
         public String gender;
         public String email;
@@ -901,4 +981,4 @@ public class PojoUtilsTest {
 
         boolean isUrgent();
     }
-}
\ No newline at end of file
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
index 6b6b7f6..d9adde8 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ReflectUtilsTest.java
@@ -416,18 +416,44 @@ public class ReflectUtilsTest {
         Assertions.assertEquals("java.lang.String", types1[0].getTypeName());
         Assertions.assertEquals("java.lang.String", types1[1].getTypeName());
 
-        Type[] types2 = ReflectUtils.getReturnTypes(clazz.getMethod("getListFuture"));
-        Assertions.assertEquals("java.util.List", types2[0].getTypeName());
-        Assertions.assertEquals("java.util.List<java.lang.String>", types2[1].getTypeName());
+        Type[] types2 = ReflectUtils.getReturnTypes(clazz.getMethod("getT"));
+        Assertions.assertEquals("java.lang.String", types2[0].getTypeName());
+        Assertions.assertEquals("T", types2[1].getTypeName());
+
+        Type[] types3 = ReflectUtils.getReturnTypes(clazz.getMethod("getS"));
+        Assertions.assertEquals("java.lang.Object", types3[0].getTypeName());
+        Assertions.assertEquals("S", types3[1].getTypeName());
+
+        Type[] types4 = ReflectUtils.getReturnTypes(clazz.getMethod("getListFuture"));
+        Assertions.assertEquals("java.util.List", types4[0].getTypeName());
+        Assertions.assertEquals("java.util.List<java.lang.String>", types4[1].getTypeName());
+
+        Type[] types5 = ReflectUtils.getReturnTypes(clazz.getMethod("getGenericWithUpperFuture"));
+        // T extends String, the first arg should be the upper bound of param
+        Assertions.assertEquals("java.lang.String", types5[0].getTypeName());
+        Assertions.assertEquals("T", types5[1].getTypeName());
+
+        Type[] types6 = ReflectUtils.getReturnTypes(clazz.getMethod("getGenericFuture"));
+        // default upper bound is Object
+        Assertions.assertEquals("java.lang.Object", types6[0].getTypeName());
+        Assertions.assertEquals("S", types6[1].getTypeName());
     }
 
-    public interface TypeClass {
+    public interface TypeClass<T extends String, S> {
 
         CompletableFuture<String> getFuture();
 
         String getString();
 
+        T getT();
+
+        S getS();
+
         CompletableFuture<List<String>> getListFuture();
+
+        CompletableFuture<T> getGenericWithUpperFuture();
+
+        CompletableFuture<S> getGenericFuture();
     }
 
     public static class EmptyClass {
diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt b/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt
new file mode 100644
index 0000000..be83ff5
--- /dev/null
+++ b/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt
@@ -0,0 +1 @@
+duplicated=org.apache.dubbo.common.extension.duplicated.impl.DuplicatedOverriddenExt2
\ No newline at end of file
diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt b/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt
new file mode 100644
index 0000000..237c8fd
--- /dev/null
+++ b/dubbo-common/src/test/resources/META-INF/dubbo/external/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt
@@ -0,0 +1 @@
+duplicated=org.apache.dubbo.common.extension.duplicated.impl.DuplicatedWithoutOverriddenExt2
\ No newline at end of file
diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt
new file mode 100644
index 0000000..a7a66ef
--- /dev/null
+++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedOverriddenExt
@@ -0,0 +1 @@
+duplicated=org.apache.dubbo.common.extension.duplicated.impl.DuplicatedOverriddenExt1
\ No newline at end of file
diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt
new file mode 100644
index 0000000..e655ee6
--- /dev/null
+++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.duplicated.DuplicatedWithoutOverriddenExt
@@ -0,0 +1 @@
+duplicated=org.apache.dubbo.common.extension.duplicated.impl.DuplicatedWithoutOverriddenExt1
\ No newline at end of file
diff --git a/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.wrapper.Demo b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.wrapper.Demo
new file mode 100644
index 0000000..a346d65
--- /dev/null
+++ b/dubbo-common/src/test/resources/META-INF/dubbo/internal/org.apache.dubbo.common.extension.wrapper.Demo
@@ -0,0 +1,4 @@
+demo=org.apache.dubbo.common.extension.wrapper.impl.DemoImpl
+wrapper=org.apache.dubbo.common.extension.wrapper.impl.DemoWrapper
+wrapper2=org.apache.dubbo.common.extension.wrapper.impl.DemoWrapper2
+demo2=org.apache.dubbo.common.extension.wrapper.impl.DemoImpl
\ No newline at end of file
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
index 21f4675..4182ea6 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/registry/support/FailbackRegistry.java
@@ -51,10 +51,6 @@ public abstract class FailbackRegistry implements org.apache.dubbo.registry.Regi
         failbackRegistry.removeFailedUnsubscribedTask(url.getOriginalURL(), new NotifyListener.ReverseCompatibleNotifyListener(listener));
     }
 
-    public void removeFailedNotifiedTask(URL url, NotifyListener listener) {
-        failbackRegistry.removeFailedNotifiedTask(url.getOriginalURL(), new NotifyListener.ReverseCompatibleNotifyListener(listener));
-    }
-
     @Override
     public void register(URL url) {
         failbackRegistry.register(url.getOriginalURL());
diff --git a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java
index 5b9711e..b2bba70 100644
--- a/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java
+++ b/dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/protocol/dubbo/FutureAdapter.java
@@ -45,15 +45,28 @@ public class FutureAdapter<V> implements Future<V> {
         this.future = future;
     }
 
+    public FutureAdapter(ResponseFuture responseFuture) {
+        this.future = new CompletableFuture<>();
+        responseFuture.setCallback(new ResponseCallback() {
+            @Override
+            public void done(Object response) {
+                future.complete(response);
+            }
+
+            @Override
+            public void caught(Throwable exception) {
+                future.completeExceptionally(exception);
+            }
+        });
+    }
+
     public ResponseFuture getFuture() {
         return new ResponseFuture() {
             @Override
             public Object get() throws RemotingException {
                 try {
                     return future.get();
-                } catch (InterruptedException e) {
-                    throw new RemotingException(e);
-                } catch (ExecutionException e) {
+                } catch (InterruptedException | ExecutionException e) {
                     throw new RemotingException(e);
                 }
             }
@@ -62,11 +75,7 @@ public class FutureAdapter<V> implements Future<V> {
             public Object get(int timeoutInMillis) throws RemotingException {
                 try {
                     return future.get(timeoutInMillis, TimeUnit.MILLISECONDS);
-                } catch (InterruptedException e) {
-                    throw new RemotingException(e);
-                } catch (ExecutionException e) {
-                    throw new RemotingException(e);
-                } catch (TimeoutException e) {
+                } catch (InterruptedException | TimeoutException | ExecutionException e) {
                     throw new RemotingException(e);
                 }
             }
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/echo/EchoServiceTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/echo/EchoServiceTest.java
index 24cbfa2..b650b40 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/echo/EchoServiceTest.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/echo/EchoServiceTest.java
@@ -23,11 +23,10 @@ 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.service.EchoService;
 import org.apache.dubbo.service.DemoService;
 import org.apache.dubbo.service.DemoServiceImpl;
 
-import com.alibaba.dubbo.rpc.service.EchoService;
-
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/generic/GenericServiceTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/generic/GenericServiceTest.java
index fba3c40..d34121c 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/generic/GenericServiceTest.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/generic/GenericServiceTest.java
@@ -33,6 +33,7 @@ import org.apache.dubbo.service.ComplexObject;
 import org.apache.dubbo.service.DemoService;
 import org.apache.dubbo.service.DemoServiceImpl;
 
+import com.alibaba.dubbo.config.ReferenceConfig;
 import com.alibaba.fastjson.JSON;
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
@@ -89,6 +90,29 @@ public class GenericServiceTest {
     }
 
     @Test
+    public void testGenericCompatible() {
+        DemoService server = new DemoServiceImpl();
+        ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+        Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+        URL url = URL.valueOf("dubbo://127.0.0.1:5342/" + DemoService.class.getName() + "?version=1.0.0&generic=true$timeout=3000");
+        Exporter<DemoService> exporter = protocol.export(proxyFactory.getInvoker(server, DemoService.class, url));
+
+        // simulate normal invoke
+        ReferenceConfig<com.alibaba.dubbo.rpc.service.GenericService> oldReferenceConfig = new ReferenceConfig<>();
+        oldReferenceConfig.setGeneric(true);
+        oldReferenceConfig.setInterface(DemoService.class.getName());
+        oldReferenceConfig.checkAndUpdateSubConfigs();
+        Invoker invoker = protocol.refer(oldReferenceConfig.getInterfaceClass(), url);
+        com.alibaba.dubbo.rpc.service.GenericService client = (com.alibaba.dubbo.rpc.service.GenericService) proxyFactory.getProxy(invoker, true);
+
+        Object result = client.$invoke("sayHello", new String[]{"java.lang.String"}, new Object[]{"haha"});
+        Assertions.assertEquals("hello haha", result);
+
+        invoker.destroy();
+        exporter.unexport();
+    }
+
+    @Test
     public void testGenericComplexCompute4FullServiceMetadata() {
         DemoService server = new DemoServiceImpl();
         ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index 86880eb..501d365 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -160,5 +160,11 @@
             <scope>test</scope>
         </dependency>
 
+        <dependency>
+            <groupId>org.apache.curator</groupId>
+            <artifactId>curator-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 </project>
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 084a1ab..a12ef09 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
@@ -300,7 +300,8 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
         if (StringUtils.isEmpty(hostToRegistry)) {
             hostToRegistry = NetUtils.getLocalHost();
         } else if (isInvalidLocalHost(hostToRegistry)) {
-            throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
+            throw new IllegalArgumentException(
+                    "Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
         }
         map.put(REGISTER_IP_KEY, hostToRegistry);
 
@@ -364,7 +365,10 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
                         }
                     }
                     if (urls.isEmpty()) {
-                        throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
+                        throw new IllegalStateException(
+                                "No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() +
+                                        " use dubbo version " + Version.getVersion() +
+                                        ", please config <dubbo:registry address=\"...\" /> to your spring config.");
                     }
                 }
             }
@@ -375,11 +379,33 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
                 List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
                 URL registryURL = null;
                 for (URL url : urls) {
-                    invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
+                    Invoker<?> referInvoker = REF_PROTOCOL.refer(interfaceClass, url);
+                    if (shouldCheck()) {
+                        if (referInvoker.isAvailable()) {
+                            invokers.add(referInvoker);
+                        } else {
+                            referInvoker.destroy();
+                        }
+                    } else {
+                        invokers.add(referInvoker);
+                    }
+
                     if (UrlUtils.isRegistry(url)) {
                         registryURL = url; // use last registry url
                     }
                 }
+
+                if (shouldCheck() && invokers.size() == 0) {
+                    throw new IllegalStateException("Failed to check the status of the service "
+                            + interfaceName
+                            + ". No provider available for the service "
+                            + (group == null ? "" : group + "/")
+                            + interfaceName +
+                            (version == null ? "" : ":" + version)
+                            + " from the multi registry cluster"
+                            + " use dubbo version " + Version.getVersion());
+                }
+
                 if (registryURL != null) { // registry url is available
                     // for multi-subscription scenario, use 'zone-aware' policy by default
                     String cluster = registryURL.getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME);
@@ -387,7 +413,9 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
                     invoker = Cluster.getCluster(cluster, false).join(new StaticDirectory(registryURL, invokers));
                 } else { // not a registry url, must be direct invoke.
                     String cluster = CollectionUtils.isNotEmpty(invokers)
-                            ? (invokers.get(0).getUrl() != null ? invokers.get(0).getUrl().getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME) : Cluster.DEFAULT)
+                            ?
+                            (invokers.get(0).getUrl() != null ? invokers.get(0).getUrl().getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME) :
+                                    Cluster.DEFAULT)
                             : Cluster.DEFAULT;
                     invoker = Cluster.getCluster(cluster).join(new StaticDirectory(invokers));
                 }
@@ -430,11 +458,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
             throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
         }
         completeCompoundConfigs(consumer);
-        if (consumer != null) {
-            if (StringUtils.isEmpty(registryIds)) {
-                setRegistryIds(consumer.getRegistryIds());
-            }
-        }
         // get consumer's global configuration
         checkDefault();
 
@@ -459,12 +482,8 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
             checkInterfaceAndMethods(interfaceClass, getMethods());
         }
 
-        //init serivceMetadata
-        serviceMetadata.setVersion(getVersion());
-        serviceMetadata.setGroup(getGroup());
-        serviceMetadata.setDefaultGroup(getGroup());
+        initServiceMetadata(consumer);
         serviceMetadata.setServiceType(getActualInterface());
-        serviceMetadata.setServiceInterfaceName(interfaceName);
         // TODO, uncomment this line once service key is unified
         serviceMetadata.setServiceKey(URL.buildKey(interfaceName, group, version));
 
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 c1d7052..78a9f70 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
@@ -197,13 +197,10 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
 
         checkAndUpdateSubConfigs();
 
-        //init serviceMetadata
-        serviceMetadata.setVersion(getVersion());
-        serviceMetadata.setGroup(getGroup());
-        serviceMetadata.setDefaultGroup(getGroup());
+        initServiceMetadata(provider);
         serviceMetadata.setServiceType(getInterfaceClass());
-        serviceMetadata.setServiceInterfaceName(getInterface());
         serviceMetadata.setTarget(getRef());
+        serviceMetadata.generateServiceKey();
 
         if (!shouldExport()) {
             return;
@@ -334,8 +331,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
                     .orElse(path), group, version);
             // In case user specified path, register service one more time to map it to path.
             repository.registerService(pathKey, interfaceClass);
-            // TODO, uncomment this line once service key is unified
-            serviceMetadata.setServiceKey(pathKey);
             doExportUrlsFor1Protocol(protocolConfig, registryURLs);
         }
     }
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 e5544e4..ea9d8f8 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
@@ -23,7 +23,6 @@ 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.extension.ExtensionLoader;
-import org.apache.dubbo.common.lang.ShutdownHookCallback;
 import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
@@ -58,9 +57,6 @@ 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.event.EventDispatcher;
-import org.apache.dubbo.event.EventListener;
-import org.apache.dubbo.event.GenericEventListener;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.MetadataServiceExporter;
 import org.apache.dubbo.metadata.WritableMetadataService;
@@ -94,7 +90,7 @@ import java.util.function.Consumer;
 import java.util.function.Supplier;
 
 import static java.lang.String.format;
-import static java.util.Arrays.asList;
+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.DynamicConfiguration.getDynamicConfiguration;
@@ -123,7 +119,7 @@ import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
  *
  * @since 2.7.5
  */
-public class DubboBootstrap extends GenericEventListener {
+public class DubboBootstrap {
 
     public static final String DEFAULT_REGISTRY_ID = "REGISTRY#DEFAULT";
 
@@ -153,8 +149,6 @@ public class DubboBootstrap extends GenericEventListener {
 
     private final ExecutorService executorService = newSingleThreadExecutor();
 
-    private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
-
     private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
 
     private final ConfigManager configManager;
@@ -225,12 +219,7 @@ public class DubboBootstrap extends GenericEventListener {
         environment = ApplicationModel.getEnvironment();
 
         DubboShutdownHook.getDubboShutdownHook().register();
-        ShutdownHookCallbacks.INSTANCE.addCallback(new ShutdownHookCallback() {
-            @Override
-            public void callback() throws Throwable {
-                DubboBootstrap.this.destroy();
-            }
-        });
+        ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy);
     }
 
     public void unRegisterShutdownHook() {
@@ -366,7 +355,7 @@ public class DubboBootstrap extends GenericEventListener {
     }
 
     public DubboBootstrap protocol(ProtocolConfig protocolConfig) {
-        return protocols(asList(protocolConfig));
+        return protocols(singletonList(protocolConfig));
     }
 
     public DubboBootstrap protocols(List<ProtocolConfig> protocolConfigs) {
@@ -438,7 +427,7 @@ public class DubboBootstrap extends GenericEventListener {
     }
 
     public DubboBootstrap provider(ProviderConfig providerConfig) {
-        return providers(asList(providerConfig));
+        return providers(singletonList(providerConfig));
     }
 
     public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
@@ -462,7 +451,7 @@ public class DubboBootstrap extends GenericEventListener {
     }
 
     public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
-        return consumers(asList(consumerConfig));
+        return consumers(singletonList(consumerConfig));
     }
 
     public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
@@ -476,7 +465,7 @@ public class DubboBootstrap extends GenericEventListener {
 
     // {@link ConfigCenterConfig} correlative methods
     public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
-        return configCenters(asList(configCenterConfig));
+        return configCenters(singletonList(configCenterConfig));
     }
 
     public DubboBootstrap configCenters(List<ConfigCenterConfig> configCenterConfigs) {
@@ -551,8 +540,6 @@ public class DubboBootstrap extends GenericEventListener {
 
         initMetadataService();
 
-        initEventListener();
-
         if (logger.isInfoEnabled()) {
             logger.info(NAME + " has been initialized!");
         }
@@ -715,7 +702,9 @@ public class DubboBootstrap extends GenericEventListener {
         cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
         cc.setProtocol(protocol);
         cc.setPort(port);
-        cc.setGroup(registryConfig.getGroup());
+        if (StringUtils.isNotEmpty(registryConfig.getGroup())) {
+            cc.setGroup(registryConfig.getGroup());
+        }
         cc.setAddress(getRegistryCompatibleAddress(registryConfig));
         cc.setNamespace(registryConfig.getGroup());
         cc.setUsername(registryConfig.getUsername());
@@ -887,14 +876,6 @@ public class DubboBootstrap extends GenericEventListener {
     }
 
     /**
-     * Initialize {@link EventListener}
-     */
-    private void initEventListener() {
-        // Add current instance into listeners
-        addEventListener(this);
-    }
-
-    /**
      * Start the bootstrap
      */
     public DubboBootstrap start() {
@@ -927,12 +908,16 @@ public class DubboBootstrap extends GenericEventListener {
                     if (logger.isInfoEnabled()) {
                         logger.info(NAME + " is ready.");
                     }
+                    ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
+                    exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
                 }).start();
             } else {
                 startup.set(true);
                 if (logger.isInfoEnabled()) {
                     logger.info(NAME + " is ready.");
                 }
+                ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
+                exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
             }
             if (logger.isInfoEnabled()) {
                 logger.info(NAME + " has started.");
@@ -1002,6 +987,7 @@ public class DubboBootstrap extends GenericEventListener {
         return shutdown.get();
     }
 
+
     public DubboBootstrap stop() throws IllegalStateException {
         destroy();
         return this;
@@ -1066,17 +1052,6 @@ public class DubboBootstrap extends GenericEventListener {
     }
 
     /**
-     * Add an instance of {@link EventListener}
-     *
-     * @param listener {@link EventListener}
-     * @return {@link DubboBootstrap}
-     */
-    public DubboBootstrap addEventListener(EventListener<?> listener) {
-        eventDispatcher.addEventListener(listener);
-        return this;
-    }
-
-    /**
      * export {@link MetadataService}
      */
     private void exportMetadataService() {
@@ -1098,8 +1073,12 @@ public class DubboBootstrap extends GenericEventListener {
             if (exportAsync) {
                 ExecutorService executor = executorRepository.getServiceExporterExecutor();
                 Future<?> future = executor.submit(() -> {
-                    sc.export();
-                    exportedServices.add(sc);
+                	try {
+                        sc.export();
+                        exportedServices.add(sc);
+                	}catch (Throwable t) {
+                		logger.error("export async catch error : " + t.getMessage(), t);
+					}
                 });
                 asyncExportingFutures.add(future);
             } else {
@@ -1244,12 +1223,14 @@ public class DubboBootstrap extends GenericEventListener {
                     unreferServices();
 
                     destroyRegistries();
-                    DubboShutdownHook.destroyProtocols();
+
                     destroyServiceDiscoveries();
 
                     clear();
                     shutdown();
                     release();
+                    ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
+                    exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(this));
                 }
             } finally {
                 destroyLock.unlock();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrapStartStopListener.java
similarity index 72%
copy from dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
copy to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrapStartStopListener.java
index 773f532..dc7818d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/DirectEventDispatcher.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrapStartStopListener.java
@@ -14,17 +14,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.event;
+
+package org.apache.dubbo.config.bootstrap;
+
+import org.apache.dubbo.common.extension.SPI;
 
 /**
- * Direct {@link EventDispatcher} implementation uses current thread execution model
+ * call on DubboBootstrap start or stop.
  *
- * @see EventDispatcher
- * @since 2.7.5
+ * @scene 2.7.9
+ * @see DubboBootstrap
  */
-public final class DirectEventDispatcher extends AbstractEventDispatcher {
+@SPI
+public interface DubboBootstrapStartStopListener {
+
+    void onStart(DubboBootstrap bootstrap);
 
-    public DirectEventDispatcher() {
-        super(DIRECT_EXECUTOR);
-    }
+    void onStop(DubboBootstrap bootstrap);
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
index 99af153..9608b7f 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
@@ -31,7 +31,7 @@ import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
  *
  * @since 2.7
  */
-public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfig, ReferenceBuilder<T>> {
+public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfig<T>, ReferenceBuilder<T>> {
     /**
      * The interface name of the reference service
      */
@@ -74,8 +74,8 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
      */
     private String services;
 
-    public static ReferenceBuilder newBuilder() {
-        return new ReferenceBuilder();
+    public static <T> ReferenceBuilder<T> newBuilder() {
+        return new ReferenceBuilder<>();
     }
 
     public ReferenceBuilder<T> id(String id) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ServiceBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ServiceBuilder.java
index cfea580..b02e7c1 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ServiceBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ServiceBuilder.java
@@ -29,7 +29,7 @@ import java.util.List;
  *
  * @since 2.7
  */
-public class ServiceBuilder<U> extends AbstractServiceBuilder<ServiceConfig, ServiceBuilder<U>> {
+public class ServiceBuilder<U> extends AbstractServiceBuilder<ServiceConfig<U>, ServiceBuilder<U>> {
     /**
      * The interface name of the exported service
      */
@@ -69,11 +69,11 @@ public class ServiceBuilder<U> extends AbstractServiceBuilder<ServiceConfig, Ser
      */
     private String generic;
 
-    public static ServiceBuilder newBuilder() {
-        return new ServiceBuilder();
+    public static <T> ServiceBuilder<T> newBuilder() {
+        return new ServiceBuilder<>();
     }
 
-    public ServiceBuilder id(String id) {
+    public ServiceBuilder<U> id(String id) {
         return super.id(id);
     }
 
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 3422809..2e3f5e6 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
@@ -50,7 +50,7 @@ import org.apache.dubbo.config.SslConfig;
 import org.apache.dubbo.monitor.MonitorFactory;
 import org.apache.dubbo.monitor.MonitorService;
 import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.remoting.Codec;
+import org.apache.dubbo.remoting.Codec2;
 import org.apache.dubbo.remoting.Dispatcher;
 import org.apache.dubbo.remoting.Transporter;
 import org.apache.dubbo.remoting.exchange.Exchanger;
@@ -63,7 +63,10 @@ import org.apache.dubbo.rpc.cluster.Cluster;
 import org.apache.dubbo.rpc.cluster.LoadBalance;
 import org.apache.dubbo.rpc.support.MockInvoker;
 
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -104,6 +107,7 @@ 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;
 import static org.apache.dubbo.config.Constants.ENVIRONMENT;
+import static org.apache.dubbo.config.Constants.IGNORE_CHECK_KEYS;
 import static org.apache.dubbo.config.Constants.LAYER_KEY;
 import static org.apache.dubbo.config.Constants.NAME;
 import static org.apache.dubbo.config.Constants.ORGANIZATION;
@@ -173,6 +177,10 @@ public class ConfigValidationUtils {
      */
     private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
 
+    public static final String IPV6_START_MARK = "[";
+
+    public static final String IPV6_END_MARK = "]";
+
     public static List<URL> loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider) {
         // check && override if necessary
         List<URL> registryList = new ArrayList<URL>();
@@ -503,12 +511,12 @@ public class ConfigValidationUtils {
         if (config != null) {
             String name = config.getName();
             checkName("name", name);
-            checkName(HOST_KEY, config.getHost());
+            checkHost(HOST_KEY, config.getHost());
             checkPathName("contextpath", config.getContextpath());
 
 
             if (DUBBO_PROTOCOL.equals(name)) {
-                checkMultiExtension(Codec.class, CODEC_KEY, config.getCodec());
+                checkMultiExtension(Codec2.class, CODEC_KEY, config.getCodec());
                 checkMultiExtension(Serialization.class, SERIALIZATION_KEY, config.getSerialization());
                 checkMultiExtension(Transporter.class, SERVER_KEY, config.getServer());
                 checkMultiExtension(Transporter.class, CLIENT_KEY, config.getClient());
@@ -622,6 +630,22 @@ public class ConfigValidationUtils {
         checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
     }
 
+    public static void checkHost(String property, String value) {
+        if (StringUtils.isEmpty(value)) {
+            return;
+        }
+        if (value.startsWith(IPV6_START_MARK) && value.endsWith(IPV6_END_MARK)) {
+            // if the value start with "[" and end with "]", check whether it is IPV6
+            try {
+                InetAddress.getByName(value);
+                return;
+            } catch (UnknownHostException e) {
+                // not a IPv6 string, do nothing, go on to checkName
+            }
+        }
+        checkName(property, value);
+    }
+
     public static void checkNameHasSymbol(String property, String value) {
         checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL);
     }
@@ -646,8 +670,14 @@ public class ConfigValidationUtils {
         if (CollectionUtils.isEmptyMap(parameters)) {
             return;
         }
+        List<String> ignoreCheckKeys = new ArrayList<>();
+        ignoreCheckKeys.add(BACKUP_KEY);
+        String ignoreCheckKeysStr = parameters.get(IGNORE_CHECK_KEYS);
+        if (!StringUtils.isBlank(ignoreCheckKeysStr)) {
+            ignoreCheckKeys.addAll(Arrays.asList(ignoreCheckKeysStr.split(",")));
+        }
         for (Map.Entry<String, String> entry : parameters.entrySet()) {
-            if (!entry.getKey().equals(BACKUP_KEY)) {
+            if (!ignoreCheckKeys.contains(entry.getKey())) {
                 checkNameHasSymbol(entry.getKey(), entry.getValue());
             }
         }
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
index 0f4c8fe..3d90c3b 100644
--- a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
@@ -1 +1 @@
-config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
\ No newline at end of file
+config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
index 1b843b6..2bda3f2 100644
--- a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
@@ -1,3 +1,2 @@
 # since 2.7.8
 local = org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter
-remote = org.apache.dubbo.config.metadata.RemoteMetadataServiceExporter
\ No newline at end of file
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 04d5f72..d81f51c 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
@@ -107,6 +107,15 @@ public class AbstractConfigTest {
     }*/
 
     @Test
+    public void testValidateProtocolConfig() {
+        ProtocolConfig protocolConfig = new ProtocolConfig();
+        protocolConfig.setCodec("exchange");
+        protocolConfig.setName("test");
+        protocolConfig.setHost("host");
+        ConfigValidationUtils.validateProtocolConfig(protocolConfig);
+    }
+
+    @Test
     public void testAppendParameters1() throws Exception {
         Map<String, String> parameters = new HashMap<String, String>();
         parameters.put("num", "ONE");
@@ -170,12 +179,14 @@ public class AbstractConfigTest {
 
     @Test
     public void checkMultiExtension1() throws Exception {
-        Assertions.assertThrows(IllegalStateException.class, () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,world"));
+        Assertions.assertThrows(IllegalStateException.class,
+                () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,world"));
     }
 
     @Test
     public void checkMultiExtension2() throws Exception {
-        Assertions.assertThrows(IllegalStateException.class, () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,-world"));
+        Assertions.assertThrows(IllegalStateException.class,
+                () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,-world"));
     }
 
     @Test
diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MetadataReportConfigTest.java
similarity index 56%
copy from dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java
copy to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MetadataReportConfigTest.java
index 23484c6..463f383 100644
--- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MetadataReportConfigTest.java
@@ -6,7 +6,7 @@
  * (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
+ *      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,
@@ -14,25 +14,27 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.cache.support.expiring;
 
-import org.apache.dubbo.cache.Cache;
-import org.apache.dubbo.cache.support.AbstractCacheFactory;
-import org.apache.dubbo.cache.support.AbstractCacheFactoryTest;
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.URL;
+
 import org.junit.jupiter.api.Test;
 
-import static org.hamcrest.core.Is.is;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.equalTo;
 
-public class ExpiringCacheFactoryTest extends AbstractCacheFactoryTest {
+public class MetadataReportConfigTest {
     @Test
-    public void testLruCacheFactory() throws Exception {
-        Cache cache = super.constructCache();
-        assertThat(cache instanceof ExpiringCache, is(true));
-    }
+    public void testFile() {
+        MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
+        metadataReportConfig.setFile("file");
+        assertThat(metadataReportConfig.getFile(), equalTo("file"));
+
+        metadataReportConfig.setAddress("127.0.0.1:2181");
+        URL url = metadataReportConfig.toUrl();
+        assertThat(url.getParameter("file"), equalTo("file"));
 
-    @Override
-    protected AbstractCacheFactory getCacheFactory() {
-        return new ExpiringCacheFactory();
     }
-}
\ No newline at end of file
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
index c064f95..6b853d2 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/MethodConfigTest.java
@@ -87,12 +87,12 @@ public class MethodConfigTest {
         assertThat(EXECUTES, equalTo(methodConfig.getExecutes().intValue()));
         assertThat(DEPERECATED, equalTo(methodConfig.getDeprecated()));
         assertThat(STICKY, equalTo(methodConfig.getSticky()));
-//        assertThat(ONINVOKE, equalTo(methodConfig.getOninvoke()));
-//        assertThat(ONINVOKE_METHOD, equalTo(methodConfig.getOninvokeMethod()));
-//        assertThat(ONTHROW, equalTo(methodConfig.getOnthrow()));
-//        assertThat(ONTHROW_METHOD, equalTo(methodConfig.getOnthrowMethod()));
-//        assertThat(ONRETURN, equalTo(methodConfig.getOnreturn()));
-//        assertThat(ONRETURN_METHOD, equalTo(methodConfig.getOnreturnMethod()));
+        assertThat(ONINVOKE, equalTo(methodConfig.getOninvoke()));
+        assertThat(ONINVOKE_METHOD, equalTo(methodConfig.getOninvokeMethod()));
+        assertThat(ONTHROW, equalTo(methodConfig.getOnthrow()));
+        assertThat(ONTHROW_METHOD, equalTo(methodConfig.getOnthrowMethod()));
+        assertThat(ONRETURN, equalTo(methodConfig.getOnreturn()));
+        assertThat(ONRETURN_METHOD, equalTo(methodConfig.getOnreturnMethod()));
         assertThat(CACHE, equalTo(methodConfig.getCache()));
         assertThat(VALIDATION, equalTo(methodConfig.getValidation()));
         assertThat(ARGUMENTS_INDEX, equalTo(methodConfig.getArguments().get(0).getIndex().intValue()));
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 3e8ad3a..0dbf17f 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
@@ -16,44 +16,58 @@
  */
 package org.apache.dubbo.config;
 
+import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.config.annotation.Argument;
 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.provider.impl.DemoServiceImpl;
 import org.apache.dubbo.rpc.model.ApplicationModel;
 
+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 java.io.IOException;
+
 import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
 import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
 
 public class ReferenceConfigTest {
+    private TestingServer zkServer;
+    private String registryUrl;
 
     @BeforeEach
-    public void setUp() {
+    public void setUp() throws Exception {
         ApplicationModel.reset();
+        int zkServerPort = NetUtils.getAvailablePort(NetUtils.getRandomPort());
+        this.zkServer = new TestingServer(zkServerPort, true);
+        this.zkServer.start();
+        this.registryUrl = "zookeeper://localhost:" + zkServerPort;
     }
 
     @AfterEach
-    public void tearDown() {
+    public void tearDown() throws IOException {
+        zkServer.stop();
         ApplicationModel.reset();
     }
 
     @Test
+    @Disabled("Disabled due to Github Actions environment")
     public void testInjvm() throws Exception {
         ApplicationConfig application = new ApplicationConfig();
         application.setName("test-protocol-random-port");
         ApplicationModel.getConfigManager().setApplication(application);
 
         RegistryConfig registry = new RegistryConfig();
-        registry.setAddress("multicast://224.5.6.7:1234");
+        registry.setAddress(registryUrl);
 
         ProtocolConfig protocol = new ProtocolConfig();
-        protocol.setName("mockprotocol");
+        protocol.setName("dubbo");
 
         ServiceConfig<DemoService> demoService;
         demoService = new ServiceConfig<DemoService>();
@@ -75,8 +89,12 @@ public class ReferenceConfigTest {
                     rc.getInvoker().getUrl().getProtocol()));
         } finally {
             System.clearProperty("java.net.preferIPv4Stack");
+            rc.destroy();
             demoService.unexport();
         }
+
+        // Manually trigger dubbo resource recycling.
+        DubboBootstrap.getInstance().destroy();
     }
 
     /**
@@ -89,7 +107,7 @@ public class ReferenceConfigTest {
         ApplicationModel.getConfigManager().setApplication(application);
 
         RegistryConfig registry = new RegistryConfig();
-        registry.setAddress("multicast://224.5.6.7:1234");
+        registry.setAddress(registryUrl);
         ProtocolConfig protocol = new ProtocolConfig();
         protocol.setName("mockprotocol");
 
@@ -122,6 +140,8 @@ public class ReferenceConfigTest {
         } catch (Exception e) {
             e.printStackTrace();
         } finally {
+            rc.destroy();
+            sc.unexport();
             System.clearProperty("java.net.preferIPv4Stack");
         }
         Assertions.assertTrue(success);
@@ -141,15 +161,15 @@ public class ReferenceConfigTest {
         Assertions.assertEquals(3, (int) ((MethodConfig) referenceConfig.getMethods().get(0)).getActives());
         Assertions.assertEquals(5, (int) ((MethodConfig) referenceConfig.getMethods().get(0)).getExecutes());
         Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).isAsync());
-        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i");
-        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r");
-        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvokeMethod(), "i");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturnMethod(), "r");
+        Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrowMethod(), "t");
         Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c");
     }
 
 
     @Reference(methods = {@Method(name = "sayHello", timeout = 1300, retries = 4, loadbalance = "random", async = true,
-            actives = 3, executes = 5, deprecated = true, sticky = true, oninvoke = "i", onthrow = "t", onreturn = "r", cache = "c", validation = "v",
+            actives = 3, executes = 5, deprecated = true, sticky = true, oninvoke = "instance.i", onthrow = "instance.t", onreturn = "instance.r", cache = "c", validation = "v",
             arguments = {@Argument(index = 24, callback = true, type = "sss")})})
     private InnerTest innerTest;
 
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 fb74b1e..4a63037 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,6 +17,9 @@
 
 package org.apache.dubbo.config;
 
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.UrlUtils;
+
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -24,6 +27,7 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 
+import static org.apache.dubbo.common.constants.CommonConstants.PREFERRED_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
 import static org.apache.dubbo.config.Constants.SHUTDOWN_TIMEOUT_KEY;
 import static org.hamcrest.CoreMatchers.is;
@@ -187,4 +191,28 @@ public class RegistryConfigTest {
         Assertions.assertNotEquals(registry1, registry2);
     }
 
+    @Test
+    public void testPreferredWithTrueValue() {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setPreferred(true);
+        Map<String, String> map = new HashMap<>();
+        // process Parameter annotation
+        AbstractConfig.appendParameters(map, registry);
+        // Simulate the check that ZoneAwareClusterInvoker#doInvoke do
+        URL url = UrlUtils.parseURL("zookeeper://127.0.0.1:2181", map);
+        Assertions.assertTrue(url.getParameter(PREFERRED_KEY, false));
+    }
+
+    @Test
+    public void testPreferredWithFalseValue() {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setPreferred(false);
+        Map<String, String> map = new HashMap<>();
+        // Process Parameter annotation
+        AbstractConfig.appendParameters(map, registry);
+        // Simulate the check that ZoneAwareClusterInvoker#doInvoke do
+        URL url = UrlUtils.parseURL("zookeeper://127.0.0.1:2181", map);
+        Assertions.assertFalse(url.getParameter(PREFERRED_KEY, false));
+    }
+
 }
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 ed46382..72f39ae 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
@@ -45,11 +45,13 @@ import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_BEAN;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_DEFAULT;
 import static org.apache.dubbo.common.constants.CommonConstants.GENERIC_SERIALIZATION_NATIVE_JAVA;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER;
 import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
 import static org.apache.dubbo.config.Constants.SHUTDOWN_TIMEOUT_KEY;
 import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
 import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
@@ -155,11 +157,29 @@ public class ServiceConfigTest {
     }
 
     @Test
+    public void testVersionAndGroupConfigFromProvider() {
+        //Service no configuration version , the Provider configured.
+        service.getProvider().setVersion("1.0.0");
+        service.getProvider().setGroup("groupA");
+        service.export();
+
+        String serviceVersion = service.getVersion();
+        String serviceVersion2 = service.toUrl().getParameter(VERSION_KEY);
+
+        String group = service.getGroup();
+        String group2 = service.toUrl().getParameter(GROUP_KEY);
+
+        assertEquals(serviceVersion2, serviceVersion);
+        assertEquals(group, group2);
+    }
+
+    @Test
     public void testProxy() throws Exception {
         service2.export();
 
         assertThat(service2.getExportedUrls(), hasSize(1));
         assertEquals(2, TestProxyFactory.count); // local injvm and registry protocol, so expected is 2
+        TestProxyFactory.count = 0;
     }
 
 
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java
index ad571f8..0d6209f 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java
@@ -51,6 +51,7 @@ public class PublishingServiceDefinitionListenerTest {
 
     @BeforeEach
     public void init() {
+        ApplicationModel.reset();
         String metadataType = DEFAULT_METADATA_STORAGE_TYPE;
         ConfigManager configManager = ApplicationModel.getConfigManager();
         ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-demo-provider");
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
index ec99c1c..8b75859 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/config/DubboConfigDefaultPropertyValueBeanPostProcessor.java
@@ -16,7 +16,9 @@
  */
 package org.apache.dubbo.config.spring.beans.factory.config;
 
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.ProtocolConfig;
 
 import com.alibaba.spring.beans.factory.config.GenericBeanPostProcessorAdapter;
 import org.springframework.beans.BeansException;
@@ -54,7 +56,14 @@ public class DubboConfigDefaultPropertyValueBeanPostProcessor extends GenericBea
     protected void processBeforeInitialization(AbstractConfig dubboConfigBean, String beanName) throws BeansException {
         // [Feature] https://github.com/apache/dubbo/issues/5721
         setBeanNameAsDefaultValue(dubboConfigBean, "id", beanName);
-        setBeanNameAsDefaultValue(dubboConfigBean, "name", beanName);
+        if (dubboConfigBean instanceof ProtocolConfig) {
+            ProtocolConfig config = (ProtocolConfig) dubboConfigBean;
+            if (StringUtils.isEmpty(config.getName())) {
+                config.setName("dubbo");
+            }
+        } else {
+            setBeanNameAsDefaultValue(dubboConfigBean, "name", beanName);
+        }
     }
 
     @Override
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
index 4a98880..1911eb5 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
@@ -16,8 +16,11 @@
  */
 package org.apache.dubbo.config.spring.context;
 
+import org.apache.dubbo.config.DubboShutdownHook;
 import org.apache.dubbo.config.bootstrap.DubboBootstrap;
 
+import com.alibaba.spring.context.OnceApplicationContextEventListener;
+import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ApplicationContextEvent;
 import org.springframework.context.event.ContextClosedEvent;
@@ -30,8 +33,7 @@ import org.springframework.core.Ordered;
  *
  * @since 2.7.5
  */
-public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener
-        implements Ordered {
+public class DubboBootstrapApplicationListener extends OnceApplicationContextEventListener implements Ordered {
 
     /**
      * The bean name of {@link DubboBootstrapApplicationListener}
@@ -46,8 +48,17 @@ public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicati
         this.dubboBootstrap = DubboBootstrap.getInstance();
     }
 
+    public DubboBootstrapApplicationListener(ApplicationContext applicationContext) {
+        super(applicationContext);
+        this.dubboBootstrap = DubboBootstrap.getInstance();
+        DubboBootstrapStartStopListenerSpringAdapter.applicationContext = applicationContext;
+    }
+
     @Override
     public void onApplicationContextEvent(ApplicationContextEvent event) {
+        if (DubboBootstrapStartStopListenerSpringAdapter.applicationContext == null) {
+            DubboBootstrapStartStopListenerSpringAdapter.applicationContext = event.getApplicationContext();
+        }
         if (event instanceof ContextRefreshedEvent) {
             onContextRefreshedEvent((ContextRefreshedEvent) event);
         } else if (event instanceof ContextClosedEvent) {
@@ -60,7 +71,7 @@ public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicati
     }
 
     private void onContextClosedEvent(ContextClosedEvent event) {
-        dubboBootstrap.stop();
+        DubboShutdownHook.getDubboShutdownHook().run();
     }
 
     @Override
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapStartStopListenerSpringAdapter.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapStartStopListenerSpringAdapter.java
new file mode 100644
index 0000000..3ae3dcf
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapStartStopListenerSpringAdapter.java
@@ -0,0 +1,48 @@
+/*
+ * 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.spring.context;
+
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.bootstrap.DubboBootstrapStartStopListener;
+import org.apache.dubbo.config.spring.context.event.DubboBootstrapStatedEvent;
+import org.apache.dubbo.config.spring.context.event.DubboBootstrapStopedEvent;
+
+import org.springframework.context.ApplicationContext;
+
+/**
+ * convcert Dubbo bootstrap event to spring environment.
+ *
+ * @scene 2.7.9
+ */
+public class DubboBootstrapStartStopListenerSpringAdapter implements DubboBootstrapStartStopListener {
+
+    static ApplicationContext applicationContext;
+
+    @Override
+    public void onStart(DubboBootstrap bootstrap) {
+        if (applicationContext != null) {
+            applicationContext.publishEvent(new DubboBootstrapStatedEvent(bootstrap));
+        }
+    }
+
+    @Override
+    public void onStop(DubboBootstrap bootstrap) {
+        if (applicationContext != null) {
+            applicationContext.publishEvent(new DubboBootstrapStopedEvent(bootstrap));
+        }
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java
index 7e7ae83..46cf1ce 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring.context;
 
 import org.apache.dubbo.common.context.Lifecycle;
 
+import com.alibaba.spring.context.OnceApplicationContextEventListener;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ApplicationContextEvent;
@@ -39,7 +40,7 @@ import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncl
  * @see SmartApplicationListener
  * @since 2.7.5
  */
-public class DubboLifecycleComponentApplicationListener extends OneTimeExecutionApplicationContextEventListener {
+public class DubboLifecycleComponentApplicationListener extends OnceApplicationContextEventListener {
 
     /**
      * The bean name of {@link DubboLifecycleComponentApplicationListener}
@@ -50,6 +51,13 @@ public class DubboLifecycleComponentApplicationListener extends OneTimeExecution
 
     private List<Lifecycle> lifecycleComponents = emptyList();
 
+    public DubboLifecycleComponentApplicationListener() {
+    }
+
+    public DubboLifecycleComponentApplicationListener(ApplicationContext applicationContext) {
+        super(applicationContext);
+    }
+
     @Override
     protected void onApplicationContextEvent(ApplicationContextEvent event) {
         if (event instanceof ContextRefreshedEvent) {
@@ -70,7 +78,6 @@ public class DubboLifecycleComponentApplicationListener extends OneTimeExecution
 
     private void initLifecycleComponents(ContextRefreshedEvent event) {
         ApplicationContext context = event.getApplicationContext();
-        ClassLoader classLoader = context.getClassLoader();
         lifecycleComponents = new LinkedList<>();
         // load the Beans of Lifecycle from ApplicationContext
         loadLifecycleComponents(lifecycleComponents, context);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java
deleted file mode 100644
index 569a67e..0000000
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java
+++ /dev/null
@@ -1,71 +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.config.spring.context;
-
-import org.springframework.beans.BeansException;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ApplicationEvent;
-import org.springframework.context.ApplicationListener;
-import org.springframework.context.event.ApplicationContextEvent;
-
-import java.util.Objects;
-
-/**
- * The abstract class {@link ApplicationListener} for {@link ApplicationContextEvent} guarantees just one-time execution
- * and prevents the event propagation in the hierarchical {@link ApplicationContext ApplicationContexts}
- *
- * @since 2.7.5
- */
-abstract class OneTimeExecutionApplicationContextEventListener implements ApplicationListener, ApplicationContextAware {
-
-    private ApplicationContext applicationContext;
-
-    public final void onApplicationEvent(ApplicationEvent event) {
-        if (isOriginalEventSource(event) && event instanceof ApplicationContextEvent) {
-            onApplicationContextEvent((ApplicationContextEvent) event);
-        }
-    }
-
-    /**
-     * The subclass overrides this method to handle {@link ApplicationContextEvent}
-     *
-     * @param event {@link ApplicationContextEvent}
-     */
-    protected abstract void onApplicationContextEvent(ApplicationContextEvent event);
-
-    /**
-     * Is original {@link ApplicationContext} as the event source
-     *
-     * @param event {@link ApplicationEvent}
-     * @return
-     */
-    private boolean isOriginalEventSource(ApplicationEvent event) {
-        return (applicationContext == null) // Current ApplicationListener is not a Spring Bean, just was added
-                // into Spring's ConfigurableApplicationContext
-                || Objects.equals(applicationContext, event.getSource());
-    }
-
-    @Override
-    public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
-        this.applicationContext = applicationContext;
-    }
-
-    public ApplicationContext getApplicationContext() {
-        return applicationContext;
-    }
-}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfig.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfig.java
index 1ec03e7..3d5e085 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfig.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboConfig.java
@@ -24,6 +24,7 @@ import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 
+import com.alibaba.spring.beans.factory.annotation.EnableConfigurationBeanBinding;
 import org.springframework.context.annotation.Import;
 
 import java.lang.annotation.Documented;
@@ -34,7 +35,7 @@ import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 
 /**
- * As  a convenient and multiple {@link EnableDubboConfigBinding}
+ * As a convenient and multiple {@link EnableConfigurationBeanBinding}
  * in default behavior , is equal to single bean bindings with below convention prefixes of properties:
  * <ul>
  * <li>{@link ApplicationConfig} binding to property : "dubbo.application"</li>
@@ -57,7 +58,7 @@ import java.lang.annotation.Target;
  * <li>{@link ConsumerConfig} binding to property :  "dubbo.consumers"</li>
  * </ul>
  *
- * @see EnableDubboConfigBinding
+ * @see EnableConfigurationBeanBinding
  * @see DubboConfigConfiguration
  * @see DubboConfigConfigurationRegistrar
  * @since 2.5.8
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStatedEvent.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStatedEvent.java
new file mode 100644
index 0000000..11b0e2e
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStatedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring.context.event;
+
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * A {@link org.springframework.context.ApplicationEvent} after {@link org.apache.dubbo.config.bootstrap.DubboBootstrap#start()} success
+ *
+ * @see org.springframework.context.ApplicationEvent
+ * @see org.springframework.context.ApplicationListener
+ * @see org.apache.dubbo.config.bootstrap.DubboBootstrap
+ * @since 2.7.9
+ */
+public class DubboBootstrapStatedEvent extends ApplicationEvent {
+
+    /**
+     * Create a new ApplicationEvent.
+     *
+     * @param bootstrap {@link org.apache.dubbo.config.bootstrap.DubboBootstrap} bootstrap
+     */
+    public DubboBootstrapStatedEvent(DubboBootstrap bootstrap) {
+        super(bootstrap);
+    }
+
+    /**
+     * Get {@link org.apache.dubbo.config.bootstrap.DubboBootstrap} instance
+     *
+     * @return non-null
+     */
+    public DubboBootstrap getDubboBootstrap() {
+        return (DubboBootstrap) super.getSource();
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStopedEvent.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStopedEvent.java
new file mode 100644
index 0000000..0f5b5bf
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboBootstrapStopedEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring.context.event;
+
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * A {@link org.springframework.context.ApplicationEvent} after {@link org.apache.dubbo.config.bootstrap.DubboBootstrap#stop()} success
+ *
+ * @see org.springframework.context.ApplicationEvent
+ * @see org.springframework.context.ApplicationListener
+ * @see org.apache.dubbo.config.bootstrap.DubboBootstrap
+ * @since 2.7.9
+ */
+public class DubboBootstrapStopedEvent extends ApplicationEvent {
+
+    /**
+     * Create a new ApplicationEvent.
+     *
+     * @param bootstrap {@link org.apache.dubbo.config.bootstrap.DubboBootstrap} bootstrap
+     */
+    public DubboBootstrapStopedEvent(DubboBootstrap bootstrap) {
+        super(bootstrap);
+    }
+
+    /**
+     * Get {@link org.apache.dubbo.config.bootstrap.DubboBootstrap} instance
+     *
+     * @return non-null
+     */
+    public DubboBootstrap getDubboBootstrap() {
+        return (DubboBootstrap) super.getSource();
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java
index 1c87e95..e2d1e8a 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinder.java
@@ -19,9 +19,13 @@ package org.apache.dubbo.config.spring.context.properties;
 import org.apache.dubbo.config.AbstractConfig;
 
 import org.springframework.beans.MutablePropertyValues;
+import org.springframework.validation.BindingResult;
 import org.springframework.validation.DataBinder;
+import org.springframework.validation.FieldError;
 
+import java.util.List;
 import java.util.Map;
+import java.util.stream.IntStream;
 
 import static com.alibaba.spring.util.PropertySourcesUtils.getSubProperties;
 
@@ -42,7 +46,25 @@ public class DefaultDubboConfigBinder extends AbstractDubboConfigBinder {
         MutablePropertyValues propertyValues = new MutablePropertyValues(properties);
         // Bind
         dataBinder.bind(propertyValues);
+        BindingResult bindingResult = dataBinder.getBindingResult();
+        if (bindingResult.hasGlobalErrors()) {
+            throw new RuntimeException("Data bind global error, please check config. config: " + bindingResult.getGlobalError() + "");
+        }
+        if (bindingResult.hasFieldErrors()) {
+            throw new RuntimeException(buildErrorMsg(bindingResult.getFieldErrors(), prefix, dubboConfig.getClass().getSimpleName()));
+        }
     }
 
+    private String buildErrorMsg(List<FieldError> errors, String prefix, String config) {
+        StringBuilder builder = new StringBuilder("Data bind error, please check config. config: " + config + ", prefix: " + prefix
+                + " , error fields: [" + errors.get(0).getField());
+        if (errors.size() > 1) {
+            IntStream.range(1, errors.size()).forEach(i -> {
+                builder.append(", " + errors.get(i).getField());
+            });
+        }
+        builder.append("]");
+        return builder.toString();
+    }
 }
 
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/SpringExtensionFactory.java
index c7b6e77..da887b2 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/SpringExtensionFactory.java
@@ -21,6 +21,7 @@ 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.ConcurrentHashSet;
+import org.apache.dubbo.config.DubboShutdownHook;
 
 import com.alibaba.spring.util.BeanFactoryUtils;
 import org.springframework.context.ApplicationContext;
@@ -40,6 +41,8 @@ public class SpringExtensionFactory implements ExtensionFactory {
         CONTEXTS.add(context);
         if (context instanceof ConfigurableApplicationContext) {
             ((ConfigurableApplicationContext) context).registerShutdownHook();
+            // see https://github.com/apache/dubbo/issues/7093
+            DubboShutdownHook.getDubboShutdownHook().unregister();
         }
     }
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index a747e00..71c1048 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -66,7 +66,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport implements Co
         registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
         registerBeanDefinitionParser("protocol", new DubboBeanDefinitionParser(ProtocolConfig.class, true));
         registerBeanDefinitionParser("service", new DubboBeanDefinitionParser(ServiceBean.class, true));
-        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, false));
+        registerBeanDefinitionParser("reference", new DubboBeanDefinitionParser(ReferenceBean.class, true));
         registerBeanDefinitionParser("annotation", new AnnotationBeanDefinitionParser());
     }
 
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index cf20146..8ed2ac7 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -1079,6 +1079,11 @@
                 <xsd:documentation><![CDATA[ The IO thread pool size. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="alive" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The thread pool keepAliveTime. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
         <xsd:attribute name="queues" type="xsd:string">
             <xsd:annotation>
                 <xsd:documentation><![CDATA[ The thread pool queue size. ]]></xsd:documentation>
@@ -1255,6 +1260,11 @@
                         <xsd:documentation><![CDATA[ The IO thread pool size. ]]></xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
+                <xsd:attribute name="alive" type="xsd:string">
+                    <xsd:annotation>
+                        <xsd:documentation><![CDATA[ The thread pool keepAliveTime. ]]></xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
                 <xsd:attribute name="queues" type="xsd:string">
                     <xsd:annotation>
                         <xsd:documentation><![CDATA[ The thread pool queue size. ]]></xsd:documentation>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 57efa02..0647827 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -710,6 +710,11 @@
                 <xsd:documentation><![CDATA[ registry config id. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="file" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The metadata report file store. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
     </xsd:complexType>
 
     <xsd:complexType name="configCenterType">
@@ -1101,6 +1106,11 @@
                 <xsd:documentation><![CDATA[ The IO thread pool size. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
+        <xsd:attribute name="alive" type="xsd:string">
+            <xsd:annotation>
+                <xsd:documentation><![CDATA[ The thread pool keepAliveTime. ]]></xsd:documentation>
+            </xsd:annotation>
+        </xsd:attribute>
         <xsd:attribute name="queues" type="xsd:string">
             <xsd:annotation>
                 <xsd:documentation><![CDATA[ The thread pool queue size. ]]></xsd:documentation>
@@ -1277,6 +1287,11 @@
                         <xsd:documentation><![CDATA[ The IO thread pool size. ]]></xsd:documentation>
                     </xsd:annotation>
                 </xsd:attribute>
+                <xsd:attribute name="alive" type="xsd:string">
+                    <xsd:annotation>
+                        <xsd:documentation><![CDATA[ The thread pool keepAliveTime. ]]></xsd:documentation>
+                    </xsd:annotation>
+                </xsd:attribute>
                 <xsd:attribute name="queues" type="xsd:string">
                     <xsd:annotation>
                         <xsd:documentation><![CDATA[ The thread pool queue size. ]]></xsd:documentation>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.bootstrap.DubboBootstrapStartStopListener b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.bootstrap.DubboBootstrapStartStopListener
new file mode 100644
index 0000000..8775af2
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.bootstrap.DubboBootstrapStartStopListener
@@ -0,0 +1 @@
+default=org.apache.dubbo.config.spring.context.DubboBootstrapStartStopListenerSpringAdapter
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockRegistryFactory.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockRegistryFactory.java
index 8d8eb77..66f225c 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockRegistryFactory.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry/MockRegistryFactory.java
@@ -26,20 +26,20 @@ import java.util.Map;
 
 public class MockRegistryFactory implements RegistryFactory {
 
-    private static final Map<URL, Registry> registries = new HashMap<URL, Registry>();
+    private static final Map<URL, Registry> REGISTRIES = new HashMap<URL, Registry>();
 
     public static Collection<Registry> getCachedRegistry() {
-        return registries.values();
+        return REGISTRIES.values();
     }
 
     public static void cleanCachedRegistry() {
-        registries.clear();
+        REGISTRIES.clear();
     }
 
     @Override
     public Registry getRegistry(URL url) {
         MockRegistry registry = new MockRegistry(url);
-        registries.put(url, registry);
+        REGISTRIES.put(url, registry);
         return registry;
     }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
index 2e4ea9c..72bf442 100644
--- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-generic-consumer.xml
@@ -33,4 +33,4 @@
 
     <dubbo:service id="demoService" interface="org.apache.dubbo.config.spring.api.DemoService" generic="true"
                    ref="genericService"/>
-</beans>
\ No newline at end of file
+</beans>
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-consumer-context.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-consumer-context.xml
index 9054c4f..d7948cd 100644
--- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-consumer-context.xml
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-consumer-context.xml
@@ -10,18 +10,18 @@
     <dubbo:registry address="nacos://127.0.0.1:8848"/>
 
     <!-- Reference interface -->
-    <dubbo:reference id="demoService1" interface="org.apache.dubbo.demo.service.DemoService" version="2.0.0"
+    <dubbo:reference id="demoService1" interface="org.apache.dubbo.config.spring.api.DemoService" version="2.0.0"
                      group="default"/>
 
-    <dubbo:reference id="demoService2" interface="org.apache.dubbo.demo.service.DemoService" version="*"
+    <dubbo:reference id="demoService2" interface="org.apache.dubbo.config.spring.api.DemoService" version="*"
                      group="default"/>
 
-    <dubbo:reference id="demoService3" interface="org.apache.dubbo.demo.service.DemoService" version="2.0.0"
+    <dubbo:reference id="demoService3" interface="org.apache.dubbo.config.spring.api.DemoService" version="2.0.0"
                      group="default"/>
 
-    <dubbo:reference id="demoService4" interface="org.apache.dubbo.demo.service.DemoService" version="2.0.0" group="*"/>
+    <dubbo:reference id="demoService4" interface="org.apache.dubbo.config.spring.api.DemoService" version="2.0.0" group="*"/>
 
-    <dubbo:reference id="demoService5" interface="org.apache.dubbo.demo.service.DemoService" version="2.0.0"
+    <dubbo:reference id="demoService5" interface="org.apache.dubbo.config.spring.api.DemoService" version="2.0.0"
                      group="default,test"/>
 
-</beans>
\ No newline at end of file
+</beans>
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-provider-context.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-provider-context.xml
index 207ab7b..846c5ff 100644
--- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-provider-context.xml
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-nacos-provider-context.xml
@@ -12,8 +12,8 @@
     <!-- Use random port as Dubbo -->
     <dubbo:protocol name="dubbo" port="-1"/>
 
-    <dubbo:service interface="org.apache.dubbo.demo.service.DemoService" ref="demoService" version="2.0.0"
+    <dubbo:service interface="org.apache.dubbo.config.spring.api.DemoService" ref="demoService" version="2.0.0"
                    group="default"/>
 
-    <bean id="demoService" class="org.apache.dubbo.demo.service.DefaultService"/>
-</beans>
\ No newline at end of file
+    <bean id="demoService" class="org.apache.dubbo.config.spring.registry.nacos.demo.service.DefaultService"/>
+</beans>
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
index 64626f7..dbf6822 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/main/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfiguration.java
@@ -42,11 +42,11 @@ import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 import java.util.stream.Collectors;
 
-import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
 import static org.apache.dubbo.common.constants.CommonConstants.CHECK_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
+import static org.apache.dubbo.common.constants.CommonConstants.CONFIG_NAMESPACE_KEY;
 
 /**
  * Apollo implementation, https://github.com/ctripcorp/apollo
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java
index ca48bd6..b14f172 100644
--- a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/ApolloDynamicConfigurationTest.java
@@ -20,12 +20,11 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
 import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 
-import com.ctrip.framework.apollo.mockserver.EmbeddedApollo;
 import com.google.common.util.concurrent.SettableFuture;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.RegisterExtension;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -51,13 +50,13 @@ public class ApolloDynamicConfigurationTest {
     /**
      * The constant embeddedApollo.
      */
-    @ClassRule
-    public static EmbeddedApollo embeddedApollo = new EmbeddedApollo();
+    @RegisterExtension
+    public static EmbeddedApolloJunit5 embeddedApollo = new EmbeddedApolloJunit5();
 
     /**
      * Sets up.
      */
-    @Before
+    @BeforeEach
     public void setUp() {
         String apolloUrl = System.getProperty("apollo.configService");
         String urlForDubbo = "apollo://" + apolloUrl.substring(apolloUrl.lastIndexOf("/") + 1) + "/org.apache.dubbo.apollo.testService?namespace=dubbo&check=true";
@@ -183,7 +182,7 @@ public class ApolloDynamicConfigurationTest {
     /**
      * Tear down.
      */
-    @After
+    @AfterEach
     public void tearDown() {
 
     }
diff --git a/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/EmbeddedApolloJunit5.java b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/EmbeddedApolloJunit5.java
new file mode 100644
index 0000000..389d7c9
--- /dev/null
+++ b/dubbo-configcenter/dubbo-configcenter-apollo/src/test/java/org/apache/dubbo/configcenter/support/apollo/EmbeddedApolloJunit5.java
@@ -0,0 +1,193 @@
+/*
+ * 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.configcenter.support.apollo;
+
+import com.ctrip.framework.apollo.build.ApolloInjector;
+import com.ctrip.framework.apollo.core.dto.ApolloConfig;
+import com.ctrip.framework.apollo.core.dto.ApolloConfigNotification;
+import com.ctrip.framework.apollo.core.utils.ResourceUtils;
+import com.ctrip.framework.apollo.internals.ConfigServiceLocator;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import okhttp3.mockwebserver.Dispatcher;
+import okhttp3.mockwebserver.MockResponse;
+import okhttp3.mockwebserver.MockWebServer;
+import okhttp3.mockwebserver.RecordedRequest;
+import org.junit.jupiter.api.extension.AfterAllCallback;
+import org.junit.jupiter.api.extension.BeforeAllCallback;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+public class EmbeddedApolloJunit5 implements BeforeAllCallback, AfterAllCallback {
+    private static final Logger logger = LoggerFactory.getLogger(EmbeddedApolloJunit5.class);
+    private static final Type notificationType = new TypeToken<List<ApolloConfigNotification>>() {
+    }.getType();
+
+    private static Method CONFIG_SERVICE_LOCATOR_CLEAR;
+    private static ConfigServiceLocator CONFIG_SERVICE_LOCATOR;
+
+    private static final Gson GSON = new Gson();
+    private final Map<String, Map<String, String>> addedOrModifiedPropertiesOfNamespace = Maps.newConcurrentMap();
+    private final Map<String, Set<String>> deletedKeysOfNamespace = Maps.newConcurrentMap();
+
+    private MockWebServer server;
+
+    static {
+        try {
+            System.setProperty("apollo.longPollingInitialDelayInMills", "0");
+            CONFIG_SERVICE_LOCATOR = ApolloInjector.getInstance(ConfigServiceLocator.class);
+            CONFIG_SERVICE_LOCATOR_CLEAR = ConfigServiceLocator.class.getDeclaredMethod("initConfigServices");
+            CONFIG_SERVICE_LOCATOR_CLEAR.setAccessible(true);
+        } catch (NoSuchMethodException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void clear() throws Exception {
+        resetOverriddenProperties();
+    }
+
+    private void mockConfigServiceUrl(String url) throws Exception {
+        System.setProperty("apollo.configService", url);
+
+        CONFIG_SERVICE_LOCATOR_CLEAR.invoke(CONFIG_SERVICE_LOCATOR);
+    }
+
+    private String loadConfigFor(String namespace) {
+        String filename = String.format("mockdata-%s.properties", namespace);
+        final Properties prop = ResourceUtils.readConfigFile(filename, new Properties());
+        Map<String, String> configurations = Maps.newHashMap();
+        for (String propertyName : prop.stringPropertyNames()) {
+            configurations.put(propertyName, prop.getProperty(propertyName));
+        }
+        ApolloConfig apolloConfig = new ApolloConfig("someAppId", "someCluster", namespace, "someReleaseKey");
+
+        Map<String, String> mergedConfigurations = mergeOverriddenProperties(namespace, configurations);
+        apolloConfig.setConfigurations(mergedConfigurations);
+        return GSON.toJson(apolloConfig);
+    }
+
+    private String mockLongPollBody(String notificationsStr) {
+        List<ApolloConfigNotification> oldNotifications = GSON.fromJson(notificationsStr, notificationType);
+        List<ApolloConfigNotification> newNotifications = new ArrayList<>();
+        for (ApolloConfigNotification notification : oldNotifications) {
+            newNotifications
+                    .add(new ApolloConfigNotification(notification.getNamespaceName(), notification.getNotificationId() + 1));
+        }
+        return GSON.toJson(newNotifications);
+    }
+
+    /**
+     * Incorporate user modifications to namespace
+     */
+    private Map<String, String> mergeOverriddenProperties(String namespace, Map<String, String> configurations) {
+        if (addedOrModifiedPropertiesOfNamespace.containsKey(namespace)) {
+            configurations.putAll(addedOrModifiedPropertiesOfNamespace.get(namespace));
+        }
+        if (deletedKeysOfNamespace.containsKey(namespace)) {
+            for (String k : deletedKeysOfNamespace.get(namespace)) {
+                configurations.remove(k);
+            }
+        }
+        return configurations;
+    }
+
+    /**
+     * Add new property or update existed property
+     */
+    public void addOrModifyProperty(String namespace, String someKey, String someValue) {
+        if (addedOrModifiedPropertiesOfNamespace.containsKey(namespace)) {
+            addedOrModifiedPropertiesOfNamespace.get(namespace).put(someKey, someValue);
+        } else {
+            Map<String, String> m = Maps.newConcurrentMap();
+            m.put(someKey, someValue);
+            addedOrModifiedPropertiesOfNamespace.put(namespace, m);
+        }
+    }
+
+    /**
+     * Delete existed property
+     */
+    public void deleteProperty(String namespace, String someKey) {
+        if (deletedKeysOfNamespace.containsKey(namespace)) {
+            deletedKeysOfNamespace.get(namespace).add(someKey);
+        } else {
+            Set<String> m = Sets.newConcurrentHashSet();
+            m.add(someKey);
+            deletedKeysOfNamespace.put(namespace, m);
+        }
+    }
+
+    /**
+     * reset overridden properties
+     */
+    public void resetOverriddenProperties() {
+        addedOrModifiedPropertiesOfNamespace.clear();
+        deletedKeysOfNamespace.clear();
+    }
+
+    @Override
+    public void afterAll(ExtensionContext extensionContext) throws Exception {
+        try {
+            clear();
+            server.close();
+        } catch (Exception e) {
+            logger.error("stop apollo server error", e);
+        }
+    }
+
+    @Override
+    public void beforeAll(ExtensionContext extensionContext) throws Exception {
+        clear();
+        server = new MockWebServer();
+        final Dispatcher dispatcher = new Dispatcher() {
+            @Override
+            public MockResponse dispatch(RecordedRequest request) throws InterruptedException {
+                if (request.getPath().startsWith("/notifications/v2")) {
+                    String notifications = request.getRequestUrl().queryParameter("notifications");
+                    return new MockResponse().setResponseCode(200).setBody(mockLongPollBody(notifications));
+                }
+                if (request.getPath().startsWith("/configs")) {
+                    List<String> pathSegments = request.getRequestUrl().pathSegments();
+                    // appId and cluster might be used in the future
+                    String appId = pathSegments.get(1);
+                    String cluster = pathSegments.get(2);
+                    String namespace = pathSegments.get(3);
+                    return new MockResponse().setResponseCode(200).setBody(loadConfigFor(namespace));
+                }
+                return new MockResponse().setResponseCode(404);
+            }
+        };
+
+        server.setDispatcher(dispatcher);
+        server.start();
+
+        mockConfigServiceUrl("http://localhost:" + server.getPort());
+    }
+}
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
index a0acd51..5a10be7 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/CacheListener.java
@@ -80,9 +80,10 @@ public class CacheListener implements DataListener {
         if (!StringUtils.isEmpty(path)) {
             int beginIndex = path.indexOf(rootPath + PATH_SEPARATOR);
             if (beginIndex > -1) {
-                int endIndex = path.indexOf(PATH_SEPARATOR, beginIndex);
-                if (endIndex > beginIndex) {
-                    return path.substring(beginIndex, endIndex);
+                String remain = path.substring((rootPath + PATH_SEPARATOR).length());
+                int endIndex = remain.lastIndexOf(PATH_SEPARATOR);
+                if (endIndex > -1) {
+                    return remain.substring(0, endIndex);
                 }
             }
         }
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
index a4c3511..3ce72c0 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.configcenter.ConfigItem;
 import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
 import org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration;
+import org.apache.dubbo.common.threadpool.support.AbortPolicyWithReport;
 import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
@@ -27,7 +28,8 @@ import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 import java.util.Collection;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.Executor;
-import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -43,6 +45,9 @@ public class ZookeeperDynamicConfiguration extends TreePathDynamicConfiguration
 
     private CacheListener cacheListener;
     private URL url;
+    private static final int DEFAULT_ZK_EXECUTOR_THREADS_NUM = 1;
+    private static final int DEFAULT_QUEUE = 10000;
+    private static final Long THREAD_KEEP_ALIVE_TIME = 0L;
 
 
     ZookeeperDynamicConfiguration(URL url, ZookeeperTransporter zookeeperTransporter) {
@@ -52,7 +57,13 @@ public class ZookeeperDynamicConfiguration extends TreePathDynamicConfiguration
 
         initializedLatch = new CountDownLatch(1);
         this.cacheListener = new CacheListener(rootPath, initializedLatch);
-        this.executor = Executors.newFixedThreadPool(1, new NamedThreadFactory(this.getClass().getSimpleName(), true));
+
+        final String threadName = this.getClass().getSimpleName();
+        this.executor = new ThreadPoolExecutor(DEFAULT_ZK_EXECUTOR_THREADS_NUM, DEFAULT_ZK_EXECUTOR_THREADS_NUM,
+                THREAD_KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
+                new LinkedBlockingQueue<Runnable>(DEFAULT_QUEUE),
+                new NamedThreadFactory(threadName, true),
+                new AbortPolicyWithReport(threadName, url));
 
         zkClient = zookeeperTransporter.connect(url);
         zkClient.addDataListener(rootPath, cacheListener, executor);
diff --git a/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.sh b/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.sh
index 50c3a70..b87ac79 100755
--- a/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.sh
+++ b/dubbo-container/dubbo-container-api/src/main/resources/META-INF/assembly/bin/start.sh
@@ -21,11 +21,11 @@ cd ..
 DEPLOY_DIR=`pwd`
 CONF_DIR=$DEPLOY_DIR/conf
 
-SERVER_NAME=`sed '/dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
-SERVER_PROTOCOL=`sed '/dubbo.protocol.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
-SERVER_HOST=`sed '/dubbo.protocol.host/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
-SERVER_PORT=`sed '/dubbo.protocol.port/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
-LOGS_FILE=`sed '/dubbo.log4j.file/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
+SERVER_NAME=`sed '/^dubbo.application.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
+SERVER_PROTOCOL=`sed '/^dubbo.protocol.name/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
+SERVER_HOST=`sed '/^dubbo.protocol.host/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
+SERVER_PORT=`sed '/^dubbo.protocol.port/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
+LOGS_FILE=`sed '/^dubbo.log4j.file/!d;s/.*=//' conf/dubbo.properties | tr -d '\r'`
 VM_ARGS_PERM_SIZE='PermSize'
 VM_ARGS_METASPACE_SIZE='MetaspaceSize'
 JAVA_8_VERSION="180"
diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml
index fffa2bd..3bf2035 100644
--- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml
+++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml
@@ -79,5 +79,9 @@
             <groupId>org.apache.dubbo</groupId>
             <artifactId>dubbo-serialization-hessian2</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-serialization-jdk</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml
index c8cf138..eda0979 100644
--- a/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml
+++ b/dubbo-demo/dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml
@@ -88,7 +88,7 @@
         </dependency>
         <dependency>
             <groupId>org.apache.dubbo</groupId>
-            <artifactId>dubbo-qos</artifactId>
+            <artifactId>dubbo-serialization-jdk</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 60d1491..5cf588e 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -90,7 +90,7 @@
     <properties>
         <!-- Common libs -->
         <spring_version>5.2.8.RELEASE</spring_version>
-        <javassist_version>3.20.0-GA</javassist_version>
+        <javassist_version>3.23.1-GA</javassist_version>
         <eclipse_collections_version>10.4.0</eclipse_collections_version>
         <netty_version>3.2.5.Final</netty_version>
         <netty4_version>4.1.56.Final</netty4_version>
@@ -102,7 +102,7 @@
         <zookeeper_version>3.4.13</zookeeper_version>
         <curator_version>4.0.1</curator_version>
         <curator_test_version>2.12.0</curator_test_version>
-        <jedis_version>2.9.0</jedis_version>
+        <jedis_version>3.6.0</jedis_version>
         <consul_version>1.4.2</consul_version>
         <consul_process_version>2.0.0</consul_process_version>
         <consul_client_version>1.3.7</consul_client_version>
@@ -155,7 +155,7 @@
 
         <jaxb_version>2.2.7</jaxb_version>
         <activation_version>1.2.0</activation_version>
-        <test_container_version>1.11.2</test_container_version>
+        <test_container_version>1.15.3</test_container_version>
         <etcd_launcher_version>0.5.3</etcd_launcher_version>
         <hessian_lite_version>3.2.8</hessian_lite_version>
         <swagger_version>1.5.19</swagger_version>
diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
index 02d0e29..3122a8e 100644
--- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
+++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/filter/CacheFilter.java
@@ -37,7 +37,7 @@ import static org.apache.dubbo.common.constants.FilterConstants.CACHE_KEY;
 /**
  * CacheFilter is a core component of dubbo.Enabling <b>cache</b> key of service,method,consumer or provider dubbo will cache method return value.
  * Along with cache key we need to configure cache type. Dubbo default implemented cache types are
- * <li>lur</li>
+ * <li>lru</li>
  * <li>threadlocal</li>
  * <li>jcache</li>
  * <li>expiring</li>
diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java
index 966d923..17530af 100644
--- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java
+++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/AbstractCacheFactory.java
@@ -44,9 +44,12 @@ public abstract class AbstractCacheFactory implements CacheFactory {
      */
     private final ConcurrentMap<String, Cache> caches = new ConcurrentHashMap<String, Cache>();
 
+    private final Object MONITOR = new Object();
+
     /**
-     *  Takes URL and invocation instance and return cache instance for a given url.
-     * @param url url of the method
+     * Takes URL and invocation instance and return cache instance for a given url.
+     *
+     * @param url        url of the method
      * @param invocation invocation context.
      * @return Instance of cache store used as storage for caching return values.
      */
@@ -55,15 +58,29 @@ public abstract class AbstractCacheFactory implements CacheFactory {
         url = url.addParameter(METHOD_KEY, invocation.getMethodName());
         String key = url.toFullString();
         Cache cache = caches.get(key);
-        if (cache == null) {
-            caches.put(key, createCache(url));
+
+        // get from cache first.
+        if (null != cache) {
+            return cache;
+        }
+
+        synchronized (MONITOR) {
+            // double check.
             cache = caches.get(key);
+            if (null != cache) {
+                return cache;
+            }
+
+            cache = createCache(url);
+            caches.put(key, cache);
         }
+
         return cache;
     }
 
     /**
      * Takes url as an method argument and return new instance of cache store implemented by AbstractCacheFactory subclass.
+     *
      * @param url url of the method
      * @return Create and return new instance of cache store used as storage for caching return values.
      */
diff --git a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringMap.java b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringMap.java
index 895f114..b5306e2 100644
--- a/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringMap.java
+++ b/dubbo-filter/dubbo-filter-cache/src/main/java/org/apache/dubbo/cache/support/expiring/ExpiringMap.java
@@ -84,6 +84,12 @@ public class ExpiringMap<K, V> implements Map<K, V> {
     public V get(Object key) {
         ExpiryObject object = delegateMap.get(key);
         if (object != null) {
+            long timeIdle = System.currentTimeMillis() - object.getLastAccessTime();
+            int timeToLive = expireThread.getTimeToLive();
+            if (timeToLive > 0 && timeIdle >= timeToLive * 1000) {
+                delegateMap.remove(object.getKey());
+                return null;
+            }
             object.setLastAccessTime(System.currentTimeMillis());
             return object.getValue();
         }
@@ -137,6 +143,9 @@ public class ExpiringMap<K, V> implements Map<K, V> {
 
     @Override
     public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
         return delegateMap.equals(obj);
     }
 
@@ -226,6 +235,9 @@ public class ExpiringMap<K, V> implements Map<K, V> {
 
         @Override
         public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
             return value.equals(obj);
         }
 
@@ -282,10 +294,10 @@ public class ExpiringMap<K, V> implements Map<K, V> {
 
         private void processExpires() {
             long timeNow = System.currentTimeMillis();
+            if (timeToLiveMillis <= 0) {
+                return;
+            }
             for (ExpiryObject o : delegateMap.values()) {
-                if (timeToLiveMillis <= 0) {
-                    continue;
-                }
                 long timeIdle = timeNow - o.getLastAccessTime();
                 if (timeIdle >= timeToLiveMillis) {
                     delegateMap.remove(o.getKey());
@@ -307,7 +319,7 @@ public class ExpiringMap<K, V> implements Map<K, V> {
          * start thread
          */
         public void startExpiryIfNotStarted() {
-            if (running) {
+            if (running && timeToLiveMillis <= 0) {
                 return;
             }
             startExpiring();
diff --git a/dubbo-filter/dubbo-filter-cache/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory b/dubbo-filter/dubbo-filter-cache/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory
index 1ea180a..aa72c92 100644
--- a/dubbo-filter/dubbo-filter-cache/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory
+++ b/dubbo-filter/dubbo-filter-cache/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory
@@ -1,4 +1,5 @@
 threadlocal=org.apache.dubbo.cache.support.threadlocal.ThreadLocalCacheFactory
 lru=org.apache.dubbo.cache.support.lru.LruCacheFactory
 jcache=org.apache.dubbo.cache.support.jcache.JCacheFactory
-expiring=org.apache.dubbo.cache.support.expiring.ExpiringCacheFactory
\ No newline at end of file
+expiring=org.apache.dubbo.cache.support.expiring.ExpiringCacheFactory
+lfu=org.apache.dubbo.cache.support.lfu.LfuCacheFactory
diff --git a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java
index 23484c6..d793460 100644
--- a/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java
+++ b/dubbo-filter/dubbo-filter-cache/src/test/java/org/apache/dubbo/cache/support/expiring/ExpiringCacheFactoryTest.java
@@ -19,18 +19,90 @@ package org.apache.dubbo.cache.support.expiring;
 import org.apache.dubbo.cache.Cache;
 import org.apache.dubbo.cache.support.AbstractCacheFactory;
 import org.apache.dubbo.cache.support.AbstractCacheFactoryTest;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.RpcInvocation;
+
 import org.junit.jupiter.api.Test;
 
-import static org.hamcrest.core.Is.is;
+import java.util.concurrent.TimeUnit;
+
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
 
 public class ExpiringCacheFactoryTest extends AbstractCacheFactoryTest {
+
+    private static final String EXPIRING_CACHE_URL =
+            "test://test:12/test?cache=expiring&cache.seconds=1&cache.interval=1";
+
     @Test
-    public void testLruCacheFactory() throws Exception {
+    public void testExpiringCacheFactory() throws Exception {
         Cache cache = super.constructCache();
         assertThat(cache instanceof ExpiringCache, is(true));
     }
 
+    @Test
+    public void testExpiringCacheGetExpired() throws Exception {
+        URL url = URL.valueOf("test://test:12/test?cache=expiring&cache.seconds=1&cache.interval=1");
+        AbstractCacheFactory cacheFactory = getCacheFactory();
+        Invocation invocation = new RpcInvocation();
+        Cache cache = cacheFactory.getCache(url, invocation);
+        cache.put("testKey", "testValue");
+        Thread.sleep(2100);
+        assertNull(cache.get("testKey"));
+    }
+
+    @Test
+    public void testExpiringCacheUnExpired() throws Exception {
+        URL url = URL.valueOf("test://test:12/test?cache=expiring&cache.seconds=0&cache.interval=1");
+        AbstractCacheFactory cacheFactory = getCacheFactory();
+        Invocation invocation = new RpcInvocation();
+        Cache cache = cacheFactory.getCache(url, invocation);
+        cache.put("testKey", "testValue");
+        Thread.sleep(1100);
+        assertNotNull(cache.get("testKey"));
+    }
+
+    @Test
+    public void testExpiringCache() throws Exception {
+        Cache cache = constructCache();
+        assertThat(cache instanceof ExpiringCache, is(true));
+
+        // 500ms
+        TimeUnit.MILLISECONDS.sleep(500);
+        cache.put("testKey", "testValue");
+        // 800ms
+        TimeUnit.MILLISECONDS.sleep(300);
+        assertNotNull(cache.get("testKey"));
+        // 1300ms
+        TimeUnit.MILLISECONDS.sleep(500);
+        assertNotNull(cache.get("testKey"));
+    }
+
+    @Test
+    public void testExpiringCacheExpired() throws Exception {
+        Cache cache = constructCache();
+        assertThat(cache instanceof ExpiringCache, is(true));
+
+        // 500ms
+        TimeUnit.MILLISECONDS.sleep(500);
+        cache.put("testKey", "testValue");
+        // 1000ms ExpireThread clear all expire cache
+        TimeUnit.MILLISECONDS.sleep(500);
+        // 1700ms  get should be null
+        TimeUnit.MILLISECONDS.sleep(700);
+        assertNull(cache.get("testKey"));
+    }
+
+    @Override
+    protected Cache constructCache() {
+        URL url = URL.valueOf(EXPIRING_CACHE_URL);
+        Invocation invocation = new RpcInvocation();
+        return getCacheFactory().getCache(url, invocation);
+    }
+
     @Override
     protected AbstractCacheFactory getCacheFactory() {
         return new ExpiringCacheFactory();
diff --git a/dubbo-metadata/dubbo-metadata-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml
index fe6a20c..9caf31e 100644
--- a/dubbo-metadata/dubbo-metadata-api/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-api/pom.xml
@@ -78,6 +78,13 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- Spring Web MVC -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-context</artifactId>
+            <scope>test</scope>
+        </dependency>
+
     </dependencies>
 
 </project>
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
index f524fcf..44b8000 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
@@ -69,7 +69,7 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
             dynamicConfiguration.publishConfig(key, ServiceNameMapping.buildGroup(serviceInterface, group, version, protocol), content);
             if (logger.isDebugEnabled()) {
                 logger.info(String.format("Dubbo service[%s] mapped to interface name[%s].",
-                        group, serviceInterface, group));
+                        group, serviceInterface));
             }
         });
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
index cda2e58..cac87d2 100755
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.metadata.definition.builder;
 
 import org.apache.dubbo.metadata.definition.TypeDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.TypeDefinition;
-import org.apache.dubbo.metadata.definition.util.ClassUtils;
 
 import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
@@ -26,7 +25,6 @@ import java.text.MessageFormat;
 import java.util.Arrays;
 import java.util.Map;
 
-import static org.apache.dubbo.common.utils.StringUtils.replace;
 import static org.apache.dubbo.common.utils.TypeUtils.getRawClass;
 import static org.apache.dubbo.common.utils.TypeUtils.isClass;
 import static org.apache.dubbo.common.utils.TypeUtils.isParameterizedType;
@@ -60,14 +58,7 @@ public class MapTypeBuilder implements TypeBuilder {
                             + Arrays.toString(actualTypeArgs), type, actualTypeArgs));
         }
 
-        // Change since 2.7.6
-        /**
-         * Replacing <code>", "</code> to <code>","</code> will not change the semantic of
-         * {@link ParameterizedType#toString()}
-         * @see sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
-         */
-        String mapType = ClassUtils.getCanonicalNameForParameterizedType(parameterizedType);
-        mapType = replace(mapType, ", ", ",");
+        String mapType = type.toString();
 
         TypeDefinition td = typeCache.get(mapType);
         if (td != null) {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
index ac09e96..e355859 100755
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
@@ -22,6 +22,9 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Objects;
 
+import static org.apache.dubbo.metadata.definition.model.TypeDefinition.formatType;
+import static org.apache.dubbo.metadata.definition.model.TypeDefinition.formatTypes;
+
 /**
  * 2015/1/27.
  */
@@ -66,11 +69,11 @@ public class MethodDefinition implements Serializable {
     }
 
     public void setParameterTypes(String[] parameterTypes) {
-        this.parameterTypes = parameterTypes;
+        this.parameterTypes = formatTypes(parameterTypes);
     }
 
     public void setReturnType(String returnType) {
-        this.returnType = returnType;
+        this.returnType = formatType(returnType);
     }
 
     @Override
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
index 816bd09..6dd0f06 100755
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
@@ -26,6 +26,8 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 
+import static org.apache.dubbo.common.utils.StringUtils.replace;
+
 /**
  * 2015/1/27.
  */
@@ -65,7 +67,52 @@ public class TypeDefinition implements Serializable {
     }
 
     public TypeDefinition(String type) {
-        this.type = type;
+        this.setType(type);
+    }
+
+    /**
+     * Format the {@link String} array presenting Java types
+     *
+     * @param types the strings presenting Java types
+     * @return new String array of Java types after be formatted
+     * @since 2.7.9
+     */
+    public static String[] formatTypes(String[] types) {
+        String[] newTypes = new String[types.length];
+        for (int i = 0; i < types.length; i++) {
+            newTypes[i] = formatType(types[i]);
+        }
+        return newTypes;
+    }
+
+    /**
+     * Format the {@link String} presenting Java type
+     *
+     * @param type the String presenting type
+     * @return new String presenting Java type after be formatted
+     * @since 2.7.9
+     */
+    public static String formatType(String type) {
+        if (isGenericType(type)) {
+            return formatGenericType(type);
+        }
+        return type;
+    }
+
+    /**
+     * Replacing <code>", "</code> to <code>","</code> will not change the semantic of
+     * {@link ParameterizedType#toString()}
+     *
+     * @param type
+     * @return formatted type
+     * @see sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl
+     */
+    private static String formatGenericType(String type) {
+        return replace(type, ", ", ",");
+    }
+
+    private static boolean isGenericType(String type) {
+        return type.contains("<") && type.contains(">");
     }
 
     public List<String> getEnums() {
@@ -106,7 +153,7 @@ public class TypeDefinition implements Serializable {
     }
 
     public void setType(String type) {
-        this.type = type;
+        this.type = formatType(type);
     }
 
     @Override
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
index a0e360f..4cdbb3b 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReportInstance.java
@@ -20,11 +20,13 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_DIRECTORY;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
 import static org.apache.dubbo.metadata.report.support.Constants.METADATA_REPORT_KEY;
@@ -51,6 +53,7 @@ public class MetadataReportInstance {
                     .removeParameter(METADATA_REPORT_KEY)
                     .build();
         }
+        url = url.addParameterIfAbsent(APPLICATION_KEY, ApplicationModel.getApplicationConfig().getName());
         String relatedRegistryId = config.getRegistry() == null ? DEFAULT_KEY : config.getRegistry();
 //        RegistryConfig registryConfig = ApplicationModel.getConfigManager().getRegistry(relatedRegistryId)
 //                .orElseThrow(() -> new IllegalStateException("Registry id " + relatedRegistryId + " does not exist."));
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
index 454b250..07b26f0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReportFactory.java
@@ -39,10 +39,16 @@ public abstract class AbstractMetadataReportFactory implements MetadataReportFac
         url = url.setPath(MetadataReport.class.getName())
                 .removeParameters(EXPORT_KEY, REFER_KEY);
         String key = url.toServiceString();
+
+        MetadataReport metadataReport = SERVICE_STORE_MAP.get(key);
+        if (metadataReport != null) {
+            return metadataReport;
+        }
+
         // Lock the metadata access process to ensure a single instance of the metadata instance
         LOCK.lock();
         try {
-            MetadataReport metadataReport = SERVICE_STORE_MAP.get(key);
+            metadataReport = SERVICE_STORE_MAP.get(key);
             if (metadataReport != null) {
                 return metadataReport;
             }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java
index ea07421..eb48bda 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java
@@ -18,6 +18,7 @@ package org.apache.dubbo.metadata.rest;
 
 import org.apache.dubbo.common.utils.MethodComparator;
 import org.apache.dubbo.common.utils.ServiceAnnotationResolver;
+import org.apache.dubbo.config.annotation.DubboService;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.metadata.definition.MethodDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.MethodDefinition;
@@ -70,7 +71,8 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest
     }
 
     protected final boolean isServiceAnnotationPresent(Class<?> serviceType) {
-        return isAnyAnnotationPresent(serviceType, Service.class, com.alibaba.dubbo.config.annotation.Service.class);
+        return isAnyAnnotationPresent(serviceType, DubboService.class, Service.class,
+                com.alibaba.dubbo.config.annotation.Service.class);
     }
 
     /**
@@ -296,7 +298,7 @@ public abstract class AbstractServiceRestMetadataResolver implements ServiceRest
         for (int i = 0; i < paramCount; i++) {
             Parameter parameter = parameters[i];
             // Add indexed parameter name
-            metadata.addIndexToName(i,parameter.getName());
+            metadata.addIndexToName(i, parameter.getName());
             processAnnotatedMethodParameter(parameter, i, serviceMethod, serviceType, serviceInterfaceClass, metadata);
         }
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMetadataConstants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMetadataConstants.java
index 82e6328..6c758bf 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMetadataConstants.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMetadataConstants.java
@@ -16,6 +16,11 @@
  */
 package org.apache.dubbo.metadata.rest;
 
+import java.lang.annotation.Annotation;
+
+import static org.apache.dubbo.common.utils.ClassUtils.getClassLoader;
+import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
+
 /**
  * The REST Metadata Constants definition interface
  *
@@ -108,5 +113,33 @@ public interface RestMetadataConstants {
          * The annotation class name of @RequestParam
          */
         String REQUEST_PARAM_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestParam";
+
+        /**
+         * The class of @Controller
+         *
+         * @since 2.7.9
+         */
+        Class<? extends Annotation> CONTROLLER_ANNOTATION_CLASS = (Class<? extends Annotation>) resolveClass(CONTROLLER_ANNOTATION_CLASS_NAME, getClassLoader());
+
+        /**
+         * The class of @RequestMapping
+         *
+         * @since 2.7.9
+         */
+        Class<? extends Annotation> REQUEST_MAPPING_ANNOTATION_CLASS = (Class<? extends Annotation>) resolveClass(REQUEST_MAPPING_ANNOTATION_CLASS_NAME, getClassLoader());
+
+        /**
+         * The annotation class name of AnnotatedElementUtils
+         *
+         * @since 2.7.9
+         */
+        String ANNOTATED_ELEMENT_UTILS_CLASS_NAME = "org.springframework.core.annotation.AnnotatedElementUtils";
+
+        /**
+         * The class of AnnotatedElementUtils
+         *
+         * @since 2.7.9
+         */
+        Class<?> ANNOTATED_ELEMENT_UTILS_CLASS = resolveClass(ANNOTATED_ELEMENT_UTILS_CLASS_NAME, getClassLoader());
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
index a675eb3..1531c97 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
@@ -159,8 +159,12 @@ public class RestMethodMetadata implements Serializable {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof RestMethodMetadata)) return false;
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof RestMethodMetadata)) {
+            return false;
+        }
         RestMethodMetadata that = (RestMethodMetadata) o;
         return Objects.equals(getMethod(), that.getMethod()) &&
                 Objects.equals(getRequest(), that.getRequest()) &&
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
index 876b8a3..df396b0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
@@ -76,8 +76,12 @@ public class ServiceRestMetadata implements Serializable {
 
     @Override
     public boolean equals(Object o) {
-        if (this == o) return true;
-        if (!(o instanceof ServiceRestMetadata)) return false;
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof ServiceRestMetadata)) {
+            return false;
+        }
         ServiceRestMetadata that = (ServiceRestMetadata) o;
         return Objects.equals(getServiceInterface(), that.getServiceInterface()) &&
                 Objects.equals(getVersion(), that.getVersion()) &&
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
index 28407c2..74807ea 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
@@ -16,11 +16,13 @@
  */
 package org.apache.dubbo.metadata.rest.springmvc;
 
+import org.apache.dubbo.common.utils.AnnotationUtils;
 import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
 import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Parameter;
+import java.util.Objects;
 
 import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
 
@@ -49,11 +51,18 @@ public abstract class AbstractRequestAnnotationParameterProcessor extends Abstra
 
     @Override
     protected String getDefaultValue(Annotation annotation, Parameter parameter, int parameterIndex) {
-        String defaultValue = getAttribute(annotation, "defaultValue");
-        if (isEmpty(defaultValue)) {
-            defaultValue = super.getDefaultValue(annotation, parameter, parameterIndex);
+        String attributeName = "defaultValue";
+        String attributeValue = getAttribute(annotation, attributeName);
+
+        if (isEmpty(attributeValue) || isDefaultValue(annotation, attributeName, attributeValue)) {
+            attributeValue = super.getDefaultValue(annotation, parameter, parameterIndex);
         }
-        return defaultValue;
+        return attributeValue;
+    }
+
+    private boolean isDefaultValue(Annotation annotation, String attributeName, Object attributeValue) {
+        String defaultValue = AnnotationUtils.getDefaultValue(annotation, attributeName);
+        return Objects.equals(attributeValue, defaultValue);
     }
 
     protected boolean isEmpty(String str) {
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java
index e24422a..de64592 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java
@@ -29,14 +29,15 @@ import static java.lang.String.valueOf;
 import static java.lang.reflect.Array.getLength;
 import static java.util.stream.Stream.of;
 import static org.apache.dubbo.common.utils.AnnotationUtils.findAnnotation;
-import static org.apache.dubbo.common.utils.AnnotationUtils.findMetaAnnotation;
 import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
 import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
 import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
 import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
+import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
 import static org.apache.dubbo.common.utils.PathUtils.buildPath;
-import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.CONTROLLER_ANNOTATION_CLASS_NAME;
-import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_MAPPING_ANNOTATION_CLASS_NAME;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.ANNOTATED_ELEMENT_UTILS_CLASS;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.CONTROLLER_ANNOTATION_CLASS;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_MAPPING_ANNOTATION_CLASS;
 
 /**
  * {@link ServiceRestMetadataResolver}
@@ -49,23 +50,17 @@ public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMet
 
     @Override
     protected boolean supports0(Class<?> serviceType) {
-        return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
+        return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS);
     }
 
     @Override
     protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
-        return isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+        return isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS) ||
+                isAnnotationPresent(serviceMethod, REQUEST_MAPPING_ANNOTATION_CLASS);
     }
 
     @Override
     protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
-        String requestBasePath = resolveRequestPath(serviceType);
-        String requestRelativePath = resolveRequestPath(serviceMethod);
-        return buildPath(requestBasePath, requestRelativePath);
-    }
-
-    @Override
-    protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
         Annotation requestMapping = getRequestMapping(serviceMethod);
 
         // httpMethod is an array of RequestMethod
@@ -80,6 +75,13 @@ public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMet
     }
 
     @Override
+    protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        String requestBasePath = resolveRequestPath(serviceType);
+        String requestRelativePath = resolveRequestPath(serviceMethod);
+        return buildPath(requestBasePath, requestRelativePath);
+    }
+
+    @Override
     protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> produces) {
         addMediaTypes(serviceMethod, "produces", produces);
     }
@@ -91,6 +93,7 @@ public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMet
 
     private String resolveRequestPath(AnnotatedElement annotatedElement) {
         Annotation mappingAnnotation = getRequestMapping(annotatedElement);
+
         // try "value" first
         String[] value = getAttribute(mappingAnnotation, "value");
 
@@ -118,10 +121,20 @@ public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMet
 
     private Annotation getRequestMapping(AnnotatedElement annotatedElement) {
         // try "@RequestMapping" first
-        Annotation requestMapping = findAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
-        // try the annotation meta-annotated later
+        Annotation requestMapping = findAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS);
         if (requestMapping == null) {
-            requestMapping = findMetaAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+            // To try the meta-annotated annotation if can't be found.
+            // For example, if the annotation "@GetMapping" is used in the Spring Framework is 4.2 or above,
+            // because of "@GetMapping" alias for ("@AliasFor") "@RequestMapping" , both of them belongs to
+            // the artifact "spring-web" which depends on "spring-core", thus Spring core's
+            // AnnotatedElementUtils.findMergedAnnotation(AnnotatedElement, Class) must be involved.
+            Method method = findMethod(ANNOTATED_ELEMENT_UTILS_CLASS, "findMergedAnnotation", AnnotatedElement.class, Class.class);
+            if (method != null) {
+                try {
+                    requestMapping = (Annotation) method.invoke(null, annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS);
+                } catch (Exception ignored) {
+                }
+            }
         }
         return requestMapping;
     }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/SpringRestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/SpringRestService.java
index ead5186..f967ad7 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/SpringRestService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/SpringRestService.java
@@ -16,7 +16,7 @@
  */
 package org.apache.dubbo.metadata.rest;
 
-import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.config.annotation.DubboService;
 
 import org.springframework.http.MediaType;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -35,7 +35,7 @@ import java.util.Map;
  *
  * @since 2.7.6
  */
-@Service(version = "2.0.0")
+@DubboService(version = "2.0.0", group = "spring")
 @RestController
 public class SpringRestService implements RestService {
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/StandardRestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/StandardRestService.java
index f5d94b7..684d76f 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/StandardRestService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/StandardRestService.java
@@ -16,7 +16,7 @@
  */
 package org.apache.dubbo.metadata.rest;
 
-import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.config.annotation.DubboService;
 
 import javax.ws.rs.Consumes;
 import javax.ws.rs.FormParam;
@@ -34,7 +34,7 @@ import java.util.Map;
 /**
  * JAX-RS {@link RestService}
  */
-@Service(version = "3.0.0", protocol = {"dubbo", "rest"}, group = "standard")
+@DubboService(version = "3.0.0", protocol = {"dubbo", "rest"}, group = "standard")
 @Path("/")
 public class StandardRestService implements RestService {
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolverTest.java
similarity index 96%
copy from dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
copy to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolverTest.java
index d959007..53c5428 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolverTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.rest.resolver.jaxrs;
+package org.apache.dubbo.metadata.rest.jaxrs;
 
 import org.apache.dubbo.metadata.rest.ClassPathServiceRestMetadataReader;
 import org.apache.dubbo.metadata.rest.DefaultRestService;
@@ -23,7 +23,6 @@ import org.apache.dubbo.metadata.rest.RestService;
 import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
 import org.apache.dubbo.metadata.rest.SpringRestService;
 import org.apache.dubbo.metadata.rest.StandardRestService;
-import org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver;
 
 import org.junit.jupiter.api.Test;
 
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java
similarity index 82%
rename from dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java
index d959007..43abc8f 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolverTest.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.metadata.rest.resolver.jaxrs;
+package org.apache.dubbo.metadata.rest.springmvc;
 
 import org.apache.dubbo.metadata.rest.ClassPathServiceRestMetadataReader;
 import org.apache.dubbo.metadata.rest.DefaultRestService;
@@ -23,7 +23,6 @@ import org.apache.dubbo.metadata.rest.RestService;
 import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
 import org.apache.dubbo.metadata.rest.SpringRestService;
 import org.apache.dubbo.metadata.rest.StandardRestService;
-import org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver;
 
 import org.junit.jupiter.api.Test;
 
@@ -35,20 +34,20 @@ import static org.junit.jupiter.api.Assertions.assertFalse;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
 /**
- * {@link JAXRSServiceRestMetadataResolver} Test
+ * {@link SpringMvcServiceRestMetadataResolver} Test
  *
- * @since 2.7.6
+ * @since 2.7.9
  */
-public class JAXRSServiceRestMetadataResolverTest {
+public class SpringMvcServiceRestMetadataResolverTest {
 
-    private JAXRSServiceRestMetadataResolver instance = new JAXRSServiceRestMetadataResolver();
+    private SpringMvcServiceRestMetadataResolver instance = new SpringMvcServiceRestMetadataResolver();
 
     @Test
     public void testSupports() {
-        // JAX-RS RestService class
-        assertTrue(instance.supports(StandardRestService.class));
         // Spring MVC RestService class
-        assertFalse(instance.supports(SpringRestService.class));
+        assertTrue(instance.supports(SpringRestService.class));
+        // JAX-RS RestService class
+        assertFalse(instance.supports(StandardRestService.class));
         // Default RestService class
         assertFalse(instance.supports(DefaultRestService.class));
         // No annotated RestService class
@@ -60,11 +59,11 @@ public class JAXRSServiceRestMetadataResolverTest {
     @Test
     public void testResolve() {
         // Generated by "dubbo-metadata-processor"
-        ClassPathServiceRestMetadataReader reader = new ClassPathServiceRestMetadataReader("META-INF/dubbo/jax-rs-service-rest-metadata.json");
+        ClassPathServiceRestMetadataReader reader = new ClassPathServiceRestMetadataReader("META-INF/dubbo/spring-mvc-servoce-rest-metadata.json");
         List<ServiceRestMetadata> serviceRestMetadataList = reader.read();
 
         ServiceRestMetadata expectedServiceRestMetadata = serviceRestMetadataList.get(0);
-        ServiceRestMetadata serviceRestMetadata = instance.resolve(StandardRestService.class);
+        ServiceRestMetadata serviceRestMetadata = instance.resolve(SpringRestService.class);
 
 
         List<RestMethodMetadata> meta1 = new LinkedList<>(expectedServiceRestMetadata.getMeta());
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/spring-mvc-servoce-rest-metadata.json b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/spring-mvc-servoce-rest-metadata.json
new file mode 100644
index 0000000..c0f25f5
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/spring-mvc-servoce-rest-metadata.json
@@ -0,0 +1,321 @@
+[
+  {
+    "serviceInterface": "org.apache.dubbo.metadata.rest.RestService",
+    "version": "2.0.0",
+    "group": "spring",
+    "meta": [
+      {
+        "method": {
+          "name": "form",
+          "parameterTypes": [
+            "java.lang.String"
+          ],
+          "returnType": "java.lang.String",
+          "parameters": [
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "POST",
+          "path": "/form",
+          "params": {
+            "f": [
+              "{0}"
+            ]
+          },
+          "headers": {},
+          "consumes": [],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "form"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "headers",
+          "parameterTypes": [
+            "java.lang.String",
+            "java.lang.String",
+            "java.lang.Integer"
+          ],
+          "returnType": "java.lang.String",
+          "parameters": [
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.Integer",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "GET",
+          "path": "/headers",
+          "params": {
+            "v": [
+              "1"
+            ]
+          },
+          "headers": {
+            "h": [
+              "value-h"
+            ],
+            "h2": [
+              "value-h2"
+            ]
+          },
+          "consumes": [],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "header"
+          ],
+          "1": [
+            "header2"
+          ],
+          "2": [
+            "param"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "param",
+          "parameterTypes": [
+            "java.lang.String"
+          ],
+          "returnType": "java.lang.String",
+          "parameters": [
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "GET",
+          "path": "/param",
+          "params": {
+            "param": [
+              "value-param"
+            ]
+          },
+          "headers": {},
+          "consumes": [],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "param"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "params",
+          "parameterTypes": [
+            "int",
+            "java.lang.String"
+          ],
+          "returnType": "java.lang.String",
+          "parameters": [
+            {
+              "type": "int",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "POST",
+          "path": "/params",
+          "params": {
+            "a": [
+              "value-a"
+            ],
+            "b": [
+              "value-b"
+            ]
+          },
+          "headers": {},
+          "consumes": [],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "a"
+          ],
+          "1": [
+            "b"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "pathVariables",
+          "parameterTypes": [
+            "java.lang.String",
+            "java.lang.String",
+            "java.lang.String"
+          ],
+          "returnType": "java.lang.String",
+          "parameters": [
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
... 5873 lines suppressed ...