You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by me...@apache.org on 2020/02/17 12:16:27 UTC

[dubbo] branch master updated: 2.7.6 REST Metadata (#5738)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 7b0ae12  2.7.6 REST Metadata (#5738)
7b0ae12 is described below

commit 7b0ae127a96eb508af5c2b980b20041efff01d56
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Mon Feb 17 20:15:43 2020 +0800

    2.7.6 REST Metadata (#5738)
    
    * Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring
    
    * Polish /apache/dubbo#4674 & /apache/dubbo#4470
    
    * Polish /apache/dubbo#5093 : Revert the previous commit
    
    * Polish apache/dubbo#5093 : [Feature] Dubbo Services generate the metadata of REST services
    
    * Polish apache/dubbo#5306 : [Migration] Upgrade the @since tags in Javadoc migration cloud native to master
    
    * Polish apache/dubbo#5306 : [Migration] Upgrade the @since tags in Javadoc migration cloud native to master
    
    * Polish apache/dubbo#5309 : [ISSURE] The beans of Dubbo's Config can't be found on the ReferenceBean's initialization
    
    * Polish apache/dubbo#5312 : Resolve the demos' issues of zookeeper and nacos
    
    * Polish apache/dubbo#5313 : [Migration] migrate the code in common module from cloud-native branch to master
    
    * Polish apache/dubbo#5316 : [Refactor] Replace @EnableDubboConfigBinding Using spring-context-support
    
    * Polish apache/dubbo#5317 : [Refactor] Refactor ReferenceAnnotationBeanPostProcessor using Alibaba spring-context-suuport API
    
    * Polish apache/dubbo#5321 : Remove BeanFactoryUtils
    
    * Polish apache/dubbo#5321 : Remove AnnotatedBeanDefinitionRegistryUtils
    
    * Polish apache/dubbo#5321 : Remove AnnotationUtils
    
    * Polish apache/dubbo#5321 : Remove ClassUtils
    
    * Polish apache/dubbo#5321 : Remove BeanRegistrar
    
    * Polish apache/dubbo#5321 : Remove ObjectUtils
    
    * Polish apache/dubbo#5321 : Remove PropertySourcesUtils
    
    * Polish apache/dubbo#5325 : [Migration] To migrate dubbo-metadata-api from cloud-native branch
    
    * Polish apache/dubbo#5326 : [Migration] To migrate dubbo-metadata-processor from cloud-native branch
    
    * Polish apache/dubbo#5329 : [Feature] To add the default metadata into ServiceInstance
    
    * Polish apache/dubbo#5339 : [Refactor] Refactor the DynamicConfiguration interface
    
    * Polish bugfix
    
    * Fixes test cases
    
    * Merge remote-tracking branch 'upstream/master' into cloud-native-2.7.5
    
    # Conflicts:
    #	dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
    #	dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
    
    * Merge remote-tracking branch 'upstream/master' into cloud-native-2.7.5
    
    # Conflicts:
    #	dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
    #	dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMappingTest.java
    
    * Polish /apache/dubbo#5721 : [Enhancement] Setting the default IDs for Dubbo's Config Beans
    
    * Polish /apache/dubbo#5729 : [Optimization] To remove EnableDubboConfigBinding and EnableDubboConfigBindings
    
    * Polish /apache/dubbo#5594 : [Feature] Add the resolver of ServiceRestMetadata based on Java Reflection
    
    * Polish /apache/dubbo#5736 : [Feature] Introducing Conversion features
    
    * Polish /apache/dubbo#5737 : [Feature] Introducing "dubbo-metadata-processor" module
    
    * Polish /apache/dubbo#5594 : Change the Metadata implementation
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
    
    * Polish /apache/dubbo#5594 : Fixed test cases
---
 dubbo-all/pom.xml                                  | 191 ++++++---
 .../org/apache/dubbo/common/convert/Converter.java |  91 ++++
 .../dubbo/common/convert/StringConverter.java      |  27 ++
 .../common/convert/StringToBooleanConverter.java   |  38 ++
 .../common/convert/StringToCharArrayConverter.java |  39 ++
 .../common/convert/StringToCharacterConverter.java |  44 ++
 .../common/convert/StringToDoubleConverter.java    |  39 ++
 .../common/convert/StringToFloatConverter.java     |  38 ++
 .../common/convert/StringToIntegerConverter.java   |  38 ++
 .../common/convert/StringToLongConverter.java      |  39 ++
 .../common/convert/StringToOptionalConverter.java  |  40 ++
 .../common/convert/StringToShortConverter.java     |  39 ++
 .../common/convert/StringToStringConverter.java    |  30 ++
 .../convert/multiple/MultiValueConverter.java      |  64 +++
 .../convert/multiple/StringToArrayConverter.java   |  60 +++
 .../multiple/StringToBlockingDequeConverter.java   |  33 ++
 .../multiple/StringToBlockingQueueConverter.java   |  34 ++
 .../multiple/StringToCollectionConverter.java      |  33 ++
 .../convert/multiple/StringToDequeConverter.java   |  33 ++
 .../multiple/StringToIterableConverter.java        |  80 ++++
 .../convert/multiple/StringToListConverter.java    |  33 ++
 .../multiple/StringToMultiValueConverter.java      |  61 +++
 .../multiple/StringToNavigableSetConverter.java    |  34 ++
 .../convert/multiple/StringToQueueConverter.java   |  34 ++
 .../convert/multiple/StringToSetConverter.java     |  33 ++
 .../multiple/StringToSortedSetConverter.java       |  33 ++
 .../multiple/StringToTransferQueueConverter.java   |  33 ++
 .../dubbo/common/extension/ExtensionLoader.java    |  11 +-
 .../apache/dubbo/common/utils/AnnotationUtils.java | 452 ++++++++++++++++++++
 .../dubbo/common/utils/CharSequenceComparator.java |  37 ++
 .../org/apache/dubbo/common/utils/ClassUtils.java  | 226 +++++++++-
 .../apache/dubbo/common/utils/CollectionUtils.java | 109 ++++-
 .../org/apache/dubbo/common/utils/HttpUtils.java   | 264 ++++++++++++
 .../org/apache/dubbo/common/utils/MemberUtils.java |  62 +++
 .../dubbo/common/utils/MethodComparator.java       |  71 ++++
 .../org/apache/dubbo/common/utils/MethodUtils.java | 292 ++++++++++++-
 .../apache/dubbo/common/utils/ReflectUtils.java    |  34 ++
 .../common/utils/ServiceAnnotationResolver.java    | 119 ++++++
 .../org/apache/dubbo/common/utils/TypeUtils.java   | 224 ++++++++++
 .../org.apache.dubbo.common.convert.Converter      |  11 +
 ...bbo.common.convert.multiple.MultiValueConverter |  12 +
 .../dubbo/common/utils/AnnotationUtilsTest.java    | 343 +++++++++++++++
 .../apache/dubbo/common/utils/MemberUtilsTest.java |  42 ++
 .../convert/StringToBooleanConverterTest.java      |  58 +++
 .../convert/StringToCharArrayConverterTest.java    |  54 +++
 .../convert/StringToCharacterConverterTest.java    |  58 +++
 .../dubbo/convert/StringToDoubleConverterTest.java |  58 +++
 .../dubbo/convert/StringToFloatConverterTest.java  |  58 +++
 .../convert/StringToIntegerConverterTest.java      |  58 +++
 .../dubbo/convert/StringToLongConverterTest.java   |  58 +++
 .../convert/StringToOptionalConverterTest.java     |  55 +++
 .../dubbo/convert/StringToShortConverterTest.java  |  58 +++
 .../dubbo/convert/StringToStringConverterTest.java |  54 +++
 .../multiple/StringToArrayConverterTest.java       |  70 +++
 .../StringToBlockingDequeConverterTest.java        | 122 ++++++
 .../StringToBlockingQueueConverterTest.java        | 125 ++++++
 .../multiple/StringToCollectionConverterTest.java  | 119 ++++++
 .../multiple/StringToDequeConverterTest.java       | 120 ++++++
 .../multiple/StringToListConverterTest.java        | 119 ++++++
 .../StringToNavigableSetConverterTest.java         | 119 ++++++
 .../multiple/StringToQueueConverterTest.java       | 119 ++++++
 .../convert/multiple/StringToSetConverterTest.java | 118 ++++++
 .../multiple/StringToSortedSetConverterTest.java   | 119 ++++++
 .../StringToTransferQueueConverterTest.java        | 122 ++++++
 .../apache/dubbo/generic/GenericServiceTest.java   |   3 +-
 .../apache/dubbo/config/spring/ServiceBean.java    |   3 +-
 dubbo-metadata/dubbo-metadata-api/pom.xml          |  14 +
 .../definition/MethodDefinitionBuilder.java        |  78 ++++
 .../metadata/definition/TypeDefinitionBuilder.java |   4 +-
 .../definition/builder/MapTypeBuilder.java         |  37 +-
 .../AbstractAnnotatedMethodParameterProcessor.java |  51 +++
 .../rest/AbstractServiceRestMetadataResolver.java  | 341 +++++++++++++++
 .../rest/AnnotatedMethodParameterProcessor.java    |  66 +++
 .../rest/ClassPathServiceRestMetadataReader.java   |  82 ++++
 .../rest/DefaultServiceRestMetadataResolver.java   |  59 +++
 .../dubbo/metadata/rest/RequestMetadata.java       | 226 ++++++++++
 .../dubbo/metadata/rest/RestMetadataConstants.java | 112 +++++
 .../dubbo/metadata/rest/RestMethodMetadata.java    | 195 +++++++++
 .../dubbo/metadata/rest/ServiceRestMetadata.java   | 103 +++++
 .../metadata/rest/ServiceRestMetadataReader.java   |  39 ++
 .../metadata/rest/ServiceRestMetadataResolver.java |  43 ++
 .../rest/jaxrs/DefaultValueParameterProcessor.java |  74 ++++
 .../rest/jaxrs/FormParamParameterProcessor.java    |  34 ++
 .../rest/jaxrs/HeaderParamParameterProcessor.java  |  49 +++
 .../jaxrs/JAXRSServiceRestMetadataResolver.java    |  99 +++++
 .../rest/jaxrs/MatrixParamParameterProcessor.java  |  34 ++
 .../jaxrs/ParamAnnotationParameterProcessor.java   |  38 ++
 .../rest/jaxrs/QueryParamParameterProcessor.java   |  34 ++
 ...bstractRequestAnnotationParameterProcessor.java |  62 +++
 .../springmvc/RequestHeaderParameterProcessor.java |  43 ++
 .../springmvc/RequestParamParameterProcessor.java  |  43 ++
 .../SpringMvcServiceRestMetadataResolver.java      | 128 ++++++
 ...metadata.rest.AnnotatedMethodParameterProcessor |  10 +
 ...dubbo.metadata.rest.ServiceRestMetadataResolver |   3 +
 ...Test.java => ServiceDefinitionBuilderTest.java} |   4 +-
 .../dubbo/metadata/rest/DefaultRestService.java    |  69 +++
 .../apache/dubbo/metadata/rest/RestService.java    |  42 ++
 .../dubbo/metadata/rest/SpringRestService.java     |  97 +++++
 .../dubbo/metadata/rest/StandardRestService.java   | 107 +++++
 .../java/org/apache/dubbo/metadata/rest/User.java  |  61 +++
 .../JAXRSServiceRestMetadataResolverTest.java      |  82 ++++
 .../dubbo/jax-rs-service-rest-metadata.json        | 349 +++++++++++++++
 .../protobuf/ProtobufTypeBuilderTest.java          |   4 +-
 dubbo-metadata/dubbo-metadata-processor/pom.xml    | 177 ++++++++
 .../AbstractServiceAnnotationProcessor.java        | 108 +++++
 .../processing/ClassPathMetadataStorage.java       | 105 +++++
 ...rviceDefinitionMetadataAnnotationProcessor.java |  60 +++
 .../builder/ArrayTypeDefinitionBuilder.java        |  50 +++
 .../builder/CollectionTypeDefinitionBuilder.java   |  61 +++
 .../builder/DeclaredTypeDefinitionBuilder.java     |  49 +++
 .../builder/EnumTypeDefinitionBuilder.java         |  55 +++
 .../builder/GeneralTypeDefinitionBuilder.java      |  65 +++
 .../builder/MapTypeDefinitionBuilder.java          |  62 +++
 .../builder/MethodDefinitionBuilder.java           |  53 +++
 .../builder/PrimitiveTypeDefinitionBuilder.java    |  48 +++
 .../builder/ServiceDefinitionBuilder.java          |  56 +++
 .../builder/SimpleTypeDefinitionBuilder.java       |  49 +++
 .../processing/builder/TypeDefinitionBuilder.java  |  96 +++++
 .../AbstractAnnotatedMethodParameterProcessor.java |  52 +++
 .../rest/AbstractServiceRestMetadataResolver.java  | 291 +++++++++++++
 .../rest/AnnotatedMethodParameterProcessor.java    |  64 +++
 .../rest/DefaultServiceRestMetadataResolver.java   | 186 ++++++++
 .../ServiceRestMetadataAnnotationProcessor.java    |  86 ++++
 .../rest/ServiceRestMetadataResolver.java          |  55 +++
 .../rest/ServiceRestMetadataStorage.java           |  65 +++
 .../rest/jaxrs/DefaultValueParameterProcessor.java |  75 ++++
 .../rest/jaxrs/FormParamParameterProcessor.java    |  34 ++
 .../rest/jaxrs/HeaderParamParameterProcessor.java  |  51 +++
 .../jaxrs/JAXRSServiceRestMetadataResolver.java    | 108 +++++
 .../rest/jaxrs/MatrixParamParameterProcessor.java  |  34 ++
 .../jaxrs/ParamAnnotationParameterProcessor.java   |  38 ++
 .../rest/jaxrs/QueryParamParameterProcessor.java   |  34 ++
 ...bstractRequestAnnotationParameterProcessor.java |  69 +++
 .../springmvc/RequestHeaderParameterProcessor.java |  43 ++
 .../springmvc/RequestParamParameterProcessor.java  |  44 ++
 .../SpringMvcServiceRestMetadataResolver.java      | 165 ++++++++
 .../processing/util/AnnotationUtils.java           | 233 ++++++++++
 .../util/ExecutableElementComparator.java          |  72 ++++
 .../annotation/processing/util/FieldUtils.java     | 146 +++++++
 .../annotation/processing/util/LoggerUtils.java    |  45 ++
 .../annotation/processing/util/MemberUtils.java    |  94 +++++
 .../annotation/processing/util/MethodUtils.java    | 156 +++++++
 .../processing/util/ServiceAnnotationUtils.java    | 121 ++++++
 .../annotation/processing/util/TypeUtils.java      | 400 ++++++++++++++++++
 ...tation.processing.builder.TypeDefinitionBuilder |   7 +
 ...ocessing.rest.AnnotatedMethodParameterProcessor |  10 +
 ...ion.processing.rest.ServiceRestMetadataResolver |   3 +
 .../services/javax.annotation.processing.Processor |   2 +
 .../AbstractAnnotationProcessingTest.java          |  69 +++
 .../builder/ArrayTypeDefinitionBuilderTest.java    | 121 ++++++
 .../CollectionTypeDefinitionBuilderTest.java       | 105 +++++
 .../builder/EnumTypeDefinitionBuilderTest.java     |  67 +++
 .../builder/GeneralTypeDefinitionBuilderTest.java  |  67 +++
 .../builder/MapTypeDefinitionBuilderTest.java      | 134 ++++++
 .../PrimitiveTypeDefinitionBuilderTest.java        | 130 ++++++
 .../builder/ServiceDefinitionBuilderTest.java      |  64 +++
 .../builder/SimpleTypeDefinitionBuilderTest.java   | 146 +++++++
 .../processing/model/ArrayTypeModel.java           |  36 ++
 .../processing/model/CollectionTypeModel.java      |  42 ++
 .../annotation/processing/model/Color.java         |  46 ++
 .../annotation/processing/model/MapTypeModel.java  |  41 ++
 .../annotation/processing/model/Model.java         |  89 ++++
 .../processing/model/PrimitiveTypeModel.java       |  73 ++++
 .../processing/model/SimpleTypeModel.java          | 161 +++++++
 .../AnnotatedMethodParameterProcessorTest.java     |  59 +++
 .../processing/util/AnnotationUtilsTest.java       | 231 ++++++++++
 .../annotation/processing/util/FieldUtilsTest.java | 259 ++++++++++++
 .../processing/util/LoggerUtilsTest.java           |  50 +++
 .../processing/util/MemberUtilsTest.java           | 113 +++++
 .../processing/util/MethodUtilsTest.java           | 195 +++++++++
 .../util/ServiceAnnotationUtilsTest.java           | 136 ++++++
 .../annotation/processing/util/TypeUtilsTest.java  | 468 +++++++++++++++++++++
 .../dubbo/metadata/rest/DefaultRestService.java    |  69 +++
 .../apache/dubbo/metadata/rest/RestService.java    |  42 ++
 .../dubbo/metadata/rest/SpringRestService.java     |  97 +++++
 .../dubbo/metadata/rest/StandardRestService.java   | 107 +++++
 .../java/org/apache/dubbo/metadata/rest/User.java  |  61 +++
 .../org/apache/dubbo/metadata/tools/Ancestor.java  |  35 ++
 .../org/apache/dubbo/metadata/tools/Compiler.java  | 116 +++++
 .../apache/dubbo/metadata/tools/CompilerTest.java  |  37 ++
 .../metadata/tools/DefaultRestServiceTest.java     |  45 ++
 .../dubbo/metadata/tools/DefaultTestService.java   |  63 +++
 .../dubbo/metadata/tools/GenericTestService.java   |  38 ++
 .../org/apache/dubbo/metadata/tools/Parent.java    |  63 +++
 .../dubbo/metadata/tools/RestServiceTest.java      |  42 ++
 .../metadata/tools/SpringRestServiceTest.java      |  39 ++
 .../metadata/tools/StandardRestServiceTest.java    |  39 ++
 .../apache/dubbo/metadata/tools/TestProcessor.java |  46 ++
 .../apache/dubbo/metadata/tools/TestService.java   |  54 +++
 .../dubbo/metadata/tools/TestServiceImpl.java      |  51 +++
 dubbo-metadata/pom.xml                             |   1 +
 pom.xml                                            |   5 +-
 192 files changed, 16107 insertions(+), 85 deletions(-)

diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index 6904795..325083e 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -14,7 +14,8 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.dubbo</groupId>
@@ -685,172 +686,218 @@
                             </artifactSet>
                             <transformers>
                                 <!-- dubbo-common beginning -->
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.compiler.Compiler
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.extension.ExtensionFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.infra.InfraAdapter
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.logger.LoggerAdapter
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.status.StatusChecker
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.store.DataStore
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.common.threadpool.ThreadPool
                                     </resource>
                                 </transformer>
                                 <!-- dubbo-common end -->
 
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.common.serialize.Serialization
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Dispatcher</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Codec2</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.Transporter</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.exchange.Exchanger
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.http.HttpBinder
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.p2p.Networker
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.remoting.telnet.TelnetHandler
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.Protocol</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.Filter</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.InvokerListener</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.ExporterListener</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.ProxyFactory</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Cluster</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.LoadBalance
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.Merger</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.RouterFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>
                                         META-INF/dubbo/internal/org.apache.dubbo.rpc.cluster.ConfiguratorFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.container.Container</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.monitor.MonitorFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.RegistryFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.validation.Validation</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.cache.CacheFactory</resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.qos.command.BaseCommand
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.report.MetadataReportFactory
                                     </resource>
                                 </transformer>
                                 <!-- @since 2.7.5 -->
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.event.EventDispatcher
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.WritableMetadataService
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.ServiceNameMapping
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.registry.client.metadata.proxy.MetadataServiceProxyFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                     <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscovery
                                     </resource>
                                 </transformer>
-                                <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
-                                    <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
                                     </resource>
                                 </transformer>
                                 <transformer
@@ -871,6 +918,56 @@
                                     </resource>
                                 </transformer>
 
+                                <!-- @since 2.7.6 -->
+
+                                <!-- 'dubbo-common' module -->
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.common.convert.Converter
+                                    </resource>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.common.convert.multiple.MultiValueConverter
+                                    </resource>
+                                </transformer>
+
+                                <!-- 'dubbo-metadata-api' module -->
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor
+                                    </resource>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver
+                                    </resource>
+                                </transformer>
+
+                                <!-- 'dubbo-metadata-processor' module -->
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
+                                    </resource>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
+                                    </resource>
+                                </transformer>
+                                <transformer
+                                        implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                                    <resource>
+                                        META-INF/dubbo/internal/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataResolver
+                                    </resource>
+                                </transformer>
+
                             </transformers>
                             <filters>
                                 <filter>
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
new file mode 100644
index 0000000..5bc2d4d
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
@@ -0,0 +1,91 @@
+/*
+ * 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.convert;
+
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
+import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
+
+/**
+ * A class to convert the source-typed value to the target-typed value
+ *
+ * @param <S> The source type
+ * @param <T> The target type
+ * @since 2.7.6
+ */
+@SPI
+@FunctionalInterface
+public interface Converter<S, T> extends Prioritized {
+
+    /**
+     * Accept the source type and target type or not
+     *
+     * @param sourceType the source type
+     * @param targetType the target type
+     * @return if accepted, return <code>true</code>, or <code>false</code>
+     */
+    default boolean accept(Class<?> sourceType, Class<?> targetType) {
+        return isAssignableFrom(sourceType, getSourceType()) && isAssignableFrom(targetType, getTargetType());
+    }
+
+    /**
+     * Convert the source-typed value to the target-typed value
+     *
+     * @param source the source-typed value
+     * @return the target-typed value
+     */
+    T convert(S source);
+
+    /**
+     * Get the source type
+     *
+     * @return non-null
+     */
+    default Class<S> getSourceType() {
+        return findActualTypeArgument(getClass(), Converter.class, 0);
+    }
+
+    /**
+     * Get the target type
+     *
+     * @return non-null
+     */
+    default Class<T> getTargetType() {
+        return findActualTypeArgument(getClass(), Converter.class, 1);
+    }
+
+    /**
+     * Get the Converter instance from {@link ExtensionLoader} with the specified source and target type
+     *
+     * @param sourceType the source type
+     * @param targetType the target type
+     * @return
+     * @see ExtensionLoader#getSupportedExtensionInstances()
+     */
+    static Converter<?, ?> getConverter(Class<?> sourceType, Class<?> targetType) {
+        return getExtensionLoader(Converter.class)
+                .getSupportedExtensionInstances()
+                .stream()
+                .filter(converter -> converter.accept(sourceType, targetType))
+                .findFirst()
+                .orElse(null);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
new file mode 100644
index 0000000..9232fed
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+/**
+ * A class to covert {@link String} to the target-typed value
+ *
+ * @see Converter
+ * @since 2.7.6
+ */
+@FunctionalInterface
+public interface StringConverter<T> extends Converter<String, T> {
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToBooleanConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToBooleanConverter.java
new file mode 100644
index 0000000..98655c7
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToBooleanConverter.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import static java.lang.Boolean.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Boolean}
+ *
+ * @since 2.7.6
+ */
+public class StringToBooleanConverter implements StringConverter<Boolean> {
+
+    @Override
+    public Boolean convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 5;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharArrayConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharArrayConverter.java
new file mode 100644
index 0000000..3e40bf1
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharArrayConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.convert;
+
+
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to <code>char[]</code>
+ *
+ * @since 2.7.6
+ */
+public class StringToCharArrayConverter implements StringConverter<char[]> {
+
+    @Override
+    public char[] convert(String source) {
+        return isNotEmpty(source) ? source.toCharArray() : null;
+    }
+
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 7;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharacterConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharacterConverter.java
new file mode 100644
index 0000000..580986f
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToCharacterConverter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import static org.apache.dubbo.common.utils.StringUtils.length;
+
+/**
+ * The class to convert {@link String} to {@link Character}
+ *
+ * @since 2.7.6
+ */
+public class StringToCharacterConverter implements StringConverter<Character> {
+
+    @Override
+    public Character convert(String source) {
+        int length = length(source);
+        if (length == 0) {
+            return null;
+        }
+        if (length > 1) {
+            throw new IllegalArgumentException("The source String is more than one character!");
+        }
+        return source.charAt(0);
+    }
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 8;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToDoubleConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToDoubleConverter.java
new file mode 100644
index 0000000..148b2f8
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToDoubleConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.convert;
+
+import static java.lang.Double.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Double}
+ *
+ * @since 2.7.6
+ */
+public class StringToDoubleConverter implements StringConverter<Double> {
+
+    @Override
+    public Double convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 3;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToFloatConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToFloatConverter.java
new file mode 100644
index 0000000..a3b3b166
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToFloatConverter.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import static java.lang.Float.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Float}
+ *
+ * @since 2.7.6
+ */
+public class StringToFloatConverter implements StringConverter<Float> {
+
+    @Override
+    public Float convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 4;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToIntegerConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToIntegerConverter.java
new file mode 100644
index 0000000..211f66d
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToIntegerConverter.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import static java.lang.Integer.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Integer}
+ *
+ * @since 2.7.6
+ */
+public class StringToIntegerConverter implements StringConverter<Integer> {
+
+    @Override
+    public Integer convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToLongConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToLongConverter.java
new file mode 100644
index 0000000..f9ebdcd
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToLongConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.convert;
+
+import static java.lang.Long.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Long}
+ *
+ * @since 2.7.6
+ */
+public class StringToLongConverter implements StringConverter<Long> {
+
+    @Override
+    public Long convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 1;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToOptionalConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToOptionalConverter.java
new file mode 100644
index 0000000..a26fa04
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToOptionalConverter.java
@@ -0,0 +1,40 @@
+/*
+ * 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.convert;
+
+import java.util.Optional;
+
+import static java.util.Optional.ofNullable;
+
+/**
+ * The class to convert {@link String} to {@link Optional}
+ *
+ * @since 2.7.6
+ */
+public class StringToOptionalConverter implements StringConverter<Optional> {
+
+    @Override
+    public Optional convert(String source) {
+        return ofNullable(source);
+    }
+
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToShortConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToShortConverter.java
new file mode 100644
index 0000000..6427b17
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToShortConverter.java
@@ -0,0 +1,39 @@
+/*
+ * 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.convert;
+
+import static java.lang.Short.valueOf;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+
+/**
+ * The class to convert {@link String} to {@link Short}
+ *
+ * @since 2.7.6
+ */
+public class StringToShortConverter implements StringConverter<Short> {
+
+    @Override
+    public Short convert(String source) {
+        return isNotEmpty(source) ? valueOf(source) : null;
+    }
+
+
+    @Override
+    public int getPriority() {
+        return NORMAL_PRIORITY + 2;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToStringConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToStringConverter.java
new file mode 100644
index 0000000..d97d523
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringToStringConverter.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+/**
+ * A class to covert {@link String} to {@link String} value, just no-op
+ *
+ * @since 2.7.6
+ */
+public class StringToStringConverter implements StringConverter<String> {
+
+    @Override
+    public String convert(String source) {
+        return source;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java
new file mode 100644
index 0000000..298b459
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java
@@ -0,0 +1,64 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
+
+import java.util.Collection;
+
+import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
+
+/**
+ * An interface to convert the source-typed value to multiple value, e.g , Java array, {@link Collection} or
+ * sub-interfaces
+ *
+ * @param <S> The source type
+ * @since 2.7.6
+ */
+@SPI
+public interface MultiValueConverter<S> extends Prioritized {
+
+    /**
+     * Accept the source type and target type or not
+     *
+     * @param sourceType     the source type
+     * @param multiValueType the multi-value type
+     * @return if accepted, return <code>true</code>, or <code>false</code>
+     */
+    boolean accept(Class<S> sourceType, Class<?> multiValueType);
+
+    /**
+     * Convert the source to be the multiple value
+     *
+     * @param source         the source-typed value
+     * @param multiValueType the multi-value type
+     * @param elementType    the element type
+     * @return
+     */
+    Object convert(S source, Class<?> multiValueType, Class<?> elementType);
+
+    /**
+     * Get the source type
+     *
+     * @return non-null
+     */
+    default Class<S> getSourceType() {
+        return findActualTypeArgument(getClass(), MultiValueConverter.class, 0);
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverter.java
new file mode 100644
index 0000000..32490cd
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.Converter;
+
+import java.lang.reflect.Array;
+
+import static java.lang.reflect.Array.newInstance;
+
+/**
+ * The class to convert {@link String} to array-type object
+ *
+ * @since 2.7.6
+ */
+public class StringToArrayConverter implements StringToMultiValueConverter {
+
+    public boolean accept(Class<String> type, Class<?> multiValueType) {
+        if (multiValueType != null && multiValueType.isArray()) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Object convert(String[] segments, int size, Class<?> targetType, Class<?> elementType) {
+
+        Class<?> componentType = targetType.getComponentType();
+
+        Converter converter = Converter.getConverter(String.class, componentType);
+
+        Object array = newInstance(componentType, size);
+
+        for (int i = 0; i < size; i++) {
+            Array.set(array, i, converter.convert(segments[i]));
+        }
+
+        return array;
+    }
+
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverter.java
new file mode 100644
index 0000000..61e0a7d
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.LinkedBlockingDeque;
+
+/**
+ * The class to convert {@link String} to {@link BlockingDeque}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToBlockingDequeConverter extends StringToIterableConverter<BlockingDeque> {
+
+    @Override
+    protected BlockingDeque createMultiValue(int size, Class<?> multiValueType) {
+        return new LinkedBlockingDeque(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverter.java
new file mode 100644
index 0000000..f099e84
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+
+/**
+ * The class to convert {@link String} to {@link BlockingDeque}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToBlockingQueueConverter extends StringToIterableConverter<BlockingQueue> {
+
+    @Override
+    protected BlockingQueue createMultiValue(int size, Class<?> multiValueType) {
+        return new ArrayBlockingQueue(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverter.java
new file mode 100644
index 0000000..478447e
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * The class to convert {@link String} to {@link Collection}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToCollectionConverter extends StringToIterableConverter<Collection> {
+
+    @Override
+    protected Collection createMultiValue(int size, Class<?> multiValueType) {
+        return new ArrayList(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverter.java
new file mode 100644
index 0000000..19bdc33
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+
+/**
+ * The class to convert {@link String} to {@link Deque}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToDequeConverter extends StringToIterableConverter<Deque> {
+
+    @Override
+    protected Deque createMultiValue(int size, Class<?> multiValueType) {
+        return new ArrayDeque(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToIterableConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToIterableConverter.java
new file mode 100644
index 0000000..f84b360
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToIterableConverter.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import org.apache.dubbo.common.convert.StringConverter;
+
+import java.util.Collection;
+import java.util.Optional;
+
+import static org.apache.dubbo.common.convert.Converter.getConverter;
+import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
+import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
+import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
+
+/**
+ * The class to convert {@link String} to {@link Iterable}-based value
+ *
+ * @since 2.7.6
+ */
+public abstract class StringToIterableConverter<T extends Iterable> implements StringToMultiValueConverter {
+
+    public boolean accept(Class<String> type, Class<?> multiValueType) {
+        return isAssignableFrom(getSupportedType(), multiValueType);
+    }
+
+    @Override
+    public final Object convert(String[] segments, int size, Class<?> multiValueType, Class<?> elementType) {
+
+        Optional<StringConverter> stringConverter = getStringConverter(elementType);
+
+        return stringConverter.map(converter -> {
+
+            T convertedObject = createMultiValue(size, multiValueType);
+
+            if (convertedObject instanceof Collection) {
+                Collection collection = (Collection) convertedObject;
+                for (int i = 0; i < size; i++) {
+                    String segment = segments[i];
+                    Object element = converter.convert(segment);
+                    collection.add(element);
+                }
+                return collection;
+            }
+
+            return convertedObject;
+        }).orElse(null);
+    }
+
+    protected abstract T createMultiValue(int size, Class<?> multiValueType);
+
+    protected Optional<StringConverter> getStringConverter(Class<?> elementType) {
+        StringConverter converter = (StringConverter) getConverter(String.class, elementType);
+        return Optional.ofNullable(converter);
+    }
+
+    protected final Class<T> getSupportedType() {
+        return findActualTypeArgument(getClass(), StringToIterableConverter.class, 0);
+    }
+
+    @Override
+    public final int getPriority() {
+        int level = getAllInterfaces(getSupportedType(), type ->
+                isAssignableFrom(Iterable.class, type)).size();
+        return MIN_PRIORITY - level;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToListConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToListConverter.java
new file mode 100644
index 0000000..111a3a7
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToListConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * The class to convert {@link String} to {@link List}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToListConverter extends StringToIterableConverter<List> {
+
+    @Override
+    protected List createMultiValue(int size, Class<?> multiValueType) {
+        return new ArrayList(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToMultiValueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToMultiValueConverter.java
new file mode 100644
index 0000000..75fefe6
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToMultiValueConverter.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import org.apache.dubbo.common.utils.ArrayUtils;
+
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+import static org.apache.dubbo.common.utils.StringUtils.split;
+
+/**
+ * The class to convert {@link String} to multiple value object
+ *
+ * @see MultiValueConverter
+ * @since 2.7.6
+ */
+public interface StringToMultiValueConverter extends MultiValueConverter<String> {
+
+    @Override
+    default Object convert(String source, Class<?> multiValueType, Class<?> elementType) {
+
+        if (isEmpty(source)) {
+            return null;
+        }
+
+        // split by the comma
+        String[] segments = split(source, ',');
+
+        if (ArrayUtils.isEmpty(segments)) { // If empty array, create an array with only one element
+            segments = new String[]{source};
+        }
+
+        int size = segments.length;
+
+        return convert(segments, size, multiValueType, elementType);
+    }
+
+    /**
+     * Convert the segments to multiple value object
+     *
+     * @param segments    the String array of content
+     * @param size        the size of multiple value object
+     * @param targetType  the target type
+     * @param elementType the element type
+     * @return multiple value object
+     */
+    Object convert(String[] segments, int size, Class<?> targetType, Class<?> elementType);
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverter.java
new file mode 100644
index 0000000..ccd692e
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import java.util.NavigableSet;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * The class to convert {@link String} to {@link SortedSet}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToNavigableSetConverter extends StringToIterableConverter<NavigableSet> {
+
+    @Override
+    protected NavigableSet createMultiValue(int size, Class<?> multiValueType) {
+        return new TreeSet();
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverter.java
new file mode 100644
index 0000000..3bd7eed
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverter.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.Queue;
+
+/**
+ * The class to convert {@link String} to {@link Deque}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToQueueConverter extends StringToIterableConverter<Queue> {
+
+    @Override
+    protected Queue createMultiValue(int size, Class<?> multiValueType) {
+        return new ArrayDeque(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSetConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSetConverter.java
new file mode 100644
index 0000000..dfffead
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSetConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * The class to convert {@link String} to {@link Set}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToSetConverter extends StringToIterableConverter<Set> {
+
+    @Override
+    protected Set createMultiValue(int size, Class<?> multiValueType) {
+        return new HashSet(size);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverter.java
new file mode 100644
index 0000000..12b48d6
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+/**
+ * The class to convert {@link String} to {@link SortedSet}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToSortedSetConverter extends StringToIterableConverter<SortedSet> {
+
+    @Override
+    protected SortedSet createMultiValue(int size, Class<?> multiValueType) {
+        return new TreeSet();
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverter.java
new file mode 100644
index 0000000..32ca09f
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverter.java
@@ -0,0 +1,33 @@
+/*
+ * 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.convert.multiple;
+
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.TransferQueue;
+
+/**
+ * The class to convert {@link String} to {@link TransferQueue}-based value
+ *
+ * @since 2.7.6
+ */
+public class StringToTransferQueueConverter extends StringToIterableConverter<TransferQueue> {
+
+    @Override
+    protected TransferQueue createMultiValue(int size, Class<?> multiValueType) {
+        return new LinkedTransferQueue();
+    }
+}
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 595b9d0..842a43f 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
@@ -19,6 +19,7 @@ package org.apache.dubbo.common.extension;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.context.Lifecycle;
 import org.apache.dubbo.common.extension.support.ActivateComparator;
+import org.apache.dubbo.common.lang.Prioritized;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ArrayUtils;
@@ -40,7 +41,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -49,6 +51,7 @@ import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.regex.Pattern;
 
+import static java.util.Collections.sort;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX;
@@ -442,14 +445,16 @@ public class ExtensionLoader<T> {
     }
 
     public Set<T> getSupportedExtensionInstances() {
-        Set<T> instances = new HashSet<>();
+        List<T> instances = new LinkedList<>();
         Set<String> supportedExtensions = getSupportedExtensions();
         if (CollectionUtils.isNotEmpty(supportedExtensions)) {
             for (String name : supportedExtensions) {
                 instances.add(getExtension(name));
             }
         }
-        return instances;
+        // sort the Prioritized instances
+        sort(instances, Prioritized.COMPARATOR);
+        return new LinkedHashSet<>(instances);
     }
 
     /**
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
new file mode 100644
index 0000000..600c8aa
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/AnnotationUtils.java
@@ -0,0 +1,452 @@
+/*
+ * 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.utils;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+import java.lang.reflect.AnnotatedElement;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static org.apache.dubbo.common.function.Predicates.and;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+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.invokeMethod;
+
+/**
+ * Commons Annotation Utilities class
+ *
+ * @since 2.7.6
+ */
+public interface AnnotationUtils {
+
+    /**
+     * Resolve the annotation type by the annotated element and resolved class name
+     *
+     * @param annotatedElement    the annotated element
+     * @param annotationClassName the class name of annotation
+     * @param <A>                 the type of annotation
+     * @return If resolved, return the type of annotation, or <code>null</code>
+     */
+    static <A extends Annotation> Class<A> resolveAnnotationType(AnnotatedElement annotatedElement,
+                                                                 String annotationClassName) {
+        ClassLoader classLoader = annotatedElement.getClass().getClassLoader();
+        Class<?> annotationType = resolveClass(annotationClassName, classLoader);
+        if (annotationType == null || !Annotation.class.isAssignableFrom(annotationType)) {
+            return null;
+        }
+        return (Class<A>) annotationType;
+    }
+
+    /**
+     * Is the specified type a generic {@link Class type}
+     *
+     * @param annotatedElement the annotated element
+     * @return if <code>annotatedElement</code> is the {@link Class}, return <code>true</code>, or <code>false</code>
+     * @see ElementType#TYPE
+     */
+    static boolean isType(AnnotatedElement annotatedElement) {
+        return annotatedElement instanceof Class;
+    }
+
+    /**
+     * Is the type of specified annotation same to the expected type?
+     *
+     * @param annotation     the specified {@link Annotation}
+     * @param annotationType the expected annotation type
+     * @return if same, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isSameType(Annotation annotation, Class<? extends Annotation> annotationType) {
+        if (annotation == null || annotationType == null) {
+            return false;
+        }
+        return Objects.equals(annotation.annotationType(), annotationType);
+    }
+
+    /**
+     * Build an instance of {@link Predicate} to excluded annotation type
+     *
+     * @param excludedAnnotationType excluded annotation type
+     * @return non-null
+     */
+    static Predicate<Annotation> excludedType(Class<? extends Annotation> excludedAnnotationType) {
+        return annotation -> !isSameType(annotation, excludedAnnotationType);
+    }
+
+    /**
+     * Get the attribute from the specified {@link Annotation annotation}
+     *
+     * @param annotation    the specified {@link Annotation annotation}
+     * @param attributeName the attribute name
+     * @param <T>           the type of attribute
+     * @return the attribute value
+     * @throws IllegalArgumentException If the attribute name can't be found
+     */
+    static <T> T getAttribute(Annotation annotation, String attributeName) throws IllegalArgumentException {
+        return annotation == null ? null : invokeMethod(annotation, attributeName);
+    }
+
+    /**
+     * Get the "value" attribute from the specified {@link Annotation annotation}
+     *
+     * @param annotation the specified {@link Annotation annotation}
+     * @param <T>        the type of attribute
+     * @return the value of "value" attribute
+     * @throws IllegalArgumentException If the attribute name can't be found
+     */
+    static <T> T getValue(Annotation annotation) throws IllegalArgumentException {
+        return getAttribute(annotation, "value");
+    }
+
+    /**
+     * Get the {@link Annotation} from the specified {@link AnnotatedElement the annotated element} and
+     * {@link Annotation annotation} class name
+     *
+     * @param annotatedElement    {@link AnnotatedElement}
+     * @param annotationClassName the class name of annotation
+     * @param <A>                 The type of {@link Annotation}
+     * @return the {@link Annotation} if found
+     * @throws ClassCastException If the {@link Annotation annotation} type that client requires can't match actual type
+     */
+    static <A extends Annotation> A getAnnotation(AnnotatedElement annotatedElement, String annotationClassName)
+            throws ClassCastException {
+        Class<? extends Annotation> annotationType = resolveAnnotationType(annotatedElement, annotationClassName);
+        if (annotationType == null) {
+            return null;
+        }
+        return (A) annotatedElement.getAnnotation(annotationType);
+    }
+
+    /**
+     * Get annotations that are <em>directly present</em> on this element.
+     * This method ignores inherited annotations.
+     *
+     * @param annotatedElement    the annotated element
+     * @param annotationsToFilter the annotations to filter
+     * @return non-null read-only {@link List}
+     */
+    static List<Annotation> getDeclaredAnnotations(AnnotatedElement annotatedElement,
+                                                   Predicate<Annotation>... annotationsToFilter) {
+        if (annotatedElement == null) {
+            return emptyList();
+        }
+
+        return unmodifiableList(filterAll(asList(annotatedElement.getDeclaredAnnotations()), annotationsToFilter));
+    }
+
+    /**
+     * Get all directly declared annotations of the the annotated element, not including
+     * meta annotations.
+     *
+     * @param annotatedElement    the annotated element
+     * @param annotationsToFilter the annotations to filter
+     * @return non-null read-only {@link List}
+     */
+    static List<Annotation> getAllDeclaredAnnotations(AnnotatedElement annotatedElement,
+                                                      Predicate<Annotation>... annotationsToFilter) {
+        if (isType(annotatedElement)) {
+            return getAllDeclaredAnnotations((Class) annotatedElement, annotationsToFilter);
+        } else {
+            return getDeclaredAnnotations(annotatedElement, annotationsToFilter);
+        }
+    }
+
+    /**
+     * Get all directly declared annotations of the specified type and its' all hierarchical types, not including
+     * meta annotations.
+     *
+     * @param type                the specified type
+     * @param annotationsToFilter the annotations to filter
+     * @return non-null read-only {@link List}
+     */
+    static List<Annotation> getAllDeclaredAnnotations(Class<?> type, Predicate<Annotation>... annotationsToFilter) {
+
+        if (type == null) {
+            return emptyList();
+        }
+
+        List<Annotation> allAnnotations = new LinkedList<>();
+
+        // All types
+        Set<Class<?>> allTypes = new LinkedHashSet<>();
+        // Add current type
+        allTypes.add(type);
+        // Add all inherited types
+        allTypes.addAll(getAllInheritedTypes(type, t -> !Object.class.equals(t)));
+
+        for (Class<?> t : allTypes) {
+            allAnnotations.addAll(getDeclaredAnnotations(t, annotationsToFilter));
+        }
+
+        return unmodifiableList(allAnnotations);
+    }
+
+
+    /**
+     * Get the meta-annotated {@link Annotation annotations} directly, excluding {@link Target}, {@link Retention}
+     * and {@link Documented}
+     *
+     * @param annotationType          the {@link Annotation annotation} type
+     * @param metaAnnotationsToFilter the meta annotations to filter
+     * @return non-null read-only {@link List}
+     */
+    static List<Annotation> getMetaAnnotations(Class<? extends Annotation> annotationType,
+                                               Predicate<Annotation>... metaAnnotationsToFilter) {
+        return getDeclaredAnnotations(annotationType,
+                // Excludes the Java native annotation types or it causes the stack overflow, e.g,
+                // @Target annotates itself
+                excludedType(Target.class),
+                excludedType(Retention.class),
+                excludedType(Documented.class),
+                // Add other predicates
+                and(metaAnnotationsToFilter)
+        );
+    }
+
+    /**
+     * Get all meta annotations from the specified {@link Annotation annotation} type
+     *
+     * @param annotationType      the {@link Annotation annotation} type
+     * @param annotationsToFilter the annotations to filter
+     * @return non-null read-only {@link List}
+     */
+    static List<Annotation> getAllMetaAnnotations(Class<? extends Annotation> annotationType,
+                                                  Predicate<Annotation>... annotationsToFilter) {
+
+        List<Annotation> allMetaAnnotations = new LinkedList<>();
+
+        List<Annotation> metaAnnotations = getMetaAnnotations(annotationType);
+
+        allMetaAnnotations.addAll(metaAnnotations);
+
+        for (Annotation metaAnnotation : metaAnnotations) {
+            // Get the nested meta annotations recursively
+            allMetaAnnotations.addAll(getAllMetaAnnotations(metaAnnotation.annotationType()));
+        }
+
+        return unmodifiableList(filterAll(allMetaAnnotations, annotationsToFilter));
+    }
+
+    /**
+     * Find the annotation that is annotated on the specified element may be a meta-annotation
+     *
+     * @param annotatedElement    the annotated element
+     * @param annotationClassName the class name of annotation
+     * @param <A>                 the required type of annotation
+     * @return If found, return first matched-type {@link Annotation annotation}, or <code>null</code>
+     */
+    static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, String annotationClassName) {
+        return findAnnotation(annotatedElement, resolveAnnotationType(annotatedElement, annotationClassName));
+    }
+
+    /**
+     * Find the annotation that is annotated on the specified element may be a meta-annotation
+     *
+     * @param annotatedElement the annotated element
+     * @param annotationType   the type of annotation
+     * @param <A>              the required type of annotation
+     * @return If found, return first matched-type {@link Annotation annotation}, or <code>null</code>
+     */
+    static <A extends Annotation> A findAnnotation(AnnotatedElement annotatedElement, Class<A> annotationType) {
+        return (A) filterFirst(getAllDeclaredAnnotations(annotatedElement), a -> isSameType(a, annotationType));
+    }
+
+    /**
+     * Find the meta annotations from the the {@link Annotation annotation} type by meta annotation type
+     *
+     * @param annotationType     the {@link Annotation annotation} type
+     * @param metaAnnotationType the meta annotation type
+     * @param <A>                the type of required annotation
+     * @return if found, return all matched results, or get an {@link Collections#emptyList() empty list}
+     */
+    static <A extends Annotation> List<A> findMetaAnnotations(Class<? extends Annotation> annotationType,
+                                                              Class<A> metaAnnotationType) {
+        return (List<A>) getAllMetaAnnotations(annotationType, a -> isSameType(a, metaAnnotationType));
+    }
+
+    /**
+     * Find the meta annotations from the the the annotated element by meta annotation type
+     *
+     * @param annotatedElement   the annotated element
+     * @param metaAnnotationType the meta annotation type
+     * @param <A>                the type of required annotation
+     * @return if found, return all matched results, or get an {@link Collections#emptyList() empty list}
+     */
+    static <A extends Annotation> List<A> findMetaAnnotations(AnnotatedElement annotatedElement,
+                                                              Class<A> metaAnnotationType) {
+        List<A> metaAnnotations = new LinkedList<>();
+
+        for (Annotation annotation : getAllDeclaredAnnotations(annotatedElement)) {
+            metaAnnotations.addAll(findMetaAnnotations(annotation.annotationType(), metaAnnotationType));
+        }
+
+        return unmodifiableList(metaAnnotations);
+    }
+
+    /**
+     * Find the meta annotation from the annotated element by meta annotation type
+     *
+     * @param annotatedElement        the annotated element
+     * @param metaAnnotationClassName the class name of meta annotation
+     * @param <A>                     the type of required annotation
+     * @return {@link #findMetaAnnotation(Class, Class)}
+     */
+    static <A extends Annotation> A findMetaAnnotation(AnnotatedElement annotatedElement,
+                                                       String metaAnnotationClassName) {
+        return findMetaAnnotation(annotatedElement, resolveAnnotationType(annotatedElement, metaAnnotationClassName));
+    }
+
+    /**
+     * Find the meta annotation from the annotation type by meta annotation type
+     *
+     * @param annotationType     the {@link Annotation annotation} type
+     * @param metaAnnotationType the meta annotation type
+     * @param <A>                the type of required annotation
+     * @return If found, return the {@link CollectionUtils#first(Collection)} matched result, return <code>null</code>.
+     * If it requires more result, please consider to use {@link #findMetaAnnotations(Class, Class)}
+     * @see #findMetaAnnotations(Class, Class)
+     */
+    static <A extends Annotation> A findMetaAnnotation(Class<? extends Annotation> annotationType,
+                                                       Class<A> metaAnnotationType) {
+        return first(findMetaAnnotations(annotationType, metaAnnotationType));
+    }
+
+    /**
+     * Find the meta annotation from the annotated element by meta annotation type
+     *
+     * @param annotatedElement   the annotated element
+     * @param metaAnnotationType the meta annotation type
+     * @param <A>                the type of required annotation
+     * @return If found, return the {@link CollectionUtils#first(Collection)} matched result, return <code>null</code>.
+     * If it requires more result, please consider to use {@link #findMetaAnnotations(AnnotatedElement, Class)}
+     * @see #findMetaAnnotations(AnnotatedElement, Class)
+     */
+    static <A extends Annotation> A findMetaAnnotation(AnnotatedElement annotatedElement, Class<A> metaAnnotationType) {
+        return first(findMetaAnnotations(annotatedElement, metaAnnotationType));
+    }
+
+    /**
+     * Tests the annotated element is annotated the specified annotations or not
+     *
+     * @param type            the annotated type
+     * @param matchAll        If <code>true</code>, checking all annotation types are present or not, or match any
+     * @param annotationTypes the specified annotation types
+     * @return If the specified annotation types are present, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isAnnotationPresent(Class<?> type,
+                                       boolean matchAll,
+                                       Class<? extends Annotation>... annotationTypes) {
+
+        int size = annotationTypes == null ? 0 : annotationTypes.length;
+
+        if (size < 1) {
+            return false;
+        }
+
+        int presentCount = 0;
+
+        for (int i = 0; i < size; i++) {
+            Class<? extends Annotation> annotationType = annotationTypes[i];
+            if (findAnnotation(type, annotationType) != null || findMetaAnnotation(type, annotationType) != null) {
+                presentCount++;
+            }
+        }
+
+        return matchAll ? presentCount == size : presentCount > 0;
+    }
+
+    /**
+     * Tests the annotated element is annotated the specified annotation or not
+     *
+     * @param type           the annotated type
+     * @param annotationType the class of annotation
+     * @return If the specified annotation type is present, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isAnnotationPresent(Class<?> type, Class<? extends Annotation> annotationType) {
+        return isAnnotationPresent(type, true, annotationType);
+    }
+
+    /**
+     * Tests the annotated element is present any specified annotation types
+     *
+     * @param annotatedElement    the annotated element
+     * @param annotationClassName the class name of annotation
+     * @return If any specified annotation types are present, return <code>true</code>
+     */
+    static boolean isAnnotationPresent(AnnotatedElement annotatedElement, String annotationClassName) {
+        ClassLoader classLoader = annotatedElement.getClass().getClassLoader();
+        Class<?> resolvedType = resolveClass(annotationClassName, classLoader);
+        if (!Annotation.class.isAssignableFrom(resolvedType)) {
+            return false;
+        }
+        return isAnnotationPresent(annotatedElement, (Class<? extends Annotation>) resolvedType);
+    }
+
+    /**
+     * Tests the annotated element is present any specified annotation types
+     *
+     * @param annotatedElement the annotated element
+     * @param annotationType   the class of annotation
+     * @return If any specified annotation types are present, return <code>true</code>
+     */
+    static boolean isAnnotationPresent(AnnotatedElement annotatedElement, Class<? extends Annotation> annotationType) {
+        if (isType(annotatedElement)) {
+            return isAnnotationPresent((Class) annotatedElement, annotationType);
+        } else {
+            return annotatedElement.isAnnotationPresent(annotationType) ||
+                    findMetaAnnotation(annotatedElement, annotationType) != null; // to find meta-annotation
+        }
+    }
+
+    /**
+     * Tests the annotated element is annotated all specified annotations or not
+     *
+     * @param type            the annotated type
+     * @param annotationTypes the specified annotation types
+     * @return If the specified annotation types are present, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isAllAnnotationPresent(Class<?> type, Class<? extends Annotation>... annotationTypes) {
+        return isAnnotationPresent(type, true, annotationTypes);
+    }
+
+    /**
+     * Tests the annotated element is present any specified annotation types
+     *
+     * @param type            the annotated type
+     * @param annotationTypes the specified annotation types
+     * @return If any specified annotation types are present, return <code>true</code>
+     */
+    static boolean isAnyAnnotationPresent(Class<?> type,
+                                          Class<? extends Annotation>... annotationTypes) {
+        return isAnnotationPresent(type, false, annotationTypes);
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java
new file mode 100644
index 0000000..055ba48
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/CharSequenceComparator.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.utils;
+
+import java.util.Comparator;
+
+/**
+ * The {@link Comparator} for {@link CharSequence}
+ *
+ * @since 2.7.6
+ */
+public class CharSequenceComparator implements Comparator<CharSequence> {
+
+    public final static CharSequenceComparator INSTANCE = new CharSequenceComparator();
+
+    private CharSequenceComparator() {
+    }
+
+    @Override
+    public int compare(CharSequence c1, CharSequence c2) {
+        return c1.toString().compareTo(c2.toString());
+    }
+}
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 ec5b766..a0b6dee 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
@@ -18,11 +18,26 @@ package org.apache.dubbo.common.utils;
 
 
 import java.lang.reflect.Array;
+import java.math.BigDecimal;
+import java.math.BigInteger;
 import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
+import java.util.function.Predicate;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableSet;
+import static java.util.stream.Collectors.toList;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
+import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
 
 public class ClassUtils {
     /**
@@ -44,6 +59,43 @@ public class ClassUtils {
      */
     private static final Map<Class<?>, Class<?>> PRIMITIVE_WRAPPER_TYPE_MAP = new HashMap<Class<?>, Class<?>>(16);
 
+    /**
+     * Simple Types including:
+     * <ul>
+     *     <li>{@link Void}</li>
+     *     <li>{@link Boolean}</li>
+     *     <li>{@link Character}</li>
+     *     <li>{@link Byte}</li>
+     *     <li>{@link Integer}</li>
+     *     <li>{@link Float}</li>
+     *     <li>{@link Double}</li>
+     *     <li>{@link String}</li>
+     *     <li>{@link BigDecimal}</li>
+     *     <li>{@link BigInteger}</li>
+     *     <li>{@link Date}</li>
+     *     <li>{@link Object}</li>
+     * </ul>
+     *
+     * @see javax.management.openmbean.SimpleType
+     * @since 2.7.6
+     */
+    public static final Set<Class<?>> SIMPLE_TYPES = ofSet(
+            Void.class,
+            Boolean.class,
+            Character.class,
+            Byte.class,
+            Short.class,
+            Integer.class,
+            Long.class,
+            Float.class,
+            Double.class,
+            String.class,
+            BigDecimal.class,
+            BigInteger.class,
+            Date.class,
+            Object.class
+    );
+
     private static final char PACKAGE_SEPARATOR_CHAR = '.';
 
     static {
@@ -228,18 +280,27 @@ public class ClassUtils {
     }
 
 
+    /**
+     * The specified type is primitive type or simple type
+     *
+     * @param type the type to test
+     * @return
+     * @deprecated as 2.7.6, use {@link Class#isPrimitive()} plus {@link #isSimpleType(Class)} instead
+     */
     public static boolean isPrimitive(Class<?> type) {
-        return type.isPrimitive()
-                || type == String.class
-                || type == Character.class
-                || type == Boolean.class
-                || type == Byte.class
-                || type == Short.class
-                || type == Integer.class
-                || type == Long.class
-                || type == Float.class
-                || type == Double.class
-                || type == Object.class;
+        return type != null && (type.isPrimitive() || isSimpleType(type));
+    }
+
+    /**
+     * The specified type is simple type or not
+     *
+     * @param type the type to test
+     * @return if <code>type</code> is one element of {@link #SIMPLE_TYPES}, return <code>true</code>, or <code>false</code>
+     * @see #SIMPLE_TYPES
+     * @since 2.7.6
+     */
+    public static boolean isSimpleType(Class<?> type) {
+        return SIMPLE_TYPES.contains(type);
     }
 
     public static Object convertPrimitive(Class<?> type, String value) {
@@ -285,4 +346,147 @@ public class ClassUtils {
         }
         return true;
     }
+
+    /**
+     * Get all super classes from the specified type
+     *
+     * @param type         the specified type
+     * @param classFilters the filters for classes
+     * @return non-null read-only {@link Set}
+     * @since 2.7.6
+     */
+    public static Set<Class<?>> getAllSuperClasses(Class<?> type, Predicate<Class<?>>... classFilters) {
+
+        Set<Class<?>> allSuperClasses = new LinkedHashSet<>();
+
+        Class<?> superClass = type.getSuperclass();
+
+        if (superClass != null) {
+            // add current super class
+            allSuperClasses.add(superClass);
+            // add ancestor classes
+            allSuperClasses.addAll(getAllSuperClasses(superClass));
+        }
+
+        return unmodifiableSet(filterAll(allSuperClasses, classFilters));
+    }
+
+    /**
+     * Get all interfaces from the specified type
+     *
+     * @param type             the specified type
+     * @param interfaceFilters the filters for interfaces
+     * @return non-null read-only {@link Set}
+     * @since 2.7.6
+     */
+    public static Set<Class<?>> getAllInterfaces(Class<?> type, Predicate<Class<?>>... interfaceFilters) {
+
+        if (type == null || type.isPrimitive()) {
+            return emptySet();
+        }
+
+        Set<Class<?>> allInterfaces = new LinkedHashSet<>();
+
+        Class<?>[] interfaces = type.getInterfaces();
+
+        if (isNotEmpty(interfaces)) {
+            // add current interfaces
+            allInterfaces.addAll(asList(interfaces));
+        }
+
+        // add all super interfaces
+        getAllSuperClasses(type).forEach(superType -> allInterfaces.addAll(getAllInterfaces(superType)));
+
+        // add all super interfaces from all interfaces
+        allInterfaces.stream()
+                .map(ClassUtils::getAllInterfaces)
+                .flatMap(Collection::stream)
+                .collect(toList())
+                .forEach(allInterfaces::add);
+
+        return filterAll(allInterfaces, interfaceFilters);
+    }
+
+    /**
+     * Get all inherited types from the specified type
+     *
+     * @param type        the specified type
+     * @param typeFilters the filters for types
+     * @return non-null read-only {@link Set}
+     * @since 2.7.6
+     */
+    public static Set<Class<?>> getAllInheritedTypes(Class<?> type, Predicate<Class<?>>... typeFilters) {
+        // Add all super classes
+        Set<Class<?>> types = new LinkedHashSet<>(getAllSuperClasses(type, typeFilters));
+        // Add all interface classes
+        types.addAll(getAllInterfaces(type, typeFilters));
+        return unmodifiableSet(types);
+    }
+
+
+    /**
+     * the semantics is same as {@link Class#isAssignableFrom(Class)}
+     *
+     * @param superType  the super type
+     * @param targetType the target type
+     * @return see {@link Class#isAssignableFrom(Class)}
+     * @since 2.7.6
+     */
+    public static boolean isAssignableFrom(Class<?> superType, Class<?> targetType) {
+        // any argument is null
+        if (superType == null || targetType == null) {
+            return false;
+        }
+        // equals
+        if (Objects.equals(superType, targetType)) {
+            return true;
+        }
+        // isAssignableFrom
+        return superType.isAssignableFrom(targetType);
+    }
+
+    /**
+     * Test the specified class name is present in the {@link ClassLoader}
+     *
+     * @param className   the name of {@link Class}
+     * @param classLoader {@link ClassLoader}
+     * @return If found, return <code>true</code>
+     * @since 2.7.6
+     */
+    public static boolean isPresent(String className, ClassLoader classLoader) {
+        try {
+            forName(className, classLoader);
+        } catch (Throwable ignored) { // Ignored
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Resolve the {@link Class} by the specified name and {@link ClassLoader}
+     *
+     * @param className   the name of {@link Class}
+     * @param classLoader {@link ClassLoader}
+     * @return If can't be resolved , return <code>null</code>
+     * @since 2.7.6
+     */
+    public static Class<?> resolveClass(String className, ClassLoader classLoader) {
+        Class<?> targetClass = null;
+        try {
+            targetClass = forName(className, classLoader);
+        } catch (Throwable ignored) { // Ignored
+        }
+        return targetClass;
+    }
+
+    /**
+     * Is generic class or not?
+     *
+     * @param type the target type
+     * @return if the target type is not null or <code>void</code> or Void.class, return <code>true</code>, or false
+     * @since 2.7.6
+     */
+    public static boolean isGenericClass(Class<?> type) {
+        return type != null && !void.class.equals(type) && !Void.class.equals(type);
+    }
 }
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 9bb3c5e..1b73370 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
@@ -16,6 +16,7 @@
  */
 package org.apache.dubbo.common.utils;
 
+import java.util.AbstractSet;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -26,7 +27,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import static java.util.Arrays.asList;
 import static java.util.Collections.emptySet;
 import static java.util.Collections.unmodifiableSet;
 
@@ -270,9 +270,112 @@ public class CollectionUtils {
      * @return read-only {@link Set}
      */
     public static <T> Set<T> ofSet(T... values) {
-        if (values == null || values.length < 1) {
+        int size = values == null ? 0 : values.length;
+        if (size < 1) {
             return emptySet();
         }
-        return unmodifiableSet(new LinkedHashSet<>(asList(values)));
+
+        float loadFactor = 1f / ((size + 1) * 1.0f);
+
+        if (loadFactor > 0.75f) {
+            loadFactor = 0.75f;
+        }
+
+        Set<T> elements = new LinkedHashSet<>(size, loadFactor);
+        for (int i = 0; i < size; i++) {
+            elements.add(values[i]);
+        }
+        return unmodifiableSet(elements);
     }
+
+    /**
+     * Get the size of the specified {@link Collection}
+     *
+     * @param collection the specified {@link Collection}
+     * @return must be positive number
+     * @since 2.7.6
+     */
+    public static int size(Collection<?> collection) {
+        return collection == null ? 0 : collection.size();
+    }
+
+    /**
+     * Compares the specified collection with another, the main implementation references
+     * {@link AbstractSet}
+     *
+     * @param one     {@link Collection}
+     * @param another {@link Collection}
+     * @return if equals, return <code>true</code>, or <code>false</code>
+     * @since 2.7.6
+     */
+    public static boolean equals(Collection<?> one, Collection<?> another) {
+
+        if (one == another) {
+            return true;
+        }
+
+        if (isEmpty(one) && isEmpty(another)) {
+            return true;
+        }
+
+        if (size(one) != size(another)) {
+            return false;
+        }
+
+        try {
+            return one.containsAll(another);
+        } catch (ClassCastException unused) {
+            return false;
+        } catch (NullPointerException unused) {
+            return false;
+        }
+    }
+
+    /**
+     * Add the multiple values into {@link Collection the specified collection}
+     *
+     * @param collection {@link Collection the specified collection}
+     * @param values     the multiple values
+     * @param <T>        the type of values
+     * @return the effected count after added
+     * @since 2.7.6
+     */
+    public static <T> int addAll(Collection<T> collection, T... values) {
+
+        int size = values == null ? 0 : values.length;
+
+        if (collection == null || size < 1) {
+            return 0;
+        }
+
+        int effectedCount = 0;
+        for (int i = 0; i < size; i++) {
+            if (collection.add(values[i])) {
+                effectedCount++;
+            }
+        }
+
+        return effectedCount;
+    }
+
+    /**
+     * Take the first element from the specified collection
+     *
+     * @param values the collection object
+     * @param <T>    the type of element of collection
+     * @return if found, return the first one, or <code>null</code>
+     * @since 2.7.6
+     */
+    public static <T> T first(Collection<T> values) {
+        if (isEmpty(values)) {
+            return null;
+        }
+        if (values instanceof List) {
+            List<T> list = (List<T>) values;
+            return list.get(0);
+        } else {
+            return values.iterator().next();
+        }
+    }
+
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/HttpUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/HttpUtils.java
new file mode 100644
index 0000000..b944d5a
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/HttpUtils.java
@@ -0,0 +1,264 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed 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
+ *
+ *      https://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.utils;
+
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.common.utils.StringUtils.AND;
+import static org.apache.dubbo.common.utils.StringUtils.EQUAL;
+import static org.apache.dubbo.common.utils.StringUtils.QUESTION_MASK;
+import static org.apache.dubbo.common.utils.StringUtils.SLASH;
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+import static org.apache.dubbo.common.utils.StringUtils.replace;
+
+/**
+ * Http Utilities class
+ *
+ * @since 2.7.6
+ */
+public abstract class HttpUtils {
+
+    private static final String UTF_8 = "UTF-8";
+
+    /**
+     * HTTP GET method.
+     */
+    public static final String GET = "GET";
+    /**
+     * HTTP POST method.
+     */
+    public static final String POST = "POST";
+    /**
+     * HTTP PUT method.
+     */
+    public static final String PUT = "PUT";
+    /**
+     * HTTP DELETE method.
+     */
+    public static final String DELETE = "DELETE";
+    /**
+     * HTTP HEAD method.
+     */
+    public static final String HEAD = "HEAD";
+    /**
+     * HTTP OPTIONS method.
+     */
+    public static final String OPTIONS = "OPTIONS";
+
+    /**
+     * The HTTP methods to support
+     */
+    public static final Set<String> HTTP_METHODS = unmodifiableSet(new LinkedHashSet<>(asList(
+            GET, POST, POST, PUT, DELETE, HEAD, OPTIONS
+    )));
+
+
+    public static String buildPath(String rootPath, String... subPaths) {
+
+        Set<String> paths = new LinkedHashSet<>();
+        paths.add(rootPath);
+        paths.addAll(asList(subPaths));
+
+        return normalizePath(paths.stream()
+                .filter(StringUtils::isNotEmpty)
+                .collect(Collectors.joining(SLASH)));
+    }
+
+    /**
+     * Normalize path:
+     * <ol>
+     * <li>To remove query string if presents</li>
+     * <li>To remove duplicated slash("/") if exists</li>
+     * </ol>
+     *
+     * @param path path to be normalized
+     * @return a normalized path if required
+     */
+    public static String normalizePath(String path) {
+        if (isEmpty(path)) {
+            return SLASH;
+        }
+        String normalizedPath = path;
+        int index = normalizedPath.indexOf(QUESTION_MASK);
+        if (index > -1) {
+            normalizedPath = normalizedPath.substring(0, index);
+        }
+        return replace(normalizedPath, "//", "/");
+    }
+
+//    /**
+//     * Get Parameters from the specified query string.
+//     * <p>
+//     *
+//     * @param queryString The query string
+//     * @return The query parameters
+//     */
+//    public static MultivaluedMap<String, String> getParameters(String queryString) {
+//        return getParameters(split(queryString, AND_CHAR));
+//    }
+
+//    /**
+//     * Get Parameters from the specified pairs of name-value.
+//     * <p>
+//     *
+//     * @param pairs The pairs of name-value
+//     * @return The query parameters
+//     */
+//    public static MultivaluedMap<String, String> getParameters(Iterable<String> pairs) {
+//        MultivaluedMap<String, String> parameters = new MultivaluedHashMap<>();
+//        if (pairs != null) {
+//            for (String pair : pairs) {
+//                String[] nameAndValue = split(pair, EQUAL_CHAR);
+//                String name = decode(nameAndValue[0]);
+//                String value = nameAndValue.length < 2 ? null : nameAndValue[1];
+//                value = decode(value);
+//                addParam(parameters, name, value);
+//            }
+//        }
+//        return parameters;
+//    }
+
+//    /**
+//     * Get Parameters from the specified pairs of name-value.
+//     * <p>
+//     *
+//     * @param pairs The pairs of name-value
+//     * @return The query parameters
+//     */
+//    public static MultivaluedMap<String, String> getParameters(String... pairs) {
+//        return getParameters(asList(pairs));
+//    }
+
+    // /**
+    // * Parse a read-only {@link MultivaluedMap} of {@link HttpCookie} from {@link
+    // HttpHeaders}
+    // *
+    // * @param httpHeaders {@link HttpHeaders}
+    // * @return non-null, the key is a cookie name , the value is {@link HttpCookie}
+    // */
+    // public static MultivaluedMap<String, HttpCookie> parseCookies(HttpHeaders
+    // httpHeaders) {
+    //
+    // String cookie = httpHeaders.getFirst(COOKIE);
+    //
+    // String[] cookieNameAndValues = StringUtils.delimitedListToStringArray(cookie,
+    // SEMICOLON);
+    //
+    // MultivaluedMap<String, HttpCookie> cookies = new
+    // LinkedMultiValueMap<>(cookieNameAndValues.length);
+    //
+    // for (String cookeNameAndValue : cookieNameAndValues) {
+    // String[] nameAndValue =
+    // delimitedListToStringArray(trimWhitespace(cookeNameAndValue), EQUAL);
+    // String name = nameAndValue[0];
+    // String value = nameAndValue.length < 2 ? null : nameAndValue[1];
+    // HttpCookie httpCookie = new HttpCookie(name, value);
+    // cookies.add(name, httpCookie);
+    // }
+    //
+    // return cookies;
+    // }
+
+    /**
+     * To the name and value line sets
+     *
+     * @param nameAndValuesMap the map of name and values
+     * @return non-null
+     */
+    public static Set<String> toNameAndValuesSet(
+            Map<String, List<String>> nameAndValuesMap) {
+        Set<String> nameAndValues = new LinkedHashSet<>();
+        for (Map.Entry<String, List<String>> entry : nameAndValuesMap.entrySet()) {
+            String name = entry.getKey();
+            List<String> values = entry.getValue();
+            for (String value : values) {
+                String nameAndValue = name + EQUAL + value;
+                nameAndValues.add(nameAndValue);
+            }
+        }
+        return nameAndValues;
+    }
+
+    public static String[] toNameAndValues(Map<String, List<String>> nameAndValuesMap) {
+        return toNameAndValuesSet(nameAndValuesMap).toArray(new String[0]);
+    }
+
+    /**
+     * Generate a string of query string from the specified request parameters {@link Map}
+     *
+     * @param params the specified request parameters {@link Map}
+     * @return non-null
+     */
+    public static String toQueryString(Map<String, List<String>> params) {
+        StringBuilder builder = new StringBuilder();
+        for (String line : toNameAndValuesSet(params)) {
+            builder.append(line).append(AND);
+        }
+        return builder.toString();
+    }
+
+    /**
+     * Decode value
+     *
+     * @param value the value requires to decode
+     * @return the decoded value
+     */
+    public static String decode(String value) {
+        if (value == null) {
+            return value;
+        }
+        String decodedValue = value;
+        try {
+            decodedValue = URLDecoder.decode(value, UTF_8);
+        } catch (UnsupportedEncodingException ex) {
+        }
+        return decodedValue;
+    }
+
+    /**
+     * encode value
+     *
+     * @param value the value requires to encode
+     * @return the encoded value
+     */
+    public static String encode(String value) {
+        String encodedValue = value;
+        try {
+            encodedValue = URLEncoder.encode(value, UTF_8);
+        } catch (UnsupportedEncodingException ex) {
+        }
+        return encodedValue;
+    }
+
+//    private static void addParam(MultivaluedMap<String, String> paramsMap, String name,
+//                                 String value) {
+//        String paramValue = trim(value);
+//        if (isEmpty(paramValue)) {
+//            paramValue = EMPTY_VALUE;
+//        }
+//        paramsMap.add(trim(name), paramValue);
+//    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java
new file mode 100644
index 0000000..f7aa6ff
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MemberUtils.java
@@ -0,0 +1,62 @@
+/*
+ * 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.utils;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Member;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+
+/**
+ * Java Reflection {@link Member} Utilities class
+ *
+ * @since 2.7.6
+ */
+public interface MemberUtils {
+
+    /**
+     * check the specified {@link Member member} is static or not ?
+     *
+     * @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
+     * @return Iff <code>member</code> is static one, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isStatic(Member member) {
+        return member != null && Modifier.isStatic(member.getModifiers());
+    }
+
+    /**
+     * check the specified {@link Member member} is private or not ?
+     *
+     * @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
+     * @return Iff <code>member</code> is private one, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isPrivate(Member member) {
+        return member != null && Modifier.isPrivate(member.getModifiers());
+    }
+
+    /**
+     * check the specified {@link Member member} is public or not ?
+     *
+     * @param member {@link Member} instance, e.g, {@link Constructor}, {@link Method} or {@link Field}
+     * @return Iff <code>member</code> is public one, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isPublic(Member member) {
+        return member != null && Modifier.isPublic(member.getModifiers());
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java
new file mode 100644
index 0000000..8270c1d
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/MethodComparator.java
@@ -0,0 +1,71 @@
+/*
+ * 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.utils;
+
+import java.lang.reflect.Method;
+import java.util.Comparator;
+
+/**
+ * The Comparator class for {@link Method}, the comparison rule :
+ * <ol>
+ *     <li>Comparing to two {@link Method#getName() method names} {@link String#compareTo(String) lexicographically}.
+ *     If equals, go to step 2</li>
+ *     <li>Comparing to the count of two method parameters. If equals, go to step 3</li>
+ *     <li>Comparing to the type names of methods parameter {@link String#compareTo(String) lexicographically}</li>
+ * </ol>
+ *
+ * @since 2.7.6
+ */
+public class MethodComparator implements Comparator<Method> {
+
+    public final static MethodComparator INSTANCE = new MethodComparator();
+
+    private MethodComparator() {
+    }
+
+    @Override
+    public int compare(Method m1, Method m2) {
+
+        if (m1.equals(m2)) {
+            return 0;
+        }
+
+        // Step 1
+        String n1 = m1.getName();
+        String n2 = m2.getName();
+        int value = n1.compareTo(n2);
+
+        if (value == 0) { // Step 2
+
+            Class[] types1 = m1.getParameterTypes();
+            Class[] types2 = m2.getParameterTypes();
+
+            value = types1.length - types2.length;
+
+            if (value == 0) { // Step 3
+                for (int i = 0; i < types1.length; i++) {
+                    value = types1[i].getName().compareTo(types2[i].getName());
+                    if (value != 0) {
+                        break;
+                    }
+                }
+            }
+        }
+
+        return Integer.compare(value, 0);
+    }
+}
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 26b05ef..27262b4 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
@@ -16,17 +16,32 @@
  */
 package org.apache.dubbo.common.utils;
 
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.utils.ClassUtils.getAllInheritedTypes;
+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;
 
 /**
  * Miscellaneous method utility methods.
  * Mainly for internal use within the framework.
  *
- * @author LiZhenNet
  * @since 2.7.2
  */
-public class MethodUtils {
+public interface MethodUtils {
 
     /**
      * Return {@code true} if the provided method is a set method.
@@ -101,4 +116,277 @@ public class MethodUtils {
     public 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
+     *
+     * @param declaredClass the declared class to exclude
+     * @return non-null
+     * @since 2.7.6
+     */
+    static Predicate<Method> excludedDeclaredClass(Class<?> declaredClass) {
+        return method -> !Objects.equals(declaredClass, method.getDeclaringClass());
+    }
+
+    /**
+     * Get all {@link Method methods} of the declared class
+     *
+     * @param declaringClass        the declared class
+     * @param includeInheritedTypes include the inherited types, e,g. super classes or interfaces
+     * @param publicOnly            only public method
+     * @param methodsToFilter       (optional) the methods to be filtered
+     * @return non-null read-only {@link List}
+     * @since 2.7.6
+     */
+    static List<Method> getMethods(Class<?> declaringClass, boolean includeInheritedTypes, boolean publicOnly,
+                                   Predicate<Method>... methodsToFilter) {
+
+        if (declaringClass == null || declaringClass.isPrimitive()) {
+            return emptyList();
+        }
+
+        // All declared classes
+        List<Class<?>> declaredClasses = new LinkedList<>();
+        // Add the top declaring class
+        declaredClasses.add(declaringClass);
+        // If the super classes are resolved, all them into declaredClasses
+        if (includeInheritedTypes) {
+            declaredClasses.addAll(getAllInheritedTypes(declaringClass));
+        }
+
+        // All methods
+        List<Method> allMethods = new LinkedList<>();
+
+        for (Class<?> classToSearch : declaredClasses) {
+            Method[] methods = publicOnly ? classToSearch.getMethods() : classToSearch.getDeclaredMethods();
+            // Add the declared methods or public methods
+            for (Method method : methods) {
+                allMethods.add(method);
+            }
+        }
+
+        return unmodifiableList(filterAll(allMethods, methodsToFilter));
+    }
+
+    /**
+     * Get all declared {@link Method methods} of the declared class, excluding the inherited methods
+     *
+     * @param declaringClass  the declared class
+     * @param methodsToFilter (optional) the methods to be filtered
+     * @return non-null read-only {@link List}
+     * @see #getMethods(Class, boolean, boolean, Predicate[])
+     * @since 2.7.6
+     */
+    static List<Method> getDeclaredMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
+        return getMethods(declaringClass, false, false, methodsToFilter);
+    }
+
+    /**
+     * Get all public {@link Method methods} of the declared class, including the inherited methods.
+     *
+     * @param declaringClass  the declared class
+     * @param methodsToFilter (optional) the methods to be filtered
+     * @return non-null read-only {@link List}
+     * @see #getMethods(Class, boolean, boolean, Predicate[])
+     * @since 2.7.6
+     */
+    static List<Method> getMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
+        return getMethods(declaringClass, false, true, methodsToFilter);
+    }
+
+    /**
+     * Get all declared {@link Method methods} of the declared class, including the inherited methods.
+     *
+     * @param declaringClass  the declared class
+     * @param methodsToFilter (optional) the methods to be filtered
+     * @return non-null read-only {@link List}
+     * @see #getMethods(Class, boolean, boolean, Predicate[])
+     * @since 2.7.6
+     */
+    static List<Method> getAllDeclaredMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
+        return getMethods(declaringClass, true, false, methodsToFilter);
+    }
+
+    /**
+     * Get all public {@link Method methods} of the declared class, including the inherited methods.
+     *
+     * @param declaringClass  the declared class
+     * @param methodsToFilter (optional) the methods to be filtered
+     * @return non-null read-only {@link List}
+     * @see #getMethods(Class, boolean, boolean, Predicate[])
+     * @since 2.7.6
+     */
+    static List<Method> getAllMethods(Class<?> declaringClass, Predicate<Method>... methodsToFilter) {
+        return getMethods(declaringClass, true, true, methodsToFilter);
+    }
+
+//    static List<Method> getOverriderMethods(Class<?> implementationClass, Class<?>... superTypes) {
+
+//
+
+//    }
+
+    /**
+     * Find the {@link Method} by the the specified type and method name without the parameter types
+     *
+     * @param type       the target type
+     * @param methodName the specified method name
+     * @return if not found, return <code>null</code>
+     * @since 2.7.6
+     */
+    static Method findMethod(Class type, String methodName) {
+        return findMethod(type, methodName, EMPTY_CLASS_ARRAY);
+    }
+
+    /**
+     * Find the {@link Method} by the the specified type, method name and parameter types
+     *
+     * @param type           the target type
+     * @param methodName     the method name
+     * @param parameterTypes the parameter types
+     * @return if not found, return <code>null</code>
+     * @since 2.7.6
+     */
+    static Method findMethod(Class type, String methodName, Class<?>... parameterTypes) {
+        Method method = null;
+        try {
+            method = type.getDeclaredMethod(methodName, parameterTypes);
+        } catch (NoSuchMethodException e) {
+        }
+        return method;
+    }
+
+    /**
+     * Invoke the target object and method
+     *
+     * @param object           the target object
+     * @param methodName       the method name
+     * @param methodParameters the method parameters
+     * @param <T>              the return type
+     * @return the target method's execution result
+     * @since 2.7.6
+     */
+    static <T> T invokeMethod(Object object, String methodName, Object... methodParameters) {
+        Class type = object.getClass();
+        Class[] parameterTypes = resolveTypes(methodParameters);
+        Method method = findMethod(type, methodName, parameterTypes);
+        T value = null;
+
+        try {
+            final boolean isAccessible = method.isAccessible();
+
+            if (!isAccessible) {
+                method.setAccessible(true);
+            }
+            value = (T) method.invoke(object, methodParameters);
+            method.setAccessible(isAccessible);
+        } catch (Exception e) {
+            throw new IllegalArgumentException(e);
+        }
+
+        return value;
+    }
+
+
+    /**
+     * Tests whether one method, as a member of a given type,
+     * overrides another method.
+     *
+     * @param overrider  the first method, possible overrider
+     * @param overridden the second method, possibly being overridden
+     * @return {@code true} if and only if the first method overrides
+     * the second
+     * @jls 8.4.8 Inheritance, Overriding, and Hiding
+     * @jls 9.4.1 Inheritance and Overriding
+     * @see Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)
+     */
+    static boolean overrides(Method overrider, Method overridden) {
+
+        if (overrider == null || overridden == null) {
+            return false;
+        }
+
+        // equality comparison: If two methods are same
+        if (Objects.equals(overrider, overridden)) {
+            return false;
+        }
+
+        // Modifiers comparison: Any method must be non-static method
+        if (isStatic(overrider) || isStatic(overridden)) { //
+            return false;
+        }
+
+        // Modifiers comparison: the accessibility of any method must not be private
+        if (isPrivate(overrider) || isPrivate(overridden)) {
+            return false;
+        }
+
+        // Inheritance comparison: The declaring class of overrider must be inherit from the overridden's
+        if (!overridden.getDeclaringClass().isAssignableFrom(overrider.getDeclaringClass())) {
+            return false;
+        }
+
+        // Method comparison: must not be "default" method
+        if (overrider.isDefault()) {
+            return false;
+        }
+
+        // Method comparison: The method name must be equal
+        if (!Objects.equals(overrider.getName(), overridden.getName())) {
+            return false;
+        }
+
+        // Method comparison: The count of method parameters must be equal
+        if (!Objects.equals(overrider.getParameterCount(), overridden.getParameterCount())) {
+            return false;
+        }
+
+        // Method comparison: Any parameter type of overrider must equal the overridden's
+        for (int i = 0; i < overrider.getParameterCount(); i++) {
+            if (!Objects.equals(overridden.getParameterTypes()[i], overrider.getParameterTypes()[i])) {
+                return false;
+            }
+        }
+
+        // Method comparison: The return type of overrider must be inherit from the overridden's
+        if (!overridden.getReturnType().isAssignableFrom(overrider.getReturnType())) {
+            return false;
+        }
+
+        // Throwable comparison: "throws" Throwable list will be ignored, trust the compiler verify
+
+        return true;
+    }
+
+    /**
+     * Find the nearest overridden {@link Method method} from the inherited class
+     *
+     * @param overrider the overrider {@link Method method}
+     * @return if found, the overrider <code>method</code>, or <code>null</code>
+     */
+    static Method findNearestOverriddenMethod(Method overrider) {
+        Class<?> declaringClass = overrider.getDeclaringClass();
+        Method overriddenMethod = null;
+        for (Class<?> inheritedType : getAllInheritedTypes(declaringClass)) {
+            overriddenMethod = findOverriddenMethod(overrider, inheritedType);
+            if (overriddenMethod != null) {
+                break;
+            }
+        }
+        return overriddenMethod;
+    }
+
+    /**
+     * Find the overridden {@link Method method} from the declaring class
+     *
+     * @param overrider      the overrider {@link Method method}
+     * @param declaringClass the class that is declaring the overridden {@link Method method}
+     * @return if found, the overrider <code>method</code>, or <code>null</code>
+     */
+    static Method findOverriddenMethod(Method overrider, Class<?> declaringClass) {
+        List<Method> matchedMethods = getAllMethods(declaringClass, method -> overrides(overrider, method));
+        return matchedMethods.isEmpty() ? null : matchedMethods.get(0);
+    }
 }
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 df5764a..866d4b6 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
@@ -55,6 +55,7 @@ import java.util.stream.Stream;
 
 import static java.util.Arrays.asList;
 import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
 
 /**
  * ReflectUtils
@@ -1259,6 +1260,15 @@ public final class ReflectUtils {
         return unmodifiableSet(hierarchicalTypes);
     }
 
+    /**
+     * Get the value from the specified bean and its property.
+     *
+     * @param bean         the bean instance
+     * @param propertyName the name of property
+     * @param <T>          the type of property value
+     * @return
+     * @since 2.7.5
+     */
     public static <T> T getProperty(Object bean, String propertyName) {
         Class<?> beanClass = bean.getClass();
         BeanInfo beanInfo = null;
@@ -1282,4 +1292,28 @@ public final class ReflectUtils {
         return propertyValue;
     }
 
+    /**
+     * Resolve the types of the specified values
+     *
+     * @param values the values
+     * @return If can't be resolved, return {@link ReflectUtils#EMPTY_CLASS_ARRAY empty class array}
+     * @since 2.7.6
+     */
+    public static Class[] resolveTypes(Object... values) {
+
+        if (isEmpty(values)) {
+            return EMPTY_CLASS_ARRAY;
+        }
+
+        int size = values.length;
+
+        Class[] types = new Class[size];
+
+        for (int i = 0; i < size; i++) {
+            Object value = values[i];
+            types[i] = value == null ? null : value.getClass();
+        }
+
+        return types;
+    }
 }
\ No newline at end of file
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
new file mode 100644
index 0000000..58e5e7a
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ServiceAnnotationResolver.java
@@ -0,0 +1,119 @@
+/*
+ * 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.utils;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import java.lang.annotation.Annotation;
+
+import static java.lang.String.format;
+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;
+import static org.apache.dubbo.common.utils.ClassUtils.resolveClass;
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+
+/**
+ * The resolver class for {@link Service @Service}
+ *
+ * @see Service
+ * @see com.alibaba.dubbo.config.annotation.Service
+ * @since 2.7.6
+ */
+public class ServiceAnnotationResolver {
+
+    private final Annotation serviceAnnotation;
+
+    private final Class<?> serviceType;
+
+    public ServiceAnnotationResolver(Class<?> serviceType) throws IllegalArgumentException {
+        this.serviceType = serviceType;
+        this.serviceAnnotation = getServiceAnnotation(serviceType);
+    }
+
+    private Annotation getServiceAnnotation(Class<?> serviceType) {
+
+        Annotation serviceAnnotation = serviceType.getAnnotation(Service.class);
+
+        if (serviceAnnotation == null) {
+            serviceAnnotation = serviceType.getAnnotation(com.alibaba.dubbo.config.annotation.Service.class);
+        }
+
+        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(),
+                    serviceType.getName()
+            ));
+        }
+
+        return serviceAnnotation;
+    }
+
+    /**
+     * Resolve the class name of interface
+     *
+     * @return if not found, return <code>null</code>
+     */
+    public String resolveInterfaceClassName() {
+
+        Class interfaceClass = null;
+        // first, try to get the value from "interfaceName" attribute
+        String interfaceName = resolveAttribute("interfaceName");
+
+        if (isEmpty(interfaceName)) { // If not found, try "interfaceClass"
+            interfaceClass = resolveAttribute("interfaceClass");
+        } else {
+            interfaceClass = resolveClass(interfaceName, getClass().getClassLoader());
+        }
+
+        if (isGenericClass(interfaceClass)) {
+            interfaceName = interfaceClass.getName();
+        } else {
+            interfaceName = null;
+        }
+
+        if (isEmpty(interfaceName)) { // If not fund, try to get the first interface from the service type
+            Class[] interfaces = serviceType.getInterfaces();
+            if (isNotEmpty(interfaces)) {
+                interfaceName = interfaces[0].getName();
+            }
+        }
+
+        return interfaceName;
+    }
+
+    public String resolveVersion() {
+        return resolveAttribute("version");
+    }
+
+    public String resolveGroup() {
+        return resolveAttribute("group");
+    }
+
+    private <T> T resolveAttribute(String attributeName) {
+        return getAttribute(serviceAnnotation, attributeName);
+    }
+
+    public Annotation getServiceAnnotation() {
+        return serviceAnnotation;
+    }
+
+    public Class<?> getServiceType() {
+        return serviceType;
+    }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/TypeUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/TypeUtils.java
new file mode 100644
index 0000000..2e53296
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/TypeUtils.java
@@ -0,0 +1,224 @@
+/*
+ * 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.utils;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.unmodifiableList;
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.Collectors.toSet;
+import static java.util.stream.StreamSupport.stream;
+import static org.apache.dubbo.common.function.Predicates.and;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterList;
+import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
+import static org.apache.dubbo.common.utils.ClassUtils.getAllSuperClasses;
+import static org.apache.dubbo.common.utils.ClassUtils.isAssignableFrom;
+
+/**
+ * The utilities class for {@link Type}
+ *
+ * @since 2.7.6
+ */
+public interface TypeUtils {
+
+    Predicate<Class<?>> NON_OBJECT_TYPE_FILTER = t -> !Objects.equals(Object.class, t);
+
+    static boolean isParameterizedType(Type type) {
+        return type instanceof ParameterizedType;
+    }
+
+    static Type getRawType(Type type) {
+        if (isParameterizedType(type)) {
+            return ((ParameterizedType) type).getRawType();
+        } else {
+            return type;
+        }
+    }
+
+    static Class<?> getRawClass(Type type) {
+        Type rawType = getRawType(type);
+        if (isClass(rawType)) {
+            return (Class) rawType;
+        }
+        return null;
+    }
+
+    static boolean isClass(Type type) {
+        return type instanceof Class;
+    }
+
+    static <T> Class<T> findActualTypeArgument(Type type, Class<?> interfaceClass, int index) {
+        return (Class<T>) findActualTypeArguments(type, interfaceClass).get(index);
+    }
+
+    static List<Class<?>> findActualTypeArguments(Type type, Class<?> interfaceClass) {
+
+        List<Class<?>> actualTypeArguments = new LinkedList<>();
+
+        getAllGenericTypes(type, t -> isAssignableFrom(interfaceClass, getRawClass(t)))
+                .forEach(parameterizedType -> {
+                    Class<?> rawClass = getRawClass(parameterizedType);
+                    Type[] typeArguments = parameterizedType.getActualTypeArguments();
+                    for (int i = 0; i < typeArguments.length; i++) {
+                        Type typeArgument = typeArguments[i];
+                        if (typeArgument instanceof Class) {
+                            actualTypeArguments.add(i, (Class) typeArgument);
+                        }
+                    }
+                    Class<?> superClass = rawClass.getSuperclass();
+                    if (superClass != null) {
+                        actualTypeArguments.addAll(findActualTypeArguments(superClass, interfaceClass));
+                    }
+                });
+
+        return unmodifiableList(actualTypeArguments);
+    }
+
+    /**
+     * Get the specified types' generic types(including super classes and interfaces) that are assignable from {@link ParameterizedType} interface
+     *
+     * @param type        the specified type
+     * @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
+     * @return non-null read-only {@link List}
+     */
+    static List<ParameterizedType> getGenericTypes(Type type, Predicate<ParameterizedType>... typeFilters) {
+
+        Class<?> rawClass = getRawClass(type);
+
+        if (rawClass == null) {
+            return emptyList();
+        }
+
+        List<Type> genericTypes = new LinkedList<>();
+
+        genericTypes.add(rawClass.getGenericSuperclass());
+        genericTypes.addAll(asList(rawClass.getGenericInterfaces()));
+
+        return unmodifiableList(
+                filterList(genericTypes, TypeUtils::isParameterizedType)
+                        .stream()
+                        .map(ParameterizedType.class::cast)
+                        .filter(and(typeFilters))
+                        .collect(toList())
+        );
+    }
+
+    /**
+     * Get all generic types(including super classes and interfaces) that are assignable from {@link ParameterizedType} interface
+     *
+     * @param type        the specified type
+     * @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
+     * @return non-null read-only {@link List}
+     */
+    static List<ParameterizedType> getAllGenericTypes(Type type, Predicate<ParameterizedType>... typeFilters) {
+        List<ParameterizedType> allGenericTypes = new LinkedList<>();
+        // Add generic super classes
+        allGenericTypes.addAll(getAllGenericSuperClasses(type, typeFilters));
+        // Add generic super interfaces
+        allGenericTypes.addAll(getAllGenericInterfaces(type, typeFilters));
+        // wrap unmodifiable object
+        return unmodifiableList(allGenericTypes);
+    }
+
+    /**
+     * Get all generic super classes that are assignable from {@link ParameterizedType} interface
+     *
+     * @param type        the specified type
+     * @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
+     * @return non-null read-only {@link List}
+     */
+    static List<ParameterizedType> getAllGenericSuperClasses(Type type, Predicate<ParameterizedType>... typeFilters) {
+
+        Class<?> rawClass = getRawClass(type);
+
+        if (rawClass == null || rawClass.isInterface()) {
+            return emptyList();
+        }
+
+        List<Class<?>> allTypes = new LinkedList<>();
+        // Add current class
+        allTypes.add(rawClass);
+        // Add all super classes
+        allTypes.addAll(getAllSuperClasses(rawClass, NON_OBJECT_TYPE_FILTER));
+
+        List<ParameterizedType> allGenericSuperClasses = allTypes
+                .stream()
+                .map(Class::getGenericSuperclass)
+                .filter(TypeUtils::isParameterizedType)
+                .map(ParameterizedType.class::cast)
+                .collect(Collectors.toList());
+
+        return unmodifiableList(filterAll(allGenericSuperClasses, typeFilters));
+    }
+
+    /**
+     * Get all generic interfaces that are assignable from {@link ParameterizedType} interface
+     *
+     * @param type        the specified type
+     * @param typeFilters one or more {@link Predicate}s to filter the {@link ParameterizedType} instance
+     * @return non-null read-only {@link List}
+     */
+    static List<ParameterizedType> getAllGenericInterfaces(Type type, Predicate<ParameterizedType>... typeFilters) {
+
+        Class<?> rawClass = getRawClass(type);
+
+        if (rawClass == null) {
+            return emptyList();
+        }
+
+        List<Class<?>> allTypes = new LinkedList<>();
+        // Add current class
+        allTypes.add(rawClass);
+        // Add all super classes
+        allTypes.addAll(getAllSuperClasses(rawClass, NON_OBJECT_TYPE_FILTER));
+        // Add all super interfaces
+        allTypes.addAll(getAllInterfaces(rawClass));
+
+        List<ParameterizedType> allGenericInterfaces = allTypes
+                .stream()
+                .map(Class::getGenericInterfaces)
+                .map(Arrays::asList)
+                .flatMap(Collection::stream)
+                .filter(TypeUtils::isParameterizedType)
+                .map(ParameterizedType.class::cast)
+                .collect(toList());
+
+        return unmodifiableList(filterAll(allGenericInterfaces, typeFilters));
+    }
+
+    static String getClassName(Type type) {
+        return getRawType(type).getTypeName();
+    }
+
+    static Set<String> getClassNames(Iterable<? extends Type> types) {
+        return stream(types.spliterator(), false)
+                .map(TypeUtils::getClassName)
+                .collect(toSet());
+    }
+}
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.Converter b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.Converter
new file mode 100644
index 0000000..f1ad0cc
--- /dev/null
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.Converter
@@ -0,0 +1,11 @@
+# org.apache.dubbo.common.convert.Converter
+string-to-boolean=org.apache.dubbo.common.convert.StringToBooleanConverter
+string-to-character=org.apache.dubbo.common.convert.StringToCharacterConverter
+string-to-char-array=org.apache.dubbo.common.convert.StringToCharArrayConverter
+string-to-double=org.apache.dubbo.common.convert.StringToDoubleConverter
+string-to-float=org.apache.dubbo.common.convert.StringToFloatConverter
+string-to-integer=org.apache.dubbo.common.convert.StringToIntegerConverter
+string-to-long=org.apache.dubbo.common.convert.StringToLongConverter
+string-to-optional=org.apache.dubbo.common.convert.StringToOptionalConverter
+string-to-short=org.apache.dubbo.common.convert.StringToShortConverter
+string-to-string=org.apache.dubbo.common.convert.StringToStringConverter
\ No newline at end of file
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.multiple.MultiValueConverter b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.multiple.MultiValueConverter
new file mode 100644
index 0000000..d7f7692
--- /dev/null
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.convert.multiple.MultiValueConverter
@@ -0,0 +1,12 @@
+# org.apache.dubbo.common.convert.multiple.MultiValueConverter
+string-to-array=org.apache.dubbo.common.convert.multiple.StringToArrayConverter
+string-to-blocking-deque=org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter
+string-to-blocking-queue=org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter
+string-to-collection=org.apache.dubbo.common.convert.multiple.StringToCollectionConverter
+string-to-deque=org.apache.dubbo.common.convert.multiple.StringToDequeConverter
+string-to-list=org.apache.dubbo.common.convert.multiple.StringToListConverter
+string-to-navigable-set=org.apache.dubbo.common.convert.multiple.StringToNavigableSetConverter
+string-to-queue=org.apache.dubbo.common.convert.multiple.StringToQueueConverter
+string-to-set=org.apache.dubbo.common.convert.multiple.StringToSetConverter
+string-to-sorted-set=org.apache.dubbo.common.convert.multiple.StringToSortedSetConverter
+string-to-transfer-queue=org.apache.dubbo.common.convert.multiple.StringToTransferQueueConverter
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AnnotationUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AnnotationUtilsTest.java
new file mode 100644
index 0000000..0401763
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/AnnotationUtilsTest.java
@@ -0,0 +1,343 @@
+/*
+ * 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.utils;
+
+import org.apache.dubbo.common.extension.Adaptive;
+import org.apache.dubbo.config.annotation.Service;
+
+import org.junit.jupiter.api.Test;
+
+import java.lang.annotation.Annotation;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.utils.AnnotationUtils.excludedType;
+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.findMetaAnnotations;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getAllDeclaredAnnotations;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getAllMetaAnnotations;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getAnnotation;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getDeclaredAnnotations;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getMetaAnnotations;
+import static org.apache.dubbo.common.utils.AnnotationUtils.getValue;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isAnyAnnotationPresent;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isSameType;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isType;
+import static org.apache.dubbo.common.utils.MethodUtils.findMethod;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link AnnotationUtils} Test
+ *
+ * @since 2.7.6
+ */
+public class AnnotationUtilsTest {
+
+    @Test
+    public void testIsType() throws NoSuchMethodException {
+        // null checking
+        assertFalse(isType(null));
+        // Method checking
+        assertFalse(isType(findMethod(A.class, "execute")));
+        // Class checking
+        assertTrue(isType(A.class));
+    }
+
+    @Test
+    public void testIsSameType() {
+        assertTrue(isSameType(A.class.getAnnotation(Service.class), Service.class));
+        assertFalse(isSameType(A.class.getAnnotation(Service.class), Deprecated.class));
+        assertFalse(isSameType(A.class.getAnnotation(Service.class), null));
+        assertFalse(isSameType(null, Deprecated.class));
+        assertFalse(isSameType(null, null));
+    }
+
+    @Test
+    public void testExcludedType() {
+        assertFalse(excludedType(Service.class).test(A.class.getAnnotation(Service.class)));
+        assertTrue(excludedType(Service.class).test(A.class.getAnnotation(Deprecated.class)));
+    }
+
+    @Test
+    public void testGetAttribute() {
+        Annotation annotation = A.class.getAnnotation(Service.class);
+        assertEquals("java.lang.CharSequence", getAttribute(annotation, "interfaceName"));
+        assertEquals(CharSequence.class, getAttribute(annotation, "interfaceClass"));
+        assertEquals("", getAttribute(annotation, "version"));
+        assertEquals("", getAttribute(annotation, "group"));
+        assertEquals("", getAttribute(annotation, "path"));
+        assertEquals(true, getAttribute(annotation, "export"));
+        assertEquals(false, getAttribute(annotation, "deprecated"));
+    }
+
+    @Test
+    public void testGetValue() {
+        Adaptive adaptive = A.class.getAnnotation(Adaptive.class);
+        String[] value = getValue(adaptive);
+        assertEquals(asList("a", "b", "c"), asList(value));
+    }
+
+    @Test
+    public void testGetDeclaredAnnotations() {
+        List<Annotation> annotations = getDeclaredAnnotations(A.class);
+        assertADeclaredAnnotations(annotations, 0);
+
+        annotations = getDeclaredAnnotations(A.class, a -> isSameType(a, Service.class));
+        assertEquals(1, annotations.size());
+        Service service = (Service) annotations.get(0);
+        assertEquals("java.lang.CharSequence", service.interfaceName());
+        assertEquals(CharSequence.class, service.interfaceClass());
+    }
+
+    @Test
+    public void testGetAllDeclaredAnnotations() {
+        List<Annotation> annotations = getAllDeclaredAnnotations(A.class);
+        assertADeclaredAnnotations(annotations, 0);
+
+        annotations = getAllDeclaredAnnotations(B.class);
+        assertTrue(isSameType(annotations.get(0), Service5.class));
+        assertADeclaredAnnotations(annotations, 1);
+
+        annotations = new LinkedList<>(getAllDeclaredAnnotations(C.class));
+        assertTrue(isSameType(annotations.get(0), MyAdaptive.class));
+        assertTrue(isSameType(annotations.get(1), Service5.class));
+        assertADeclaredAnnotations(annotations, 2);
+
+        annotations = getAllDeclaredAnnotations(findMethod(A.class, "execute"));
+        MyAdaptive myAdaptive = (MyAdaptive) annotations.get(0);
+        assertArrayEquals(new String[]{"e"}, myAdaptive.value());
+
+        annotations = getAllDeclaredAnnotations(findMethod(B.class, "execute"));
+        Adaptive adaptive = (Adaptive) annotations.get(0);
+        assertArrayEquals(new String[]{"f"}, adaptive.value());
+    }
+
+    @Test
+    public void testGetMetaAnnotations() {
+        List<Annotation> metaAnnotations = getMetaAnnotations(Service.class, a -> isSameType(a, Inherited.class));
+        assertEquals(1, metaAnnotations.size());
+        assertEquals(Inherited.class, metaAnnotations.get(0).annotationType());
+
+        metaAnnotations = getMetaAnnotations(Service.class);
+        assertEquals(1, metaAnnotations.size());
+        assertEquals(Inherited.class, metaAnnotations.get(0).annotationType());
+    }
+
+    @Test
+    public void testGetAllMetaAnnotations() {
+        List<Annotation> metaAnnotations = getAllMetaAnnotations(Service5.class);
+        int offset = 0;
+        assertEquals(9, metaAnnotations.size());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Service4.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Service3.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Service2.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Service.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+
+        metaAnnotations = getAllMetaAnnotations(MyAdaptive.class);
+        offset = 0;
+        assertEquals(2, metaAnnotations.size());
+        assertEquals(Inherited.class, metaAnnotations.get(offset++).annotationType());
+        assertEquals(Adaptive.class, metaAnnotations.get(offset++).annotationType());
+    }
+
+
+    @Test
+    public void testIsAnnotationPresent() {
+        assertTrue(isAnnotationPresent(A.class, true, Service.class));
+        assertTrue(isAnnotationPresent(A.class, true, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
+        assertTrue(isAnnotationPresent(A.class, Service.class));
+        assertTrue(isAnnotationPresent(A.class, "org.apache.dubbo.config.annotation.Service"));
+        assertTrue(AnnotationUtils.isAllAnnotationPresent(A.class, Service.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
+        assertTrue(isAnnotationPresent(A.class, Deprecated.class));
+    }
+
+    @Test
+    public void testIsAnyAnnotationPresent() {
+        assertTrue(isAnyAnnotationPresent(A.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class, Deprecated.class));
+        assertTrue(isAnyAnnotationPresent(A.class, Service.class, com.alibaba.dubbo.config.annotation.Service.class));
+        assertTrue(isAnyAnnotationPresent(A.class, Service.class, Deprecated.class));
+        assertTrue(isAnyAnnotationPresent(A.class, com.alibaba.dubbo.config.annotation.Service.class, Deprecated.class));
+        assertTrue(isAnyAnnotationPresent(A.class, Service.class));
+        assertTrue(isAnyAnnotationPresent(A.class, com.alibaba.dubbo.config.annotation.Service.class));
+        assertTrue(isAnyAnnotationPresent(A.class, Deprecated.class));
+    }
+
+    @Test
+    public void testGetAnnotation() {
+        assertNotNull(getAnnotation(A.class, "org.apache.dubbo.config.annotation.Service"));
+        assertNotNull(getAnnotation(A.class, "com.alibaba.dubbo.config.annotation.Service"));
+        assertNotNull(getAnnotation(A.class, "org.apache.dubbo.common.extension.Adaptive"));
+        assertNull(getAnnotation(A.class, "java.lang.Deprecated"));
+        assertNull(getAnnotation(A.class, "java.lang.String"));
+        assertNull(getAnnotation(A.class, "NotExistedClass"));
+    }
+
+    @Test
+    public void testFindAnnotation() {
+        Service service = findAnnotation(A.class, Service.class);
+        assertEquals("java.lang.CharSequence", service.interfaceName());
+        assertEquals(CharSequence.class, service.interfaceClass());
+
+        service = findAnnotation(B.class, Service.class);
+        assertEquals(CharSequence.class, service.interfaceClass());
+    }
+
+    @Test
+    public void testFindMetaAnnotations() {
+        List<Service> services = findMetaAnnotations(B.class, Service.class);
+        assertEquals(1, services.size());
+
+        Service service = services.get(0);
+        assertEquals("", service.interfaceName());
+        assertEquals(Cloneable.class, service.interfaceClass());
+
+        services = findMetaAnnotations(Service5.class, Service.class);
+        assertEquals(1, services.size());
+
+        service = services.get(0);
+        assertEquals("", service.interfaceName());
+        assertEquals(Cloneable.class, service.interfaceClass());
+    }
+
+    @Test
+    public void testFindMetaAnnotation() {
+        Service service = findMetaAnnotation(B.class, Service.class);
+        assertEquals(Cloneable.class, service.interfaceClass());
+
+        service = findMetaAnnotation(B.class, "org.apache.dubbo.config.annotation.Service");
+        assertEquals(Cloneable.class, service.interfaceClass());
+
+        service = findMetaAnnotation(Service5.class, Service.class);
+        assertEquals(Cloneable.class, service.interfaceClass());
+    }
+
+    @Service(interfaceName = "java.lang.CharSequence", interfaceClass = CharSequence.class)
+    @com.alibaba.dubbo.config.annotation.Service(interfaceName = "java.lang.CharSequence", interfaceClass = CharSequence.class)
+    @Adaptive(value = {"a", "b", "c"})
+    static class A {
+
+        @MyAdaptive("e")
+        public void execute() {
+
+        }
+
+
+    }
+
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    @Inherited
+    @Service(interfaceClass = Cloneable.class)
+    @interface Service2 {
+
+
+    }
+
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    @Inherited
+    @Service2
+    @interface Service3 {
+
+
+    }
+
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    @Inherited
+    @Service3
+    @interface Service4 {
+
+
+    }
+
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE})
+    @Inherited
+    @Service4
+    @interface Service5 {
+
+
+    }
+
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.TYPE, ElementType.METHOD})
+    @Inherited
+    @Adaptive
+    @interface MyAdaptive {
+
+        String[] value() default {};
+
+    }
+
+    @Service5
+    static class B extends A {
+
+        @Adaptive("f")
+        @Override
+        public void execute() {
+
+        }
+
+
+    }
+
+    @MyAdaptive
+    static class C extends B {
+
+    }
+
+    private void assertADeclaredAnnotations(List<Annotation> annotations, int offset) {
+        int size = 3 + offset;
+        assertEquals(size, annotations.size());
+        Service service = (Service) annotations.get(offset++);
+        assertEquals("java.lang.CharSequence", service.interfaceName());
+        assertEquals(CharSequence.class, service.interfaceClass());
+
+        com.alibaba.dubbo.config.annotation.Service s = (com.alibaba.dubbo.config.annotation.Service) annotations.get(offset++);
+        assertEquals("java.lang.CharSequence", service.interfaceName());
+        assertEquals(CharSequence.class, service.interfaceClass());
+
+        Adaptive adaptive = (Adaptive) annotations.get(offset++);
+        assertArrayEquals(new String[]{"a", "b", "c"}, adaptive.value());
+    }
+}
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
new file mode 100644
index 0000000..051363b
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/MemberUtilsTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.utils;
+
+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
+ *
+ * @since 2.7.6
+ */
+public class MemberUtilsTest {
+
+    @Test
+    public void testIsStatic() throws NoSuchMethodException {
+
+        assertFalse(isStatic(getClass().getMethod("testIsStatic")));
+        assertTrue(isStatic(getClass().getMethod("staticMethod")));
+    }
+
+    public static void staticMethod() {
+
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.java
new file mode 100644
index 0000000..3b1d75b
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToBooleanConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToBooleanConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToBooleanConverterTest {
+
+    private StringToBooleanConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToBooleanConverter) getExtensionLoader(Converter.class).getExtension("string-to-boolean");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Boolean.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertTrue(converter.convert("true"));
+        assertTrue(converter.convert("true"));
+        assertTrue(converter.convert("True"));
+        assertFalse(converter.convert("a"));
+        assertNull(converter.convert(""));
+        assertNull(converter.convert(null));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java
new file mode 100644
index 0000000..492a129
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToCharArrayConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToCharArrayConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToCharArrayConverterTest {
+
+    private StringToCharArrayConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter =  (StringToCharArrayConverter) getExtensionLoader(Converter.class).getExtension("string-to-char-array");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, char[].class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertArrayEquals(new char[]{'1', '2', '3'}, converter.convert("123"));
+        assertNull(converter.convert(null));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.java
new file mode 100644
index 0000000..c9e88c2
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToCharacterConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToCharacterConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToCharacterConverterTest {
+
+    private StringToCharacterConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToCharacterConverter) getExtensionLoader(Converter.class).getExtension("string-to-character");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Character.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals('t', converter.convert("t"));
+        assertNull(converter.convert(null));
+        assertThrows(IllegalArgumentException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.java
new file mode 100644
index 0000000..668f3e6
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToDoubleConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToDoubleConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToDoubleConverterTest {
+
+    private StringToDoubleConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToDoubleConverter) getExtensionLoader(Converter.class).getExtension("string-to-double");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Double.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Double.valueOf("1.0"), converter.convert("1.0"));
+        assertNull(converter.convert(null));
+        assertThrows(NumberFormatException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.java
new file mode 100644
index 0000000..aa17499
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToFloatConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToFloatConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToFloatConverterTest {
+
+    private StringToFloatConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToFloatConverter) getExtensionLoader(Converter.class).getExtension("string-to-float");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Float.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Float.valueOf("1.0"), converter.convert("1.0"));
+        assertNull(converter.convert(null));
+        assertThrows(NumberFormatException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.java
new file mode 100644
index 0000000..9c7d24b
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToIntegerConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToIntegerConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToIntegerConverterTest {
+
+    private StringToIntegerConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToIntegerConverter) getExtensionLoader(Converter.class).getExtension("string-to-integer");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Integer.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Integer.valueOf("1"), converter.convert("1"));
+        assertNull(converter.convert(null));
+        assertThrows(NumberFormatException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.java
new file mode 100644
index 0000000..e14424a
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToLongConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToLongConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToLongConverterTest {
+
+    private StringToLongConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToLongConverter) getExtensionLoader(Converter.class).getExtension("string-to-long");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Long.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Long.valueOf("1"), converter.convert("1"));
+        assertNull(converter.convert(null));
+        assertThrows(NumberFormatException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
new file mode 100644
index 0000000..242ae60
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToOptionalConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.Optional;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToOptionalConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToOptionalConverterTest {
+
+    private StringToOptionalConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToOptionalConverter) getExtensionLoader(Converter.class).getExtension("string-to-optional");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Optional.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Optional.of("1"), converter.convert("1"));
+        assertEquals(Optional.empty(), converter.convert(null));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.java
new file mode 100644
index 0000000..3f1d493
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToShortConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToShortConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToShortConverterTest {
+
+    private StringToShortConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToShortConverter) getExtensionLoader(Converter.class).getExtension("string-to-short");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, Short.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals(Short.valueOf("1"), converter.convert("1"));
+        assertNull(converter.convert(null));
+        assertThrows(NumberFormatException.class, () -> {
+            converter.convert("ttt");
+        });
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
new file mode 100644
index 0000000..57806c3
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
@@ -0,0 +1,54 @@
+/*
+ * 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.convert;
+
+import org.apache.dubbo.common.convert.Converter;
+import org.apache.dubbo.common.convert.StringToStringConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToStringConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToStringConverterTest {
+
+    private StringToStringConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = (StringToStringConverter) getExtensionLoader(Converter.class).getExtension("string-to-string");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, String.class));
+    }
+
+    @Test
+    public void testConvert() {
+        assertEquals("1", converter.convert("1"));
+        assertNull(converter.convert(null));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java
new file mode 100644
index 0000000..1781356
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java
@@ -0,0 +1,70 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.StringToArrayConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Objects.deepEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToArrayConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToArrayConverterTest {
+
+    private StringToArrayConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = new StringToArrayConverter();
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(converter.accept(String.class, char[].class));
+        assertTrue(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+        assertTrue(deepEquals(new Integer[]{123}, converter.convert("123", Integer[].class, Integer.class)));
+        assertTrue(deepEquals(new Integer[]{1, 2, 3}, converter.convert("1,2,3", Integer[].class, null)));
+        assertNull(converter.convert("", Integer[].class, null));
+        assertNull(converter.convert(null, Integer[].class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java
new file mode 100644
index 0000000..6f9597d
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToBlockingDequeConverter} Test
+ *
+ * @see BlockingDeque
+ * @since 2.7.6
+ */
+public class StringToBlockingDequeConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-blocking-deque");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertTrue(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() throws NoSuchFieldException {
+
+        BlockingQueue<Integer> values = new LinkedBlockingDeque(asList(1, 2, 3));
+
+        BlockingDeque<Integer> result = (BlockingDeque<Integer>) converter.convert("1,2,3", BlockingDeque.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values = new LinkedBlockingDeque(asList(123));
+
+        result = (BlockingDeque<Integer>) converter.convert("123", BlockingDeque.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, null));
+        assertNull(converter.convert("", Collection.class, null));
+
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 5, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java
new file mode 100644
index 0000000..4fa7532
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java
@@ -0,0 +1,125 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToBlockingQueueConverter} Test
+ *
+ * @see BlockingDeque
+ * @since 2.7.6
+ */
+public class StringToBlockingQueueConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-blocking-queue");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertTrue(converter.accept(String.class, BlockingQueue.class));
+        assertTrue(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertTrue(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        BlockingQueue values = new ArrayBlockingQueue(3);
+        values.offer(1);
+        values.offer(2);
+        values.offer(3);
+
+        BlockingQueue<Integer> result = (BlockingQueue<Integer>) converter.convert("1,2,3", BlockingDeque.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values.clear();
+        values.offer(123);
+
+        result = (BlockingQueue<Integer>) converter.convert("123", BlockingDeque.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, null));
+        assertNull(converter.convert("", Collection.class, null));
+
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java
new file mode 100644
index 0000000..f0b06ec
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToCollectionConverter;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToCollectionConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToCollectionConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-collection");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertTrue(converter.accept(String.class, Collection.class));
+
+        assertTrue(converter.accept(String.class, List.class));
+        assertTrue(converter.accept(String.class, AbstractList.class));
+        assertTrue(converter.accept(String.class, ArrayList.class));
+        assertTrue(converter.accept(String.class, LinkedList.class));
+
+        assertTrue(converter.accept(String.class, Set.class));
+        assertTrue(converter.accept(String.class, SortedSet.class));
+        assertTrue(converter.accept(String.class, NavigableSet.class));
+        assertTrue(converter.accept(String.class, TreeSet.class));
+        assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertTrue(converter.accept(String.class, Queue.class));
+        assertTrue(converter.accept(String.class, BlockingQueue.class));
+        assertTrue(converter.accept(String.class, TransferQueue.class));
+        assertTrue(converter.accept(String.class, Deque.class));
+        assertTrue(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        List values = asList(1L, 2L, 3L);
+
+        Collection result = (Collection<Long>) converter.convert("1,2,3", Collection.class, Long.class);
+
+        assertEquals(values, result);
+
+        values = asList(123);
+
+        result = (Collection<Integer>) converter.convert("123", Collection.class, Integer.class);
+
+        assertEquals(values, result);
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, Integer.class));
+
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 1, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java
new file mode 100644
index 0000000..e810092
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToDequeConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToDequeConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToDequeConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-deque");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertTrue(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertTrue(converter.accept(String.class, Deque.class));
+        assertTrue(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        Deque values = new ArrayDeque(asList(1, 2, 3));
+
+        Deque result = (Deque) converter.convert("1,2,3", Deque.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values = new ArrayDeque(asList("123"));
+
+        result = (Deque) converter.convert("123", Deque.class, String.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java
new file mode 100644
index 0000000..af9ee91
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToListConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToListConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToListConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-list");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertTrue(converter.accept(String.class, List.class));
+        assertTrue(converter.accept(String.class, AbstractList.class));
+        assertTrue(converter.accept(String.class, LinkedList.class));
+        assertTrue(converter.accept(String.class, ArrayList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertFalse(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        List values = asList(1, 2, 3);
+
+        List result = (List<Integer>) converter.convert("1,2,3", List.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values = asList("123");
+
+        result = (List<String>) converter.convert("123", List.class, String.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java
new file mode 100644
index 0000000..face60d
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToListConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToListConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToNavigableSetConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-navigable-set");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertTrue(converter.accept(String.class, NavigableSet.class));
+        assertTrue(converter.accept(String.class, TreeSet.class));
+        assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertFalse(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        Set values = new TreeSet(asList(1, 2, 3));
+
+        NavigableSet result = (NavigableSet) converter.convert("1,2,3", List.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values = new TreeSet(asList("123"));
+
+        result = (NavigableSet) converter.convert("123", NavigableSet.class, String.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 4, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java
new file mode 100644
index 0000000..539693a
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.StringToQueueConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToQueueConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToQueueConverterTest {
+
+    private StringToQueueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = new StringToQueueConverter();
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertTrue(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertTrue(converter.accept(String.class, Queue.class));
+        assertTrue(converter.accept(String.class, BlockingQueue.class));
+        assertTrue(converter.accept(String.class, TransferQueue.class));
+        assertTrue(converter.accept(String.class, Deque.class));
+        assertTrue(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        Queue values = new ArrayDeque(asList(1.0, 2.0, 3.0));
+
+        Queue result = (Queue<Double>) converter.convert("1.0,2.0,3.0", Queue.class, Double.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values.clear();
+        values.add(123);
+
+        result = (Queue) converter.convert("123", Queue.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java
new file mode 100644
index 0000000..269d709
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.StringToSetConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToSetConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToSetConverterTest {
+
+    private StringToSetConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = new StringToSetConverter();
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertTrue(converter.accept(String.class, Set.class));
+        assertTrue(converter.accept(String.class, SortedSet.class));
+        assertTrue(converter.accept(String.class, NavigableSet.class));
+        assertTrue(converter.accept(String.class, TreeSet.class));
+        assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertFalse(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+        Set values = new HashSet(asList(1.0, 2.0, 3.0));
+
+        Set result = (Set<Double>) converter.convert("1.0,2.0,3.0", Queue.class, Double.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values.clear();
+        values.add(123);
+
+        result = (Set) converter.convert("123", Queue.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 2, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java
new file mode 100644
index 0000000..6af8f9d
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToListConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToListConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToSortedSetConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-sorted-set");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertTrue(converter.accept(String.class, SortedSet.class));
+        assertTrue(converter.accept(String.class, NavigableSet.class));
+        assertTrue(converter.accept(String.class, TreeSet.class));
+        assertTrue(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, TransferQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertFalse(converter.accept(String.class, BlockingDeque.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        Set values = new TreeSet(asList(1, 2, 3));
+
+        SortedSet result = (SortedSet) converter.convert("1,2,3", List.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values = new TreeSet(asList("123"));
+
+        result = (SortedSet) converter.convert("123", NavigableSet.class, String.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 3, converter.getPriority());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java
new file mode 100644
index 0000000..4d8d66b
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.convert.multiple;
+
+import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
+import org.apache.dubbo.common.convert.multiple.StringToListConverter;
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.AbstractList;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Deque;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.concurrent.LinkedTransferQueue;
+import java.util.concurrent.TransferQueue;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link StringToListConverter} Test
+ *
+ * @since 2.7.6
+ */
+public class StringToTransferQueueConverterTest {
+
+    private MultiValueConverter converter;
+
+    @BeforeEach
+    public void init() {
+        converter = getExtensionLoader(MultiValueConverter.class).getExtension("string-to-transfer-queue");
+    }
+
+    @Test
+    public void testAccept() {
+
+        assertFalse(converter.accept(String.class, Collection.class));
+
+        assertFalse(converter.accept(String.class, List.class));
+        assertFalse(converter.accept(String.class, AbstractList.class));
+        assertFalse(converter.accept(String.class, LinkedList.class));
+        assertFalse(converter.accept(String.class, ArrayList.class));
+
+        assertFalse(converter.accept(String.class, Set.class));
+        assertFalse(converter.accept(String.class, SortedSet.class));
+        assertFalse(converter.accept(String.class, NavigableSet.class));
+        assertFalse(converter.accept(String.class, TreeSet.class));
+        assertFalse(converter.accept(String.class, ConcurrentSkipListSet.class));
+
+        assertFalse(converter.accept(String.class, Queue.class));
+        assertFalse(converter.accept(String.class, BlockingQueue.class));
+        assertFalse(converter.accept(String.class, Deque.class));
+        assertFalse(converter.accept(String.class, BlockingDeque.class));
+        assertTrue(converter.accept(String.class, TransferQueue.class));
+
+        assertFalse(converter.accept(null, char[].class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, String.class));
+        assertFalse(converter.accept(null, null));
+    }
+
+    @Test
+    public void testConvert() {
+
+        TransferQueue values = new LinkedTransferQueue(asList(1, 2, 3));
+
+        TransferQueue result = (TransferQueue) converter.convert("1,2,3", List.class, Integer.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        values.clear();
+
+        values.addAll(asList("123"));
+
+        result = (TransferQueue) converter.convert("123", NavigableSet.class, String.class);
+
+        assertTrue(CollectionUtils.equals(values, result));
+
+        assertNull(converter.convert(null, Collection.class, Integer.class));
+        assertNull(converter.convert("", Collection.class, null));
+    }
+
+    @Test
+    public void testGetSourceType() {
+        assertEquals(String.class, converter.getSourceType());
+    }
+
+    @Test
+    public void testGetPriority() {
+        assertEquals(Integer.MAX_VALUE - 4, converter.getPriority());
+    }
+}
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 09d62cc..ec9a08e 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
@@ -34,7 +34,6 @@ import org.apache.dubbo.service.DemoService;
 import org.apache.dubbo.service.DemoServiceImpl;
 
 import com.alibaba.fastjson.JSON;
-
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
 
@@ -184,7 +183,7 @@ public class GenericServiceTest {
             }
         }
         Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
-        Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String, java.lang.String>");
+        Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
         Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), "org.apache.dubbo.service.ComplexObject$InnerObject");
         Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
         Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index bc63e4d..f826f85 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -38,8 +38,7 @@ import org.springframework.context.ApplicationEventPublisherAware;
  * @export
  */
 public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean, DisposableBean,
-        ApplicationContextAware, BeanNameAware,
-        ApplicationEventPublisherAware {
+        ApplicationContextAware, BeanNameAware, ApplicationEventPublisherAware {
 
 
     private static final long serialVersionUID = 213195494150089726L;
diff --git a/dubbo-metadata/dubbo-metadata-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml
index 8c9a80c..fe6a20c 100644
--- a/dubbo-metadata/dubbo-metadata-api/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-api/pom.xml
@@ -64,6 +64,20 @@
             <scope>test</scope>
         </dependency>
 
+        <!-- JAX-RS API -->
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Spring Web MVC -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</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/definition/MethodDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/MethodDefinitionBuilder.java
new file mode 100644
index 0000000..e7c18e6
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/MethodDefinitionBuilder.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.definition;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * {@link MethodDefinition} Builder based on Java Reflection
+ *
+ * @since 2.7.6
+ */
+public class MethodDefinitionBuilder {
+
+    private final TypeDefinitionBuilder builder;
+
+    public MethodDefinitionBuilder(TypeDefinitionBuilder builder) {
+        this.builder = builder;
+    }
+
+    public MethodDefinitionBuilder() {
+        this.builder = new TypeDefinitionBuilder();
+    }
+
+    /**
+     * Build the instance of {@link MethodDefinition}
+     *
+     * @param method {@link Method}
+     * @return non-null
+     */
+    public MethodDefinition build(Method method) {
+
+        MethodDefinition md = new MethodDefinition();
+        md.setName(method.getName());
+
+        // Process the parameters
+        Class<?>[] paramTypes = method.getParameterTypes();
+        Type[] genericParamTypes = method.getGenericParameterTypes();
+
+        int paramSize = paramTypes.length;
+        String[] parameterTypes = new String[paramSize];
+        List<TypeDefinition> parameters = new ArrayList<>(paramSize);
+        for (int i = 0; i < paramSize; i++) {
+            TypeDefinition parameter = builder.build(genericParamTypes[i], paramTypes[i]);
+            parameterTypes[i] = parameter.getType();
+            parameters.add(parameter);
+        }
+
+        md.setParameterTypes(parameterTypes);
+        md.setParameters(parameters);
+
+        // Process return type.
+        TypeDefinition td = builder.build(method.getGenericReturnType(), method.getReturnType());
+        md.setReturnType(td.getType());
+
+        return md;
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
index b9f68e9..d1275e7 100755
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
@@ -29,6 +29,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import static org.apache.dubbo.common.utils.ClassUtils.isSimpleType;
+
 /**
  * 2015/1/27.
  */
@@ -55,7 +57,7 @@ public class TypeDefinitionBuilder {
             td = DefaultTypeBuilder.build(clazz, typeCache);
             td.setTypeBuilderName(DefaultTypeBuilder.class.getName());
         }
-        if (clazz.equals(String.class)) {
+        if (isSimpleType(clazz)) { // changed since 2.7.6
             td.setProperties(null);
         }
         return td;
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 a207082..4fd3865 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
@@ -25,6 +25,11 @@ 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;
+
 /**
  * 2015/1/27.
  */
@@ -46,23 +51,37 @@ public class MapTypeBuilder implements TypeBuilder {
 
         ParameterizedType parameterizedType = (ParameterizedType) type;
         Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
-        if (actualTypeArgs == null || actualTypeArgs.length != 2) {
+        int actualTypeArgsLength = actualTypeArgs == null ? 0 : actualTypeArgs.length;
+
+        if (actualTypeArgsLength != 2) {
             throw new IllegalArgumentException(MessageFormat.format(
                     "[ServiceDefinitionBuilder] Map type [{0}] with unexpected amount of arguments [{1}]."
                             + Arrays.toString(actualTypeArgs), type, actualTypeArgs));
         }
 
-        for (Type actualType : actualTypeArgs) {
-            if (actualType instanceof ParameterizedType) {
+        // 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 = replace(type.toString(), ", ", ",");
+
+        TypeDefinition typeDefinition = new TypeDefinition(mapType);
+
+        for (int i = 0; i < actualTypeArgsLength; i++) {
+            Type actualType = actualTypeArgs[i];
+            TypeDefinition item = null;
+            Class<?> rawType = getRawClass(actualType);
+            if (isParameterizedType(actualType)) {
                 // Nested collection or map.
-                Class<?> rawType = (Class<?>) ((ParameterizedType) actualType).getRawType();
-                TypeDefinitionBuilder.build(actualType, rawType, typeCache);
-            } else if (actualType instanceof Class<?>) {
-                Class<?> actualClass = (Class<?>) actualType;
-                TypeDefinitionBuilder.build(null, actualClass, typeCache);
+                item = TypeDefinitionBuilder.build(actualType, rawType, typeCache);
+            } else if (isClass(actualType)) {
+                item = TypeDefinitionBuilder.build(null, rawType, typeCache);
             }
+            typeDefinition.getItems().add(item);
         }
 
-        return new TypeDefinition(type.toString());
+        return typeDefinition;
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractAnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractAnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..a168f0f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractAnnotatedMethodParameterProcessor.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.metadata.rest;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+import static org.apache.dubbo.common.utils.AnnotationUtils.getValue;
+import static org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation
+ *
+ * @since 2.7.6
+ */
+public abstract class AbstractAnnotatedMethodParameterProcessor implements AnnotatedMethodParameterProcessor {
+
+    @Override
+    public void process(Annotation annotation, Parameter parameter, int parameterIndex, Method method,
+                        Class<?> serviceType, Class<?> serviceInterfaceClass, RestMethodMetadata restMethodMetadata) {
+        String annotationValue = getAnnotationValue(annotation, parameter, parameterIndex);
+        String defaultValue = getDefaultValue(annotation, parameter, parameterIndex);
+        process(annotationValue, defaultValue, annotation, parameter, parameterIndex, method, restMethodMetadata);
+    }
+
+    protected String getAnnotationValue(Annotation annotation, Parameter parameter, int parameterIndex) {
+        return getValue(annotation);
+    }
+
+    protected String getDefaultValue(Annotation annotation, Parameter parameter, int parameterIndex) {
+        return buildDefaultValue(parameterIndex);
+    }
+
+    protected abstract void process(String annotationValue, String defaultValue, Annotation annotation, Object parameter,
+                                    int parameterIndex, Method method, RestMethodMetadata restMethodMetadata);
+}
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
new file mode 100644
index 0000000..ea07421
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AbstractServiceRestMetadataResolver.java
@@ -0,0 +1,341 @@
+/*
+ * 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.metadata.rest;
+
+import org.apache.dubbo.common.utils.MethodComparator;
+import org.apache.dubbo.common.utils.ServiceAnnotationResolver;
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.metadata.definition.MethodDefinitionBuilder;
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.sort;
+import static java.util.Collections.unmodifiableMap;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.function.ThrowableFunction.execute;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isAnyAnnotationPresent;
+import static org.apache.dubbo.common.utils.ClassUtils.forName;
+import static org.apache.dubbo.common.utils.ClassUtils.getAllInterfaces;
+import static org.apache.dubbo.common.utils.MethodUtils.excludedDeclaredClass;
+import static org.apache.dubbo.common.utils.MethodUtils.getAllMethods;
+import static org.apache.dubbo.common.utils.MethodUtils.overrides;
+
+/**
+ * The abstract {@link ServiceRestMetadataResolver} class to provider some template methods assemble the instance of
+ * {@link ServiceRestMetadata} will extended by the sub-classes.
+ *
+ * @since 2.7.6
+ */
+public abstract class AbstractServiceRestMetadataResolver implements ServiceRestMetadataResolver {
+
+    private final Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap;
+
+    public AbstractServiceRestMetadataResolver() {
+        this.parameterProcessorsMap = loadAnnotatedMethodParameterProcessors();
+    }
+
+    @Override
+    public final boolean supports(Class<?> serviceType) {
+        return isImplementedInterface(serviceType) && isServiceAnnotationPresent(serviceType) && supports0(serviceType);
+    }
+
+    protected final boolean isImplementedInterface(Class<?> serviceType) {
+        return !getAllInterfaces(serviceType).isEmpty();
+    }
+
+    protected final boolean isServiceAnnotationPresent(Class<?> serviceType) {
+        return isAnyAnnotationPresent(serviceType, Service.class, com.alibaba.dubbo.config.annotation.Service.class);
+    }
+
+    /**
+     * internal support method
+     *
+     * @param serviceType Dubbo Service interface or type
+     * @return If supports, return <code>true</code>, or <code>false</code>
+     */
+    protected abstract boolean supports0(Class<?> serviceType);
+
+    @Override
+    public final ServiceRestMetadata resolve(Class<?> serviceType) {
+
+        ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata();
+
+        // Process ServiceRestMetadata
+        processServiceRestMetadata(serviceRestMetadata, serviceType);
+
+        // Process RestMethodMetadata
+        processAllRestMethodMetadata(serviceRestMetadata, serviceType);
+
+        return serviceRestMetadata;
+    }
+
+    /**
+     * Process the service type including the sub-routines:
+     * <ul>
+     *     <li>{@link ServiceRestMetadata#setServiceInterface(String)}</li>
+     *     <li>{@link ServiceRestMetadata#setVersion(String)}</li>
+     *     <li>{@link ServiceRestMetadata#setGroup(String)}</li>
+     * </ul>
+     *
+     * @param serviceRestMetadata {@link ServiceRestMetadata}
+     * @param serviceType         Dubbo Service interface or type
+     */
+    protected void processServiceRestMetadata(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
+        ServiceAnnotationResolver resolver = new ServiceAnnotationResolver(serviceType);
+        serviceRestMetadata.setServiceInterface(resolver.resolveInterfaceClassName());
+        serviceRestMetadata.setVersion(resolver.resolveVersion());
+        serviceRestMetadata.setGroup(resolver.resolveGroup());
+    }
+
+    /**
+     * Process all {@link RestMethodMetadata}
+     *
+     * @param serviceRestMetadata {@link ServiceRestMetadata}
+     * @param serviceType         Dubbo Service interface or type
+     */
+    protected void processAllRestMethodMetadata(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
+        Class<?> serviceInterfaceClass = resolveServiceInterfaceClass(serviceRestMetadata, serviceType);
+        Map<Method, Method> serviceMethodsMap = resolveServiceMethodsMap(serviceType, serviceInterfaceClass);
+        for (Map.Entry<Method, Method> entry : serviceMethodsMap.entrySet()) {
+            // try the overrider method first
+            Method serviceMethod = entry.getKey();
+            // If failed, it indicates the overrider method does not contain metadata , then try the declared method
+            if (!processRestMethodMetadata(serviceMethod, serviceType, serviceInterfaceClass, serviceRestMetadata.getMeta()::add)) {
+                Method declaredServiceMethod = entry.getValue();
+                processRestMethodMetadata(declaredServiceMethod, serviceType, serviceInterfaceClass,
+                        serviceRestMetadata.getMeta()::add);
+            }
+        }
+    }
+
+    /**
+     * Resolve a map of all public services methods from the specified service type and its interface class, whose key is the
+     * declared method, and the value is the overrider method
+     *
+     * @param serviceType           the service interface implementation class
+     * @param serviceInterfaceClass the service interface class
+     * @return non-null read-only {@link Map}
+     */
+    protected Map<Method, Method> resolveServiceMethodsMap(Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        Map<Method, Method> serviceMethodsMap = new LinkedHashMap<>();
+        // exclude the public methods declared in java.lang.Object.class
+        List<Method> declaredServiceMethods = new ArrayList<>(getAllMethods(serviceInterfaceClass, excludedDeclaredClass(Object.class)));
+        List<Method> serviceMethods = new ArrayList<>(getAllMethods(serviceType, excludedDeclaredClass(Object.class)));
+
+        // sort methods
+        sort(declaredServiceMethods, MethodComparator.INSTANCE);
+        sort(serviceMethods, MethodComparator.INSTANCE);
+
+        for (Method declaredServiceMethod : declaredServiceMethods) {
+            for (Method serviceMethod : serviceMethods) {
+                if (overrides(serviceMethod, declaredServiceMethod)) {
+                    serviceMethodsMap.put(serviceMethod, declaredServiceMethod);
+                    continue;
+                }
+            }
+        }
+        // make them to be read-only
+        return unmodifiableMap(serviceMethodsMap);
+    }
+
+    /**
+     * Resolve the class of Dubbo Service interface
+     *
+     * @param serviceRestMetadata {@link ServiceRestMetadata}
+     * @param serviceType         Dubbo Service interface or type
+     * @return non-null
+     * @throws RuntimeException If the class is not found, the {@link RuntimeException} wraps the cause will be thrown
+     */
+    protected Class<?> resolveServiceInterfaceClass(ServiceRestMetadata serviceRestMetadata, Class<?> serviceType) {
+        return execute(serviceType.getClassLoader(), classLoader -> {
+            String serviceInterface = serviceRestMetadata.getServiceInterface();
+            return forName(serviceInterface, classLoader);
+        });
+    }
+
+    /**
+     * Process the single {@link RestMethodMetadata} by the specified {@link Consumer} if present
+     *
+     * @param serviceMethod         Dubbo Service method
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @param metadataToProcess     {@link RestMethodMetadata} to process if present
+     * @return if processed successfully, return <code>true</code>, or <code>false</code>
+     */
+    protected boolean processRestMethodMetadata(Method serviceMethod, Class<?> serviceType,
+                                                Class<?> serviceInterfaceClass,
+                                                Consumer<RestMethodMetadata> metadataToProcess) {
+
+        if (!isRestCapableMethod(serviceMethod, serviceType, serviceInterfaceClass)) {
+            return false;
+        }
+
+        String requestPath = resolveRequestPath(serviceMethod, serviceType, serviceInterfaceClass); // requestPath is required
+
+        if (requestPath == null) {
+            return false;
+        }
+
+        String requestMethod = resolveRequestMethod(serviceMethod, serviceType, serviceInterfaceClass); // requestMethod is required
+
+        if (requestMethod == null) {
+            return false;
+        }
+
+        RestMethodMetadata metadata = new RestMethodMetadata();
+
+        MethodDefinition methodDefinition = resolveMethodDefinition(serviceMethod, serviceType, serviceInterfaceClass);
+        // Set MethodDefinition
+        metadata.setMethod(methodDefinition);
+
+        // process the annotated method parameters
+        processAnnotatedMethodParameters(serviceMethod, serviceType, serviceInterfaceClass, metadata);
+
+        // process produces
+        Set<String> produces = new LinkedHashSet<>();
+        processProduces(serviceMethod, serviceType, serviceInterfaceClass, produces);
+
+        // process consumes
+        Set<String> consumes = new LinkedHashSet<>();
+        processConsumes(serviceMethod, serviceType, serviceInterfaceClass, consumes);
+
+        // Initialize RequestMetadata
+        RequestMetadata request = metadata.getRequest();
+        request.setPath(requestPath);
+        request.setMethod(requestMethod);
+        request.setProduces(produces);
+        request.setConsumes(consumes);
+
+        // Post-Process
+        postResolveRestMethodMetadata(serviceMethod, serviceType, serviceInterfaceClass, metadata);
+
+        // Accept RestMethodMetadata
+        metadataToProcess.accept(metadata);
+
+        return true;
+    }
+
+    /**
+     * Test the service method is capable of REST or not?
+     *
+     * @param serviceMethod         Dubbo Service method
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @return If capable, return <code>true</code>
+     */
+    protected abstract boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?>
+            serviceInterfaceClass);
+
+    /**
+     * Resolve the request method
+     *
+     * @param serviceMethod         Dubbo Service method
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @return if can't be resolve, return <code>null</code>
+     */
+    protected abstract String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?>
+            serviceInterfaceClass);
+
+    /**
+     * Resolve the request path
+     *
+     * @param serviceMethod         Dubbo Service method
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @return if can't be resolve, return <code>null</code>
+     */
+    protected abstract String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?>
+            serviceInterfaceClass);
+
+    /**
+     * Resolve the {@link MethodDefinition}
+     *
+     * @param serviceMethod         Dubbo Service method
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @return if can't be resolve, return <code>null</code>
+     * @see MethodDefinitionBuilder
+     */
+    protected MethodDefinition resolveMethodDefinition(Method serviceMethod, Class<?> serviceType,
+                                                       Class<?> serviceInterfaceClass) {
+        MethodDefinitionBuilder builder = new MethodDefinitionBuilder();
+        return builder.build(serviceMethod);
+    }
+
+    private void processAnnotatedMethodParameters(Method serviceMethod, Class<?> serviceType,
+                                                  Class<?> serviceInterfaceClass, RestMethodMetadata metadata) {
+        int paramCount = serviceMethod.getParameterCount();
+        Parameter[] parameters = serviceMethod.getParameters();
+        for (int i = 0; i < paramCount; i++) {
+            Parameter parameter = parameters[i];
+            // Add indexed parameter name
+            metadata.addIndexToName(i,parameter.getName());
+            processAnnotatedMethodParameter(parameter, i, serviceMethod, serviceType, serviceInterfaceClass, metadata);
+        }
+    }
+
+    private void processAnnotatedMethodParameter(Parameter parameter, int parameterIndex, Method serviceMethod,
+                                                 Class<?> serviceType, Class<?> serviceInterfaceClass,
+                                                 RestMethodMetadata metadata) {
+        Annotation[] annotations = parameter.getAnnotations();
+        for (Annotation annotation : annotations) {
+            String annotationType = annotation.annotationType().getName();
+            parameterProcessorsMap.getOrDefault(annotationType, emptyList())
+                    .forEach(processor -> {
+                        processor.process(annotation, parameter, parameterIndex, serviceMethod, serviceType,
+                                serviceInterfaceClass, metadata);
+                    });
+        }
+    }
+
+    protected abstract void processProduces(Method serviceMethod, Class<?> serviceType, Class<?>
+            serviceInterfaceClass,
+                                            Set<String> produces);
+
+    protected abstract void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?>
+            serviceInterfaceClass,
+                                            Set<String> consumes);
+
+    protected void postResolveRestMethodMetadata(Method serviceMethod, Class<?> serviceType,
+                                                 Class<?> serviceInterfaceClass, RestMethodMetadata metadata) {
+    }
+
+    private static Map<String, List<AnnotatedMethodParameterProcessor>> loadAnnotatedMethodParameterProcessors() {
+        Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = new LinkedHashMap<>();
+        getExtensionLoader(AnnotatedMethodParameterProcessor.class)
+                .getSupportedExtensionInstances()
+                .forEach(processor -> {
+                    List<AnnotatedMethodParameterProcessor> processors =
+                            parameterProcessorsMap.computeIfAbsent(processor.getAnnotationType(), k -> new LinkedList<>());
+                    processors.add(processor);
+                });
+        return parameterProcessorsMap;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..bd52017
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/AnnotatedMethodParameterProcessor.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.metadata.rest;
+
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
+
+import javax.lang.model.element.VariableElement;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.lang.reflect.Parameter;
+
+/**
+ * The interface to process the annotated method parameter
+ *
+ * @since 2.7.6
+ */
+@SPI
+public interface AnnotatedMethodParameterProcessor extends Prioritized {
+
+    /**
+     * The string presenting the annotation type
+     *
+     * @return non-null
+     */
+    String getAnnotationType();
+
+    /**
+     * Process the specified method {@link VariableElement parameter}
+     *
+     * @param annotation            {@link Annotation the target annotation} whose type is {@link #getAnnotationType()}
+     * @param parameter             the method parameter
+     * @param parameterIndex        the index of method parameter
+     * @param method                {@link Method method that parameter belongs to}
+     * @param serviceType           Dubbo Service interface or type
+     * @param serviceInterfaceClass The type of Dubbo Service interface
+     * @param restMethodMetadata    {@link RestMethodMetadata the metadata is used to update}
+     */
+    void process(Annotation annotation, Parameter parameter, int parameterIndex, Method method,
+                 Class<?> serviceType, Class<?> serviceInterfaceClass, RestMethodMetadata restMethodMetadata);
+
+    /**
+     * Build the default value
+     *
+     * @param parameterIndex the index of parameter
+     * @return the placeholder
+     */
+    static String buildDefaultValue(int parameterIndex) {
+        return "{" + parameterIndex + "}";
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ClassPathServiceRestMetadataReader.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ClassPathServiceRestMetadataReader.java
new file mode 100644
index 0000000..bd4d5a0
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ClassPathServiceRestMetadataReader.java
@@ -0,0 +1,82 @@
+/*
+ * 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.metadata.rest;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParser;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+
+import static java.util.Collections.unmodifiableList;
+import static org.apache.dubbo.common.function.ThrowableAction.execute;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.METADATA_ENCODING;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SERVICE_REST_METADATA_RESOURCE_PATH;
+
+/**
+ * Class-Path based {@link ServiceRestMetadataReader} implementation
+ *
+ * @see ServiceRestMetadataReader
+ * @since 2.7.6
+ */
+public class ClassPathServiceRestMetadataReader implements ServiceRestMetadataReader {
+
+    private final String serviceRestMetadataJsonResoucePath;
+
+    public ClassPathServiceRestMetadataReader() {
+        this(SERVICE_REST_METADATA_RESOURCE_PATH);
+    }
+
+    public ClassPathServiceRestMetadataReader(String serviceRestMetadataJsonResoucePath) {
+        this.serviceRestMetadataJsonResoucePath = serviceRestMetadataJsonResoucePath;
+    }
+
+    @Override
+    public List<ServiceRestMetadata> read() {
+
+        List<ServiceRestMetadata> serviceRestMetadataList = new LinkedList<>();
+
+        ClassLoader classLoader = getClass().getClassLoader();
+
+        execute(() -> {
+            Enumeration<URL> resources = classLoader.getResources(serviceRestMetadataJsonResoucePath);
+            Gson gson = new Gson();
+            while (resources.hasMoreElements()) {
+                URL resource = resources.nextElement();
+                InputStream inputStream = resource.openStream();
+                JsonParser parser = new JsonParser();
+                JsonElement jsonElement = parser.parse(new InputStreamReader(inputStream, METADATA_ENCODING));
+                if (jsonElement.isJsonArray()) {
+                    JsonArray jsonArray = jsonElement.getAsJsonArray();
+                    for (int i = 0; i < jsonArray.size(); i++) {
+                        JsonElement childJsonElement = jsonArray.get(i);
+                        ServiceRestMetadata serviceRestMetadata = gson.fromJson(childJsonElement, ServiceRestMetadata.class);
+                        serviceRestMetadataList.add(serviceRestMetadata);
+                    }
+                }
+            }
+        });
+
+        return unmodifiableList(serviceRestMetadataList);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/DefaultServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/DefaultServiceRestMetadataResolver.java
new file mode 100644
index 0000000..ce53dd8
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/DefaultServiceRestMetadataResolver.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest;
+
+import java.lang.reflect.Method;
+import java.util.Set;
+
+
+/**
+ * The default implementation {@link ServiceRestMetadataResolver}
+ *
+ * @since 2.7.6
+ */
+public class DefaultServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
+
+    @Override
+    protected boolean supports0(Class<?> serviceType) {
+        return false;
+    }
+
+    @Override
+    protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        return false;
+    }
+
+    @Override
+    protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        return null;
+    }
+
+    @Override
+    protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        return null;
+    }
+
+    @Override
+    protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> produces) {
+
+    }
+
+    @Override
+    protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> consumes) {
+
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java
new file mode 100644
index 0000000..9381d20
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java
@@ -0,0 +1,226 @@
+/*
+ * 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.metadata.rest;
+
+
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+
+import static java.util.Collections.unmodifiableMap;
+import static org.apache.dubbo.common.utils.HttpUtils.normalizePath;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+
+/**
+ * The metadata class for REST request
+ *
+ * @since 2.7.6
+ */
+public class RequestMetadata implements Serializable {
+
+    private static final long serialVersionUID = -240099840085329958L;
+
+    private String method;
+
+    private String path;
+
+    private Map<String, List<String>> params = new LinkedHashMap<>();
+
+    private Map<String, List<String>> headers = new LinkedHashMap<>();
+
+    private Set<String> consumes = new LinkedHashSet<>();
+
+    private Set<String> produces = new LinkedHashSet<>();
+
+    /**
+     * Default Constructor
+     */
+    public RequestMetadata() {
+    }
+
+    public String getMethod() {
+        return method;
+    }
+
+    public void setMethod(String method) {
+        this.method = method == null ? null : method.toUpperCase();
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = normalizePath(path);
+    }
+
+    public Map<String, List<String>> getParams() {
+        return unmodifiableMap(params);
+    }
+
+    public void setParams(Map<String, List<String>> params) {
+        params(params);
+    }
+
+    private static void add(Map<String, List<String>> multiValueMap, String key, String value) {
+        if (isBlank(key)) {
+            return;
+        }
+        List<String> values = get(multiValueMap, key, true);
+        values.add(value);
+    }
+
+    private static <T extends Collection<String>> void addAll(Map<String, List<String>> multiValueMap,
+                                                              Map<String, T> source) {
+        for (Map.Entry<String, T> entry : source.entrySet()) {
+            String key = entry.getKey();
+            for (String value : entry.getValue()) {
+                add(multiValueMap, key, value);
+            }
+        }
+    }
+
+    private static String getFirst(Map<String, List<String>> multiValueMap, String key) {
+        List<String> values = get(multiValueMap, key);
+        return CollectionUtils.isNotEmpty(values) ? values.get(0) : null;
+    }
+
+    private static List<String> get(Map<String, List<String>> multiValueMap, String key) {
+        return get(multiValueMap, key, false);
+    }
+
+    private static List<String> get(Map<String, List<String>> multiValueMap, String key, boolean createIfAbsent) {
+        return createIfAbsent ? multiValueMap.computeIfAbsent(key, k -> new LinkedList<>()) : multiValueMap.get(key);
+    }
+
+    public Map<String, List<String>> getHeaders() {
+        return unmodifiableMap(headers);
+    }
+
+    public void setHeaders(Map<String, List<String>> headers) {
+        headers(headers);
+    }
+
+    public Set<String> getConsumes() {
+        return consumes;
+    }
+
+    public void setConsumes(Set<String> consumes) {
+        this.consumes = consumes;
+    }
+
+    public Set<String> getProduces() {
+        return produces;
+    }
+
+    public void setProduces(Set<String> produces) {
+        this.produces = produces;
+    }
+
+    public Set<String> getParamNames() {
+        return params.keySet();
+    }
+
+    public Set<String> getHeaderNames() {
+        return headers.keySet();
+    }
+
+//    public List<MediaType> getConsumeMediaTypes() {
+//        return toMediaTypes(consumes);
+//    }
+//
+//    public List<MediaType> getProduceMediaTypes() {
+//        return toMediaTypes(produces);
+//    }
+
+    public String getParameter(String name) {
+        return getFirst(params, name);
+    }
+
+    public String getHeader(String name) {
+        return getFirst(headers, name);
+    }
+
+    public RequestMetadata addParam(String name, String value) {
+        add(params, name, value);
+        return this;
+    }
+
+    public RequestMetadata addHeader(String name, String value) {
+        add(headers, name, value);
+        return this;
+    }
+
+    private <T extends Collection<String>> RequestMetadata params(Map<String, T> params) {
+        addAll(this.params, params);
+        return this;
+    }
+
+    private <T extends Collection<String>> RequestMetadata headers(Map<String, List<String>> headers) {
+        if (headers != null && !headers.isEmpty()) {
+            Map<String, List<String>> httpHeaders = new LinkedHashMap<>();
+            // Add all headers
+            addAll(headers, httpHeaders);
+            // Handles "Content-Type" and "Accept" headers if present
+//            mediaTypes(httpHeaders, HttpHeaders.CONTENT_TYPE, this.consumes);
+//            mediaTypes(httpHeaders, HttpHeaders.ACCEPT, this.produces);
+            this.headers.putAll(httpHeaders);
+        }
+        return this;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof RequestMetadata)) {
+            return false;
+        }
+        RequestMetadata that = (RequestMetadata) o;
+        return Objects.equals(method, that.method)
+                && Objects.equals(path, that.path)
+                && Objects.equals(consumes, that.consumes)
+                && Objects.equals(produces, that.produces) &&
+                // Metadata should not compare the values
+                Objects.equals(getParamNames(), that.getParamNames())
+                && Objects.equals(getHeaderNames(), that.getHeaderNames());
+
+    }
+
+    @Override
+    public int hashCode() {
+        // The values of metadata should not use for the hashCode() method
+        return Objects.hash(method, path, consumes, produces, getParamNames(),
+                getHeaderNames());
+    }
+
+    @Override
+    public String toString() {
+        return "RequestMetadata{" + "method='" + method + '\'' + ", path='" + path + '\''
+                + ", params=" + params + ", headers=" + headers + ", consumes=" + consumes
+                + ", produces=" + produces + '}';
+    }
+}
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
new file mode 100644
index 0000000..82e6328
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMetadataConstants.java
@@ -0,0 +1,112 @@
+/*
+ * 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.metadata.rest;
+
+/**
+ * The REST Metadata Constants definition interface
+ *
+ * @since 2.7.6
+ */
+public interface RestMetadataConstants {
+
+    /**
+     * The encoding of metadata
+     */
+    String METADATA_ENCODING = "UTF-8";
+
+    /**
+     * {@link ServiceRestMetadata} Resource PATH
+     */
+    String SERVICE_REST_METADATA_RESOURCE_PATH = "META-INF/dubbo/service-rest-metadata.json";
+
+    /**
+     * JAX-RS
+     */
+    interface JAX_RS {
+
+        /**
+         * The annotation class name of @Path
+         */
+        String PATH_ANNOTATION_CLASS_NAME = "javax.ws.rs.Path";
+
+        /**
+         * The annotation class name of @HttpMethod
+         */
+        String HTTP_METHOD_ANNOTATION_CLASS_NAME = "javax.ws.rs.HttpMethod";
+
+        /**
+         * The annotation class name of @Produces
+         */
+        String PRODUCES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Produces";
+
+        /**
+         * The annotation class name of @Consumes
+         */
+        String CONSUMES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Consumes";
+
+        /**
+         * The annotation class name of @DefaultValue
+         */
+        String DEFAULT_VALUE_ANNOTATION_CLASS_NAME = "javax.ws.rs.DefaultValue";
+
+        /**
+         * The annotation class name of @FormParam
+         */
+        String FORM_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.FormParam";
+
+        /**
+         * The annotation class name of @HeaderParam
+         */
+        String HEADER_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.HeaderParam";
+
+        /**
+         * The annotation class name of @MatrixParam
+         */
+        String MATRIX_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.MatrixParam";
+
+        /**
+         * The annotation class name of @QueryParam
+         */
+        String QUERY_PARAM_ANNOTATION_CLASS_NAME = "javax.ws.rs.QueryParam";
+    }
+
+    /**
+     * Spring MVC
+     */
+    interface SPRING_MVC {
+
+        /**
+         * The annotation class name of @Controller
+         */
+        String CONTROLLER_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Controller";
+
+        /**
+         * The annotation class name of @RequestMapping
+         */
+        String REQUEST_MAPPING_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestMapping";
+
+        /**
+         * The annotation class name of @RequestHeader
+         */
+        String REQUEST_HEADER_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestHeader";
+
+        /**
+         * The annotation class name of @RequestParam
+         */
+        String REQUEST_PARAM_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestParam";
+    }
+}
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
new file mode 100644
index 0000000..a675eb3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+import static java.util.Collections.emptyList;
+
+/**
+ * The metadata class for {@link RequestMetadata HTTP(REST) request} and
+ * its binding {@link MethodDefinition method definition}
+ *
+ * @since 2.7.6
+ */
+public class RestMethodMetadata implements Serializable {
+
+    private static final long serialVersionUID = 2935252016200830694L;
+
+    private MethodDefinition method;
+
+    private RequestMetadata request;
+
+    private Integer urlIndex;
+
+    private Integer bodyIndex;
+
+    private Integer headerMapIndex;
+
+    private String bodyType;
+
+    private Map<Integer, Collection<String>> indexToName;
+
+    private List<String> formParams;
+
+    private Map<Integer, Boolean> indexToEncoded;
+
+    public MethodDefinition getMethod() {
+        if (method == null) {
+            method = new MethodDefinition();
+        }
+        return method;
+    }
+
+    public void setMethod(MethodDefinition method) {
+        this.method = method;
+    }
+
+    public RequestMetadata getRequest() {
+        if (request == null) {
+            request = new RequestMetadata();
+        }
+        return request;
+    }
+
+    public void setRequest(RequestMetadata request) {
+        this.request = request;
+    }
+
+    public Integer getUrlIndex() {
+        return urlIndex;
+    }
+
+    public void setUrlIndex(Integer urlIndex) {
+        this.urlIndex = urlIndex;
+    }
+
+    public Integer getBodyIndex() {
+        return bodyIndex;
+    }
+
+    public void setBodyIndex(Integer bodyIndex) {
+        this.bodyIndex = bodyIndex;
+    }
+
+    public Integer getHeaderMapIndex() {
+        return headerMapIndex;
+    }
+
+    public void setHeaderMapIndex(Integer headerMapIndex) {
+        this.headerMapIndex = headerMapIndex;
+    }
+
+    public String getBodyType() {
+        return bodyType;
+    }
+
+    public void setBodyType(String bodyType) {
+        this.bodyType = bodyType;
+    }
+
+    public Map<Integer, Collection<String>> getIndexToName() {
+        if (indexToName == null) {
+            indexToName = new HashMap<>();
+        }
+        return indexToName;
+    }
+
+    public void setIndexToName(Map<Integer, Collection<String>> indexToName) {
+        this.indexToName = indexToName;
+    }
+
+    public void addIndexToName(Integer index, String name) {
+        if (index == null) {
+            return;
+        }
+
+        if (name.startsWith("arg") && name.endsWith(index.toString())) {
+            // Ignore this value because of the Java byte-code without the metadata of method parameters
+            return;
+        }
+
+        Map<Integer, Collection<String>> indexToName = getIndexToName();
+        Collection<String> parameterNames = indexToName.computeIfAbsent(index, i -> new ArrayList<>(1));
+        parameterNames.add(name);
+    }
+
+    public boolean hasIndexedName(Integer index, String name) {
+        Map<Integer, Collection<String>> indexToName = getIndexToName();
+        return indexToName.getOrDefault(index, emptyList()).contains(name);
+    }
+
+    public List<String> getFormParams() {
+        return formParams;
+    }
+
+    public void setFormParams(List<String> formParams) {
+        this.formParams = formParams;
+    }
+
+    public Map<Integer, Boolean> getIndexToEncoded() {
+        return indexToEncoded;
+    }
+
+    public void setIndexToEncoded(Map<Integer, Boolean> indexToEncoded) {
+        this.indexToEncoded = indexToEncoded;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        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()) &&
+                Objects.equals(getUrlIndex(), that.getUrlIndex()) &&
+                Objects.equals(getBodyIndex(), that.getBodyIndex()) &&
+                Objects.equals(getHeaderMapIndex(), that.getHeaderMapIndex()) &&
+                Objects.equals(getBodyType(), that.getBodyType()) &&
+                Objects.equals(getFormParams(), that.getFormParams()) &&
+                Objects.equals(getIndexToEncoded(), that.getIndexToEncoded());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getMethod(), getRequest(), getUrlIndex(), getBodyIndex(), getHeaderMapIndex(), getBodyType(), getFormParams(), getIndexToEncoded());
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("RestMethodMetadata{");
+        sb.append("method=").append(method);
+        sb.append(", request=").append(request);
+        sb.append(", urlIndex=").append(urlIndex);
+        sb.append(", bodyIndex=").append(bodyIndex);
+        sb.append(", headerMapIndex=").append(headerMapIndex);
+        sb.append(", bodyType='").append(bodyType).append('\'');
+        sb.append(", indexToName=").append(indexToName);
+        sb.append(", formParams=").append(formParams);
+        sb.append(", indexToEncoded=").append(indexToEncoded);
+        sb.append('}');
+        return sb.toString();
+    }
+}
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
new file mode 100644
index 0000000..876b8a3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadata.java
@@ -0,0 +1,103 @@
+/*
+ * 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.metadata.rest;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * The metadata class for {@link RequestMetadata HTTP(REST) request} and
+ * its binding Dubbo service metadata
+ *
+ * @since 2.7.6
+ */
+public class ServiceRestMetadata implements Serializable {
+
+    private static final long serialVersionUID = -4549723140727443569L;
+
+    private String serviceInterface;
+
+    private String version;
+
+    private String group;
+
+    private Set<RestMethodMetadata> meta;
+
+    public String getServiceInterface() {
+        return serviceInterface;
+    }
+
+    public void setServiceInterface(String serviceInterface) {
+        this.serviceInterface = serviceInterface;
+    }
+
+    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 Set<RestMethodMetadata> getMeta() {
+        if (meta == null) {
+            meta = new LinkedHashSet<>();
+        }
+        return meta;
+    }
+
+    public void setMeta(Set<RestMethodMetadata> meta) {
+        this.meta = meta;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        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()) &&
+                Objects.equals(getGroup(), that.getGroup()) &&
+                Objects.equals(getMeta(), that.getMeta());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getServiceInterface(), getVersion(), getGroup(), getMeta());
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder("ServiceRestMetadata{");
+        sb.append("serviceInterface='").append(serviceInterface).append('\'');
+        sb.append(", version='").append(version).append('\'');
+        sb.append(", group='").append(group).append('\'');
+        sb.append(", meta=").append(meta);
+        sb.append('}');
+        return sb.toString();
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataReader.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataReader.java
new file mode 100644
index 0000000..de5207a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataReader.java
@@ -0,0 +1,39 @@
+/*
+ * 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.metadata.rest;
+
+
+import org.apache.dubbo.common.extension.SPI;
+
+import java.util.List;
+
+/**
+ * An interface to read {@link ServiceRestMetadata}
+ *
+ * @see ServiceRestMetadata
+ * @since 2.7.6
+ */
+@SPI
+public interface ServiceRestMetadataReader {
+
+    /**
+     * Read the instances of {@link ServiceRestMetadata}
+     *
+     * @return non-null
+     */
+    List<ServiceRestMetadata> read();
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataResolver.java
new file mode 100644
index 0000000..0c1ece8
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/ServiceRestMetadataResolver.java
@@ -0,0 +1,43 @@
+/*
+ * 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.metadata.rest;
+
+/**
+ * The interface to resolve the {@link ServiceRestMetadata REST metadata} from the specified
+ * Dubbo Service interface or type.
+ *
+ * @since 2.7.6
+ */
+public interface ServiceRestMetadataResolver {
+
+    /**
+     * Support to resolve {@link ServiceRestMetadata REST metadata} or not
+     *
+     * @param serviceType Dubbo Service interface or type
+     * @return If supports, return <code>true</code>, or <code>false</code>
+     */
+    boolean supports(Class<?> serviceType);
+
+    /**
+     * Resolve the {@link ServiceRestMetadata REST metadata} from the specified
+     * Dubbo Service interface or type
+     *
+     * @param serviceType Dubbo Service interface or type
+     * @return
+     */
+    ServiceRestMetadata resolve(Class<?> serviceType);
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/DefaultValueParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/DefaultValueParameterProcessor.java
new file mode 100644
index 0000000..a9e7c0e
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/DefaultValueParameterProcessor.java
@@ -0,0 +1,74 @@
+/*
+ * 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.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Map;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
+
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @DefaultValue
+ * *
+ *
+ * @since 2.7.6
+ */
+public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
+    }
+
+    @Override
+    protected void process(String annotationValue, String defaultValue, Annotation annotation, Object parameter,
+                           int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
+        RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+
+        // process the request parameters
+        setDefaultValue(requestMetadata.getParams(), defaultValue, annotationValue);
+        // process the request headers
+        setDefaultValue(requestMetadata.getHeaders(), defaultValue, annotationValue);
+    }
+
+    private void setDefaultValue(Map<String, List<String>> source, String placeholderValue, String defaultValue) {
+        OUTTER:
+        for (Map.Entry<String, List<String>> entry : source.entrySet()) {
+            List<String> values = entry.getValue();
+            int size = values.size();
+            for (int i = 0; i < size; i++) {
+                String value = values.get(i);
+                if (placeholderValue.equals(value)) {
+                    values.set(i, defaultValue);
+                    break OUTTER;
+                }
+            }
+        }
+    }
+
+    public int getPriority() {
+        return MIN_PRIORITY;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/FormParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/FormParamParameterProcessor.java
new file mode 100644
index 0000000..d102e39
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/FormParamParameterProcessor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.FORM_PARAM_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @FormParam
+ *
+ * @since 2.7.6
+ */
+public class FormParamParameterProcessor extends ParamAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return FORM_PARAM_ANNOTATION_CLASS_NAME;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/HeaderParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/HeaderParamParameterProcessor.java
new file mode 100644
index 0000000..16d21bf
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/HeaderParamParameterProcessor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import static org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.HEADER_PARAM_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @HeaderParam
+ *
+ * @since 2.7.6
+ */
+public class HeaderParamParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return HEADER_PARAM_ANNOTATION_CLASS_NAME;
+    }
+
+    @Override
+    protected void process(String headerName, String defaultValue, Annotation annotation, Object parameter,
+                           int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
+        RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+        // Add the placeholder as header value
+        requestMetadata.addHeader(headerName, buildDefaultValue(parameterIndex));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java
new file mode 100644
index 0000000..ca4a77f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/JAXRSServiceRestMetadataResolver.java
@@ -0,0 +1,99 @@
+/*
+ * 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.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Set;
+import java.util.stream.Stream;
+
+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.getValue;
+import static org.apache.dubbo.common.utils.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.common.utils.HttpUtils.buildPath;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.CONSUMES_ANNOTATION_CLASS_NAME;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.HTTP_METHOD_ANNOTATION_CLASS_NAME;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.PATH_ANNOTATION_CLASS_NAME;
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.PRODUCES_ANNOTATION_CLASS_NAME;
+
+/**
+ * JAX-RS {@link ServiceRestMetadataResolver} implementation
+ *
+ * @since 2.7.6
+ */
+public class JAXRSServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
+
+    @Override
+    protected boolean supports0(Class<?> serviceType) {
+        return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
+    }
+
+    @Override
+    protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        return isAnnotationPresent(serviceMethod, HTTP_METHOD_ANNOTATION_CLASS_NAME);
+    }
+
+    @Override
+    protected String resolveRequestMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        Annotation httpMethod = findMetaAnnotation(serviceMethod, HTTP_METHOD_ANNOTATION_CLASS_NAME);
+        return getValue(httpMethod);
+    }
+
+    @Override
+    protected String resolveRequestPath(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        String requestBasePath = resolveRequestPathFromType(serviceType, serviceInterfaceClass);
+        String requestRelativePath = resolveRequestPathFromMethod(serviceMethod);
+        return buildPath(requestBasePath, requestRelativePath);
+    }
+
+    private String resolveRequestPathFromType(Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        Annotation path = findAnnotation(serviceType, PATH_ANNOTATION_CLASS_NAME);
+        if (path == null) {
+            path = findAnnotation(serviceInterfaceClass, PATH_ANNOTATION_CLASS_NAME);
+        }
+        return getValue(path);
+    }
+
+    private String resolveRequestPathFromMethod(Method serviceMethod) {
+        Annotation path = findAnnotation(serviceMethod, PATH_ANNOTATION_CLASS_NAME);
+        return getValue(path);
+    }
+
+    @Override
+    protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass,
+                                   Set<String> produces) {
+        addAnnotationValues(serviceMethod, PRODUCES_ANNOTATION_CLASS_NAME, produces);
+    }
+
+    @Override
+    protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass,
+                                   Set<String> consumes) {
+        addAnnotationValues(serviceMethod, CONSUMES_ANNOTATION_CLASS_NAME, consumes);
+    }
+
+    private void addAnnotationValues(Method serviceMethod, String annotationAttributeName, Set<String> result) {
+        Annotation annotation = findAnnotation(serviceMethod, annotationAttributeName);
+        String[] value = getValue(annotation);
+        if (value != null) {
+            Stream.of(value).forEach(result::add);
+        }
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/MatrixParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/MatrixParamParameterProcessor.java
new file mode 100644
index 0000000..894f33d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/MatrixParamParameterProcessor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.MATRIX_PARAM_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @MatrixParam
+ *
+ * @since 2.7.6
+ */
+public class MatrixParamParameterProcessor extends ParamAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return MATRIX_PARAM_ANNOTATION_CLASS_NAME;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/ParamAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/ParamAnnotationParameterProcessor.java
new file mode 100644
index 0000000..b6be293
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/ParamAnnotationParameterProcessor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @*Param
+ */
+public abstract class ParamAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    @Override
+    protected void process(String name, String defaultValue, Annotation annotation, Object parameter,
+                           int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
+        RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+        requestMetadata.addParam(name, defaultValue);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/QueryParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/QueryParamParameterProcessor.java
new file mode 100644
index 0000000..bfe539c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/jaxrs/QueryParamParameterProcessor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest.jaxrs;
+
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.JAX_RS.QUERY_PARAM_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @QueryParam
+ *
+ * @since 2.7.6
+ */
+public class QueryParamParameterProcessor extends ParamAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return QUERY_PARAM_ANNOTATION_CLASS_NAME;
+    }
+}
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
new file mode 100644
index 0000000..28407c2
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
@@ -0,0 +1,62 @@
+/*
+ * 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.metadata.rest.springmvc;
+
+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 static org.apache.dubbo.common.utils.AnnotationUtils.getAttribute;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @Request*
+ */
+public abstract class AbstractRequestAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    @Override
+    protected String getAnnotationValue(Annotation annotation, Parameter parameter, int parameterIndex) {
+        // try to get "value" attribute first
+        String name = super.getAnnotationValue(annotation, parameter, parameterIndex);
+
+        // try to get "name" attribute if required
+        if (isEmpty(name)) {
+            name = getAttribute(annotation, "name");
+        }
+
+        // finally , try to the name of parameter
+        if (isEmpty(name)) {
+            name = parameter.getName();
+        }
+
+        return name;
+    }
+
+    @Override
+    protected String getDefaultValue(Annotation annotation, Parameter parameter, int parameterIndex) {
+        String defaultValue = getAttribute(annotation, "defaultValue");
+        if (isEmpty(defaultValue)) {
+            defaultValue = super.getDefaultValue(annotation, parameter, parameterIndex);
+        }
+        return defaultValue;
+    }
+
+    protected boolean isEmpty(String str) {
+        return str == null || str.isEmpty();
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestHeaderParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestHeaderParameterProcessor.java
new file mode 100644
index 0000000..8d16898
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestHeaderParameterProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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.metadata.rest.springmvc;
+
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_HEADER_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestHeader
+ */
+public class RequestHeaderParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return REQUEST_HEADER_ANNOTATION_CLASS_NAME;
+    }
+
+    @Override
+    protected void process(String name, String defaultValue, Annotation annotation, Object parameter,
+                           int parameterIndex, Method method, RestMethodMetadata restMethodMetadata) {
+        restMethodMetadata.getRequest().addHeader(name, defaultValue);
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestParamParameterProcessor.java
new file mode 100644
index 0000000..5ae4727
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/RequestParamParameterProcessor.java
@@ -0,0 +1,43 @@
+/*
+ * 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.metadata.rest.springmvc;
+
+import org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import static org.apache.dubbo.metadata.rest.RestMetadataConstants.SPRING_MVC.REQUEST_PARAM_ANNOTATION_CLASS_NAME;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestParam
+ */
+public class RequestParamParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return REQUEST_PARAM_ANNOTATION_CLASS_NAME;
+    }
+
+    @Override
+    protected void process(String name, String defaultValue, Annotation annotation, Object parameter, int parameterIndex,
+                           Method method, RestMethodMetadata restMethodMetadata) {
+        restMethodMetadata.getRequest().addParam(name, defaultValue);
+
+    }
+}
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
new file mode 100644
index 0000000..2fde671
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/springmvc/SpringMvcServiceRestMetadataResolver.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.rest.springmvc;
+
+import org.apache.dubbo.metadata.rest.AbstractServiceRestMetadataResolver;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.Set;
+
+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.HttpUtils.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;
+
+/**
+ * {@link ServiceRestMetadataResolver}
+ *
+ * @since 2.7.6
+ */
+public class SpringMvcServiceRestMetadataResolver extends AbstractServiceRestMetadataResolver {
+
+    private static final int FIRST_ELEMENT_INDEX = 0;
+
+    @Override
+    protected boolean supports0(Class<?> serviceType) {
+        return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
+    }
+
+    @Override
+    protected boolean isRestCapableMethod(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass) {
+        return isAnnotationPresent(serviceType, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+    }
+
+    @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
+        Object httpMethod = getAttribute(requestMapping, "method");
+
+        if (httpMethod == null || getLength(httpMethod) < 1) {
+            return null;
+        }
+
+        // TODO Is is required to support more request methods?
+        return valueOf(Array.get(httpMethod, FIRST_ELEMENT_INDEX));
+    }
+
+    @Override
+    protected void processProduces(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> produces) {
+        addMediaTypes(serviceMethod, "produces", produces);
+    }
+
+    @Override
+    protected void processConsumes(Method serviceMethod, Class<?> serviceType, Class<?> serviceInterfaceClass, Set<String> consumes) {
+        addMediaTypes(serviceMethod, "consumes", consumes);
+    }
+
+    private String resolveRequestPath(AnnotatedElement annotatedElement) {
+        Annotation mappingAnnotation = getRequestMapping(annotatedElement);
+        // try "value" first
+        String[] value = getAttribute(mappingAnnotation, "value");
+
+        if (isEmpty(value)) { // try "path" later
+            value = getAttribute(mappingAnnotation, "path");
+        }
+
+        if (isEmpty(value)) {
+            return "";
+        }
+        // TODO Is is required to support more request paths?
+        return value[FIRST_ELEMENT_INDEX];
+    }
+
+    private void addMediaTypes(Method serviceMethod, String annotationAttributeName, Set<String> mediaTypesSet) {
+
+        Annotation mappingAnnotation = getRequestMapping(serviceMethod);
+
+        String[] mediaTypes = getAttribute(mappingAnnotation, annotationAttributeName);
+
+        if (isNotEmpty(mediaTypes)) {
+            of(mediaTypes).forEach(mediaTypesSet::add);
+        }
+    }
+
+    private Annotation getRequestMapping(AnnotatedElement annotatedElement) {
+        // try "@RequestMapping" first
+        Annotation requestMapping = findAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+        // try the annotation meta-annotated later
+        if (requestMapping == null) {
+            requestMapping = findMetaAnnotation(annotatedElement, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+        }
+        return requestMapping;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor
new file mode 100644
index 0000000..bcb620c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.AnnotatedMethodParameterProcessor
@@ -0,0 +1,10 @@
+# JAX-RS's implementations
+jax-rs.query-param = org.apache.dubbo.metadata.rest.jaxrs.QueryParamParameterProcessor
+jax-rs.form-param = org.apache.dubbo.metadata.rest.jaxrs.FormParamParameterProcessor
+jax-rs.matrix-param = org.apache.dubbo.metadata.rest.jaxrs.MatrixParamParameterProcessor
+jax-rs.header-param = org.apache.dubbo.metadata.rest.jaxrs.HeaderParamParameterProcessor
+jax-rs.default-value-param = org.apache.dubbo.metadata.rest.jaxrs.DefaultValueParameterProcessor
+
+# Spring Web MVC's implementations
+spring-webmvc.request-param = org.apache.dubbo.metadata.rest.springmvc.RequestParamParameterProcessor
+spring-webmvc.request-header = org.apache.dubbo.metadata.rest.springmvc.RequestHeaderParameterProcessor
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver
new file mode 100644
index 0000000..5b0873b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.rest.ServiceRestMetadataResolver
@@ -0,0 +1,3 @@
+default =
+jax-rs = org.apache.dubbo.metadata.rest.jaxrs.JAXRSServiceRestMetadataResolver
+spring-webmvc = org.apache.dubbo.metadata.rest.springmvc.SpringMvcServiceRestMetadataResolver
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java
similarity index 97%
rename from dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java
rename to dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java
index 89c81a5..3762f3a 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuildderTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilderTest.java
@@ -31,7 +31,7 @@ import java.util.List;
 /**
  * 2018/11/6
  */
-public class ServiceDefinitionBuildderTest {
+public class ServiceDefinitionBuilderTest {
 
     @Test
     public void testBuilderComplextObject() {
@@ -77,7 +77,7 @@ public class ServiceDefinitionBuildderTest {
             }
         }
         Assertions.assertEquals(topTypeDefinition.getProperties().get("v").getType(), "long");
-        Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String, java.lang.String>");
+        Assertions.assertEquals(topTypeDefinition.getProperties().get("maps").getType(), "java.util.Map<java.lang.String,java.lang.String>");
         Assertions.assertEquals(topTypeDefinition.getProperties().get("innerObject").getType(), ComplexObject.InnerObject.class.getName());
         Assertions.assertEquals(topTypeDefinition.getProperties().get("intList").getType(), "java.util.List<java.lang.Integer>");
         Assertions.assertEquals(topTypeDefinition.getProperties().get("strArrays").getType(), "java.lang.String[]");
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/DefaultRestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/DefaultRestService.java
new file mode 100644
index 0000000..210952a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/DefaultRestService.java
@@ -0,0 +1,69 @@
+/*
+ * 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.metadata.rest;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import java.util.Map;
+
+/**
+ * The default implementation of {@link RestService}
+ *
+ * @since 2.7.6
+ */
+@Service(version = "1.0.0")
+public class DefaultRestService implements RestService {
+
+    @Override
+    public String param(String param) {
+        return null;
+    }
+
+    @Override
+    public String params(int a, String b) {
+        return null;
+    }
+
+    @Override
+    public String headers(String header, String header2, Integer param) {
+        return null;
+    }
+
+    @Override
+    public String pathVariables(String path1, String path2, String param) {
+        return null;
+    }
+
+    @Override
+    public String form(String form) {
+        return null;
+    }
+
+    @Override
+    public User requestBodyMap(Map<String, Object> data, String param) {
+        return null;
+    }
+
+    @Override
+    public Map<String, Object> requestBodyUser(User user) {
+        return null;
+    }
+
+    public User user(User user) {
+        return user;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/RestService.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/RestService.java
new file mode 100644
index 0000000..65d67ab
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/RestService.java
@@ -0,0 +1,42 @@
+/*
+ * 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.metadata.rest;
+
+
+import java.util.Map;
+
+/**
+ * An interface for REST service
+ *
+ * @since 2.7.6
+ */
+public interface RestService {
+
+    String param(String param);
+
+    String params(int a, String b);
+
+    String headers(String header, String header2, Integer param);
+
+    String pathVariables(String path1, String path2, String param);
+
+    String form(String form);
+
+    User requestBodyMap(Map<String, Object> data, String param);
+
+    Map<String, Object> requestBodyUser(User user);
+}
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
new file mode 100644
index 0000000..ead5186
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/SpringRestService.java
@@ -0,0 +1,97 @@
+/*
+ * 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.metadata.rest;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestHeader;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Spring MVC {@link RestService}
+ *
+ * @since 2.7.6
+ */
+@Service(version = "2.0.0")
+@RestController
+public class SpringRestService implements RestService {
+
+    @Override
+    @GetMapping(value = "/param")
+    public String param(@RequestParam(defaultValue = "value-param") String param) {
+        return param;
+    }
+
+    @Override
+    @PostMapping("/params")
+    public String params(@RequestParam(defaultValue = "value-a") int a, @RequestParam(defaultValue = "value-b") String b) {
+        return a + b;
+    }
+
+    @Override
+    @GetMapping("/headers")
+    public String headers(@RequestHeader(name = "h", defaultValue = "value-h") String header,
+                          @RequestHeader(name = "h2", defaultValue = "value-h2") String header2,
+                          @RequestParam(value = "v", defaultValue = "1") Integer param) {
+        String result = header + " , " + header2 + " , " + param;
+        return result;
+    }
+
+    @Override
+    @GetMapping("/path-variables/{p1}/{p2}")
+    public String pathVariables(@PathVariable("p1") String path1,
+                                @PathVariable("p2") String path2, @RequestParam("v") String param) {
+        String result = path1 + " , " + path2 + " , " + param;
+        return result;
+    }
+
+    @Override
+    @PostMapping("/form")
+    public String form(@RequestParam("f") String form) {
+        return String.valueOf(form);
+    }
+
+    @Override
+    @PostMapping(value = "/request/body/map", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    public User requestBodyMap(@RequestBody Map<String, Object> data,
+                               @RequestParam("param") String param) {
+        User user = new User();
+        user.setId(((Integer) data.get("id")).longValue());
+        user.setName((String) data.get("name"));
+        user.setAge((Integer) data.get("age"));
+        return user;
+    }
+
+    @PostMapping(value = "/request/body/user", consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
+    @Override
+    public Map<String, Object> requestBodyUser(@RequestBody User user) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", user.getId());
+        map.put("name", user.getName());
+        map.put("age", user.getAge());
+        return map;
+    }
+}
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
new file mode 100644
index 0000000..f5d94b7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/StandardRestService.java
@@ -0,0 +1,107 @@
+/*
+ * 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.metadata.rest;
+
+import org.apache.dubbo.config.annotation.Service;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import java.util.HashMap;
+import java.util.Map;
+
+
+/**
+ * JAX-RS {@link RestService}
+ */
+@Service(version = "3.0.0", protocol = {"dubbo", "rest"}, group = "standard")
+@Path("/")
+public class StandardRestService implements RestService {
+
+    @Override
+    @Path("param")
+    @GET
+    public String param(@QueryParam("param") String param) {
+        return param;
+    }
+
+    @Override
+    @Path("params")
+    @POST
+    public String params(@QueryParam("a") int a, @QueryParam("b") String b) {
+        return a + b;
+    }
+
+    @Override
+    @Path("headers")
+    @GET
+    public String headers(@HeaderParam("h") String header,
+                          @HeaderParam("h2") String header2, @QueryParam("v") Integer param) {
+        String result = header + " , " + header2 + " , " + param;
+        return result;
+    }
+
+    @Override
+    @Path("path-variables/{p1}/{p2}")
+    @GET
+    public String pathVariables(@PathParam("p1") String path1,
+                                @PathParam("p2") String path2, @QueryParam("v") String param) {
+        String result = path1 + " , " + path2 + " , " + param;
+        return result;
+    }
+
+    // @CookieParam does not support : https://github.com/OpenFeign/feign/issues/913
+    // @CookieValue also does not support
+
+    @Override
+    @Path("form")
+    @POST
+    public String form(@FormParam("f") String form) {
+        return String.valueOf(form);
+    }
+
+    @Override
+    @Path("request/body/map")
+    @POST
+    @Produces("application/json;charset=UTF-8")
+    public User requestBodyMap(Map<String, Object> data,
+                               @QueryParam("param") String param) {
+        User user = new User();
+        user.setId(((Integer) data.get("id")).longValue());
+        user.setName((String) data.get("name"));
+        user.setAge((Integer) data.get("age"));
+        return user;
+    }
+
+    @Path("request/body/user")
+    @POST
+    @Override
+    @Consumes("application/json;charset=UTF-8")
+    public Map<String, Object> requestBodyUser(User user) {
+        Map<String, Object> map = new HashMap<>();
+        map.put("id", user.getId());
+        map.put("name", user.getName());
+        map.put("age", user.getAge());
+        return map;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/User.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/User.java
new file mode 100644
index 0000000..2ad6a51
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/User.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2018 the original author or authors.
+ *
+ * Licensed 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
+ *
+ *      https://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.metadata.rest;
+
+import java.io.Serializable;
+
+/**
+ * User Entity
+ *
+ * @since 2.7.6
+ */
+public class User implements Serializable {
+
+    private Long id;
+
+    private String name;
+
+    private Integer age;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public Integer getAge() {
+        return age;
+    }
+
+    public void setAge(Integer age) {
+        this.age = age;
+    }
+
+    @Override
+    public String toString() {
+        return "User{" + "id=" + id + ", name='" + name + '\'' + ", age=" + age + '}';
+    }
+}
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/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
new file mode 100644
index 0000000..d959007
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/rest/resolver/jaxrs/JAXRSServiceRestMetadataResolverTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.metadata.rest.resolver.jaxrs;
+
+import org.apache.dubbo.metadata.rest.ClassPathServiceRestMetadataReader;
+import org.apache.dubbo.metadata.rest.DefaultRestService;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+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;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link JAXRSServiceRestMetadataResolver} Test
+ *
+ * @since 2.7.6
+ */
+public class JAXRSServiceRestMetadataResolverTest {
+
+    private JAXRSServiceRestMetadataResolver instance = new JAXRSServiceRestMetadataResolver();
+
+    @Test
+    public void testSupports() {
+        // JAX-RS RestService class
+        assertTrue(instance.supports(StandardRestService.class));
+        // Spring MVC RestService class
+        assertFalse(instance.supports(SpringRestService.class));
+        // Default RestService class
+        assertFalse(instance.supports(DefaultRestService.class));
+        // No annotated RestService class
+        assertFalse(instance.supports(RestService.class));
+        // null
+        assertFalse(instance.supports(null));
+    }
+
+    @Test
+    public void testResolve() {
+        // Generated by "dubbo-metadata-processor"
+        ClassPathServiceRestMetadataReader reader = new ClassPathServiceRestMetadataReader("META-INF/dubbo/jax-rs-service-rest-metadata.json");
+        List<ServiceRestMetadata> serviceRestMetadataList = reader.read();
+
+        ServiceRestMetadata expectedServiceRestMetadata = serviceRestMetadataList.get(0);
+        ServiceRestMetadata serviceRestMetadata = instance.resolve(StandardRestService.class);
+
+
+        List<RestMethodMetadata> meta1 = new LinkedList<>(expectedServiceRestMetadata.getMeta());
+        List<RestMethodMetadata> meta2 = new LinkedList<>(serviceRestMetadata.getMeta());
+
+        for (int i = 0; i < meta1.size(); i++) {
+            RestMethodMetadata restMethodMetadata = meta1.get(i);
+            RestMethodMetadata restMethodMetadata2 = meta2.get(i);
+            assertEquals(restMethodMetadata, restMethodMetadata2);
+        }
+
+        assertEquals(expectedServiceRestMetadata, serviceRestMetadata);
+
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/jax-rs-service-rest-metadata.json b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/jax-rs-service-rest-metadata.json
new file mode 100644
index 0000000..3830369
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/resources/META-INF/dubbo/jax-rs-service-rest-metadata.json
@@ -0,0 +1,349 @@
+[
+  {
+    "serviceInterface": "org.apache.dubbo.metadata.rest.RestService",
+    "version": "3.0.0",
+    "group": "standard",
+    "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": [
+              "{2}"
+            ]
+          },
+          "headers": {
+            "h": [
+              "{0}"
+            ],
+            "h2": [
+              "{1}"
+            ]
+          },
+          "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": [
+              "{0}"
+            ]
+          },
+          "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": [
+              "{0}"
+            ],
+            "b": [
+              "{1}"
+            ]
+          },
+          "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": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "GET",
+          "path": "/path-variables/{p1}/{p2}",
+          "params": {
+            "v": [
+              "{2}"
+            ]
+          },
+          "headers": {},
+          "consumes": [],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "path1"
+          ],
+          "1": [
+            "path2"
+          ],
+          "2": [
+            "param"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "requestBodyMap",
+          "parameterTypes": [
+            "java.util.Map\u003cjava.lang.String,java.lang.Object\u003e",
+            "java.lang.String"
+          ],
+          "returnType": "org.apache.dubbo.metadata.rest.User",
+          "parameters": [
+            {
+              "type": "java.util.Map\u003cjava.lang.String,java.lang.Object\u003e",
+              "items": [
+                {
+                  "type": "java.lang.String",
+                  "items": [],
+                  "enum": [],
+                  "properties": {}
+                },
+                {
+                  "type": "java.lang.Object",
+                  "items": [],
+                  "enum": [],
+                  "properties": {}
+                }
+              ],
+              "enum": [],
+              "properties": {}
+            },
+            {
+              "type": "java.lang.String",
+              "items": [],
+              "enum": [],
+              "properties": {}
+            }
+          ]
+        },
+        "request": {
+          "method": "POST",
+          "path": "/request/body/map",
+          "params": {
+            "param": [
+              "{1}"
+            ]
+          },
+          "headers": {},
+          "consumes": [],
+          "produces": [
+            "application/json;charset\u003dUTF-8"
+          ]
+        },
+        "indexToName": {
+          "0": [
+            "data"
+          ],
+          "1": [
+            "param"
+          ]
+        }
+      },
+      {
+        "method": {
+          "name": "requestBodyUser",
+          "parameterTypes": [
+            "org.apache.dubbo.metadata.rest.User"
+          ],
+          "returnType": "java.util.Map\u003cjava.lang.String,java.lang.Object\u003e",
+          "parameters": [
+            {
+              "type": "org.apache.dubbo.metadata.rest.User",
+              "items": [],
+              "enum": [],
+              "properties": {
+                "name": {
+                  "type": "java.lang.String",
+                  "items": [],
+                  "enum": [],
+                  "properties": {}
+                },
+                "id": {
+                  "type": "java.lang.Long",
+                  "items": [],
+                  "enum": [],
+                  "properties": {}
+                },
+                "age": {
+                  "type": "java.lang.Integer",
+                  "items": [],
+                  "enum": [],
+                  "properties": {}
+                }
+              }
+            }
+          ]
+        },
+        "request": {
+          "method": "POST",
+          "path": "/request/body/user",
+          "params": {},
+          "headers": {},
+          "consumes": [
+            "application/json;charset\u003dUTF-8"
+          ],
+          "produces": []
+        },
+        "indexToName": {
+          "0": [
+            "user"
+          ]
+        }
+      }
+    ]
+  }
+]
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java b/dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
index 5557e26..e9c8a17 100644
--- a/dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
+++ b/dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
@@ -66,8 +66,8 @@ public class ProtobufTypeBuilderTest {
         assertThat(propertiesMap.containsKey("phone"), is(true));
         assertThat(propertiesMap.get("phone").getType(), equalTo("java.util.List<org.apache.dubbo.metadata.definition.protobuf.model.GooglePB$PhoneNumber>"));
         assertThat(propertiesMap.containsKey("doubleMap"), is(true));
-        assertThat(propertiesMap.get("doubleMap").getType(), equalTo("java.util.Map<java.lang.String, org.apache.dubbo.metadata.definition.protobuf.model.GooglePB$PhoneNumber>"));
+        assertThat(propertiesMap.get("doubleMap").getType(), equalTo("java.util.Map<java.lang.String,org.apache.dubbo.metadata.definition.protobuf.model.GooglePB$PhoneNumber>"));
         assertThat(propertiesMap.get("bytesList").getType(), equalTo("java.util.List<com.google.protobuf.ByteString>"));
-        assertThat(propertiesMap.get("bytesMap").getType(), equalTo("java.util.Map<java.lang.String, com.google.protobuf.ByteString>"));
+        assertThat(propertiesMap.get("bytesMap").getType(), equalTo("java.util.Map<java.lang.String,com.google.protobuf.ByteString>"));
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/pom.xml b/dubbo-metadata/dubbo-metadata-processor/pom.xml
new file mode 100644
index 0000000..965c036
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml
@@ -0,0 +1,177 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ 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.
+  -->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <groupId>org.apache.dubbo</groupId>
+        <artifactId>dubbo-metadata</artifactId>
+        <version>${revision}</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>dubbo-metadata-processor</artifactId>
+    <packaging>jar</packaging>
+    <name>dubbo-metadata-processor</name>
+    <description>The metadata processor module of Dubbo project</description>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-metadata-api</artifactId>
+            <version>${project.parent.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-rpc-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-cluster</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.google.code.gson</groupId>
+                    <artifactId>gson</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-common</artifactId>
+            <version>${project.parent.version}</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>javax.annotation</groupId>
+                    <artifactId>javax.annotation-api</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>org.slf4j</groupId>
+                    <artifactId>slf4j-api</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>commons-logging</groupId>
+                    <artifactId>commons-logging</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>log4j</groupId>
+                    <artifactId>log4j</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-api</artifactId>
+                </exclusion>
+
+                <exclusion>
+                    <groupId>org.apache.logging.log4j</groupId>
+                    <artifactId>log4j-core</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.javassist</groupId>
+                    <artifactId>javassist</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alibaba</groupId>
+                    <artifactId>hessian-lite</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alibaba</groupId>
+                    <artifactId>fastjson</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.esotericsoftware</groupId>
+                    <artifactId>kryo</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>de.javakaffee</groupId>
+                    <artifactId>kryo-serializers</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>de.ruedigermoeller</groupId>
+                    <artifactId>fst</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>commons-io</groupId>
+                    <artifactId>commons-io</artifactId>
+                </exclusion>
+            </exclusions>
+
+        </dependency>
+
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
+
+        <!-- Test -->
+        <dependency>
+            <groupId>org.apache.dubbo</groupId>
+            <artifactId>dubbo-config-api</artifactId>
+            <version>${project.parent.version}</version>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-registry-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-metadata-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-monitor-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-remoting-api</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-rpc-injvm</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-filter-validation</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.dubbo</groupId>
+                    <artifactId>dubbo-filter-cache</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+
+        <!-- JAX-RS API -->
+        <dependency>
+            <groupId>javax.ws.rs</groupId>
+            <artifactId>javax.ws.rs-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+        <!-- Spring Web MVC -->
+        <dependency>
+            <groupId>org.springframework</groupId>
+            <artifactId>spring-web</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java
new file mode 100644
index 0000000..7ef7794
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/AbstractServiceAnnotationProcessor.java
@@ -0,0 +1,108 @@
+/*
+ * 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.metadata.annotation.processing;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SUPPORTED_ANNOTATION_TYPES;
+
+/**
+ * Abstract {@link Processor} for the classes that were annotated by Dubbo's @Service
+ *
+ * @since 2.7.6
+ */
+public abstract class AbstractServiceAnnotationProcessor extends AbstractProcessor {
+
+    protected Elements elements;
+
+    private List<? extends Element> objectMembers;
+
+    public synchronized void init(ProcessingEnvironment processingEnv) {
+        super.init(processingEnv);
+        this.elements = processingEnv.getElementUtils();
+        this.objectMembers = elements.getAllMembers(elements.getTypeElement(Object.class.getName()));
+    }
+
+    protected List<? extends Element> getActualMembers(TypeElement type) {
+        List<? extends Element> members = new LinkedList<>(elements.getAllMembers(type));
+        members.removeAll(objectMembers);
+        return members;
+    }
+
+    protected List<? extends ExecutableElement> getActualMethods(TypeElement type) {
+        return methodsIn(getActualMembers(type));
+    }
+
+    protected Map<String, ExecutableElement> getActualMethodsMap(TypeElement type) {
+        Map<String, ExecutableElement> methodsMap = new HashMap<>();
+        getActualMethods(type).forEach(method -> {
+            methodsMap.put(method.toString(), method);
+        });
+        return methodsMap;
+    }
+
+    public static String getMethodSignature(ExecutableElement method) {
+        if (!ElementKind.METHOD.equals(method.getKind())) {
+            throw new IllegalArgumentException("The argument must be Method Kind");
+        }
+
+        StringBuilder methodSignatureBuilder = new StringBuilder();
+
+        method.getModifiers().forEach(member -> {
+            methodSignatureBuilder.append(member).append(" ");
+        });
+
+        methodSignatureBuilder.append(method.getReturnType())
+                .append(" ")
+                .append(method.toString());
+
+        return methodSignatureBuilder.toString();
+    }
+
+    protected TypeElement getTypeElement(CharSequence className) {
+        return elements.getTypeElement(className);
+    }
+
+    protected PackageElement getPackageElement(Element type) {
+        return this.elements.getPackageOf(type);
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    @Override
+    public final Set<String> getSupportedAnnotationTypes() {
+        return SUPPORTED_ANNOTATION_TYPES;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java
new file mode 100644
index 0000000..9e1032c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ClassPathMetadataStorage.java
@@ -0,0 +1,105 @@
+/*
+ * 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.metadata.annotation.processing;
+
+
+import javax.annotation.processing.Filer;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.tools.FileObject;
+import java.io.File;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.Writer;
+import java.util.Optional;
+import java.util.function.Function;
+import java.util.function.Supplier;
+
+import static java.util.Optional.empty;
+import static java.util.Optional.ofNullable;
+import static javax.tools.StandardLocation.CLASS_OUTPUT;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.warn;
+
+/**
+ * A storage class for metadata under class path
+ */
+public class ClassPathMetadataStorage {
+
+    private final Filer filer;
+
+    public ClassPathMetadataStorage(ProcessingEnvironment processingEnv) {
+        this.filer = processingEnv.getFiler();
+    }
+
+    public void write(Supplier<String> contentSupplier, String resourceName) {
+        try (Writer writer = getWriter(resourceName)) {
+            writer.write(contentSupplier.get());
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public <T> Optional<T> read(String resourceName, Function<Reader, T> consumer) {
+        if (exists(resourceName)) {
+            try (Reader reader = getReader(resourceName)) {
+                return ofNullable(consumer.apply(reader));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+        return empty();
+    }
+
+    private boolean exists(String resourceName) {
+
+        return getResource(resourceName)
+                .map(FileObject::toUri)
+                .map(File::new)
+                .map(File::exists)
+                .orElse(false);
+    }
+
+    private Reader getReader(String resourceName) {
+        return getResource(resourceName).map(fileObject -> {
+            try {
+                return fileObject.openReader(false);
+            } catch (IOException e) {
+            }
+            return null;
+        }).orElse(null);
+    }
+
... 7990 lines suppressed ...