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 2019/10/28 09:01:40 UTC

[dubbo] branch cloud-native updated: [Update] Dubbo cloud native (#5252)

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

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


The following commit(s) were added to refs/heads/cloud-native by this push:
     new 289e670  [Update] Dubbo cloud native (#5252)
289e670 is described below

commit 289e670422ff7bb19c5b07568f7fb23653938556
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Mon Oct 28 17:00:24 2019 +0800

    [Update] Dubbo cloud native (#5252)
    
    * Polish apache/dubbo#4542 : [Enhancement] Adapt the Java standard Event/Listener mechanism
    
    * Polish apache/dubbo#4541 : [Feature] Add local File System DynamicConfigurationFactory‘s extension
    
    * Polish apache#4541 : Bugfix
    
    * Polish apache/dubbo#4541 : Optimization
    
    * Polish apache/dubbo#4541 : Add the compatibility for PollingWatchService on the some platforms
    
    * Polish apache/dubbo#4541 : Add delay publish without ThreadPoolExecutor
    
    * Polish apache/dubbo#4541 : Refactor the extension name
    
    * Polish apache/dubbo#4541 : Add remove ops
    
    * Polish apache/dubbo#4541 : Add testable constructor
    
    * Polish apache/dubbo#4541 : Add getConfigGroups method
    
    * Polish apache/dubbo#4610 : [Refactor] Refactor the bootstrap module
    
    * Polish apache/dubbo#4541 : Fix the nulling URL issue
    
    * Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
    
    * Polish apache/dubbo#4622 : [Refactor] Refactor ConfigManager
    
    * Polish apache/dubbo#4622 : Support multiple configcenters
    
    * Polish apache/dubbo#4671 : ServiceNameMapping will not map the group, version and protocol
    
    * update referenceCount log (#4683)
    
    Add comments to support multiple shared connections
    
    * Polish /apache/dubbo#4687 : Remove the duplicated test code in dubbo-config-spring (#4688)
    
    * #4685  修改代码if判断false问题 if (hasException == false)修改成if (!hasException) (#4695)
    
    * Fixed Service annotation method parameters are not in effect (#4598)
    
    * keep demo simple, and switch to use zookeeper as registry center (#4705)
    
    * keep demo simple, and switch to use zookeeper as registry center
    
    * remove comment
    
    * @Reference auto-wires the instance of generic interface #4594 (#4677)
    
    * try to shorten maven output to make travis build pass (#4710)
    
    * use CountDownLatch to check zk registry if establish connection (#4589)
    
    * Minor change
    
    * Rename the extension name of WritableMetadataService
    
    * Polish apache/dubbo#4759 : [Refactor] Change the signature of methods of MetadataService #4759
    
    * Merge remote-tracking branch 'upstream/master' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-all/pom.xml
    #	dubbo-bom/pom.xml
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
    #	dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
    #	dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
    #	dubbo-configcenter/dubbo-configcenter-api/src/main/java/org/apache/dubbo/configcenter/DynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
    #	dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
    #	dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
    #	dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
    #	dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
    #	dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/src/main/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilder.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
    #	dubbo-metadata/pom.xml
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
    #	dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java
    #	dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java
    #	dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
    
    * Polish apache/dubbo#3984 : Add the implementation of Page<ServiceInstance> getInstances(String serviceName, int offset, int pageSize, boolean healthyOnly)
    
    * Code merge
    
    * Fix the cases
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
    #	dubbo-metadata/dubbo-metadata-definition-protobuf/pom.xml
    #	dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/support/ServiceOrientedRegistryTest.java
    #	dubbo-registry/dubbo-registry-consul/src/main/java/org/apache/dubbo/registry/consul/ConsulServiceDiscoveryFactory.java
    #	dubbo-registry/dubbo-registry-etcd3/src/main/java/org/apache/dubbo/registry/etcd/EtcdServiceDiscovery.java
    
    * Refactor ConfigManager
    
    * Refactor ConfigManager
    
    * Resolve the issues on ConfigManager
    
    * Refactor and add test-cases for ConfigManager
    
    * Polish apache/dubbo#4774 : [Feature] Dubbo Cloud Native - To Support in Spring
    
    * Polish apache/dubbo#4808 : [Feature] Add the registered/unregistered event mechanism ShutdownHook
    
    * Polish apache/dubbo#4807 : [Feature] Add the callback mechanism ShutdownHook #4807
    
    * Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
    
    * Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
    
    * Polish apache/dubbo#4815 : [Feature] Add the ServiceLoader for Dubbo's services or components
    
    * Polish apache/dubbo#4813 : [Feature] add Prioritized implementation for ServiceInstanceCustomizer
    
    * Polish apache/dubbo#4807 : Add sort implementation
    
    * Refactor
    
    * Refactor
    
    * Polish apache/dubbo#4845 : [Feature] Enhance the Event-Publishing feature to original ServiceDiscovery
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
    
    * Polish apache/dubbo#4854 : [Feature] MetadataService supports the Dubbo protocol under auto-increased port
    
    * Polish apache/dubbo#4857 : [Enhancement] Sync the Metadata storage type into ApplicationConfig
    
    * Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent
    
    * Polish apache/dubbo#4868 : [Enhancement] Refactor ConfigChangeEvent
    
    * Polish apache/dubbo#4873 : [Feature] Add a conditional EventListener into Event Module
    
    * Polish apache/dubbo#4875 : [Feature] Refactor ServiceInstancesChangedListener
    
    * Remove the cycle dependencies
    
    * Remove the cycle dependencies
    
    * Polish apache/dubbo#4903 : [Feature] Set source into the BeanDefinition of Dubbo Config
    
    * Polish apache/dubbo#4902 : [Feature] Dubbo Cloud Native to Spring XML scenario
    
    * Polish apache/dubbo#4713 : Initial the new module and dependencies
    
    * Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
    
    * Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
    
    * Polish apache/dubbo#4690 : AnnotatedBeanDefinitionRegistryUtils#registerBeans can't remove the duplicated bean definitions
    
    * Polish apache/dubbo#4910 : [Feature] To suppoort DubboLifecycleComponentApplicationListener in Spring XML scenario
    
    * Polish apache/dubbo#4713 : Add Service discovery implementation for Eureka #4713
    
    * Polish apache/dubbo#4713 : Add Service registration and discovery implementation for Eureka
    
    * Polish apache/dubbo#4713 : Add Service registration and discovery implementation for Eureka
    
    * Polish apache/dubbo#4920 : [Refactor] Extract the common implementation for URLs' revision
    
    * Refactor
    
    * Polish apache/dubbo#4925 : ServiceDiscovery limits only one ServiceInstancesChangedListener each service
    
    * Polish apache/dubbo#4925 : ServiceDiscovery limits only one ServiceInstancesChangedListener each service
    
    * Remove useless classes
    
    * Bugfix & Refactor ServiceDiscoveryRegistry
    
    * Polish apache/dubbo#4937 : The calculation of Revision should add the parameters of URL
    
    * Polish apache/dubbo#4940 : NacosDynamicConfiguration supports getConfigKeys method
    
    * Polish apache/dubbo#4942 : Dubbo Cloud Native supports multiple protcols
    
    * Polish apache/dubbo#4944 : [Feature] Simplify The metadata of URL for MetadataService
    
    * Polish apache/dubbo#4947 : [Feature] Dubbo Cloud-Native supports the REST call to Non-Dubbo
    
    * Merge remote-tracking branch 'upstream/cloud-native' into dubbo-cloud-native
    
    # Conflicts:
    #	dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java
    
    * Refactor
    
    * Update JavaDoc
    
    * Polish apache/dubbo#4905 : Add test cases for Configuration
    
    * Polish apache/dubbo#4905 : Add test cases for AbstractDynamicConfigurationFactory
    
    * Polish apache/dubbo#4905 : Add test cases for ConfigChangeType
    
    * Polish apache/dubbo#4905 : Add test cases for AbstractDynamicConfiguration
    
    * Polish apache/dubbo#4905 : Add test cases for ConfigChangedEvent
    
    * Polish apache/dubbo#4905 : Add test cases for ConfigChangedEvent
    
    * Polish apache/dubbo#4905 : Add test cases for FileSystemDynamicConfiguration
    
    * Polish apache/dubbo#4905 : Add test cases for FileSystemDynamicConfigurationFactory
    
    * Polish apache/dubbo#4905 : Enhancement the robustness for FileSystemDynamicConfiguration
    
    * Polish apache/dubbo#4905 : Add test cases for AdaptiveClassCodeGenerator
    
    * Polish apache/dubbo#4905 : Add test cases for ExtensionLoader
    
    * Polish apache/dubbo#4905 : Add test cases for ThrowableAction, ThrowableConsumer, ThrowableFunction
    
    * Polish apache/dubbo#4905 : Add test cases for Prioritized
    
    * Polish apache/dubbo#4905 : Add test cases for ShutdownHookCallbacks
    
    * Polish apache/dubbo#4905 : Add test cases for DubboServiceLoader
    
    * Polish apache/dubbo#4981 : Add dubbo-common
    
    * Polish apache/dubbo#4907 : Add test cases for DubboServiceDestroyedEvent
    
    * Polish apache/dubbo#4907 : Add test cases for DubboShutdownHookRegisteredEvent
    
    * Polish apache/dubbo#4907 : Add test cases for DubboShutdownHookUnregisteredEvent
    
    * Polish apache/dubbo#4907 : Add test cases for ReferenceConfigDestroyedEvent
    
    * Polish apache/dubbo#4907 : Add test cases for ReferenceConfigInitializedEvent
    
    * Polish apache/dubbo#4907 : Add test cases for ServiceInstancePortCustomizer
    
    * Polish apache/dubbo#4907 : Add test cases for ConfigurableMetadataServiceExporter
    
    * Polish apache/dubbo#4907 : bugfix for @EnableDubbo
    
    * Polish apache/dubbo#4907 : add test cases for @EnableDubboLifecycle
    
    * Update the version to be 2.7.5
    
    * Polish apache/dubbo#5034 : update
    
    * Polish apache/dubbo#5034 : Add TypeDefinition builders
    
    * Polish apache/dubbo#5034 : Complete TypeDefinition builders
    
    * Polish apache/dubbo#5034 : Add ModelUtils
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : Add Spring Web MVC
    
    * Polish apache/dubbo#5034 : Refactor
    
    * Polish apache/dubbo#5034 : bug fix
    
    * Polish apache/dubbo#5034 : Add test cases
    
    * Polish apache/dubbo#5034 : Add test cases
---
 dubbo-common/pom.xml                               |  13 +-
 .../org/apache/dubbo/common/convert/Converter.java |  55 +++
 .../dubbo/common/convert/StringConverter.java}     |  22 +-
 .../apache/dubbo/common/function/Predicates.java   | 115 +++++
 .../org/apache/dubbo/common/function/Streams.java  |  71 ++++
 .../dubbo/common/lang/ShutdownHookCallbacks.java   |   2 +-
 .../apache/dubbo/common/utils/CollectionUtils.java |  19 +
 ...ceLoader.java => PrioritizedServiceLoader.java} |   6 +-
 .../org/apache/dubbo/common/utils/StringUtils.java |  31 +-
 .../dubbo/common/utils/DubboServiceLoaderTest.java |   4 +-
 .../apache/dubbo/config/annotation/Service.java    |   1 +
 dubbo-dependencies-bom/pom.xml                     | 106 +++--
 dubbo-metadata/dubbo-metadata-api/pom.xml          |   2 +-
 .../dubbo/metadata/rest/RequestMetadata.java       | 225 ++++++++++
 .../dubbo/metadata/rest/RestMethodMetadata.java    | 187 +++++++++
 .../dubbo/metadata/rest/ServiceRestMetadata.java   | 103 +++++
 .../store/BaseWritableMetadataService.java         |   4 -
 .../RemoteWritableMetadataServiceDelegate.java     |   1 -
 .../org/apache/dubbo/metadata/util/HttpUtils.java  | 266 ++++++++++++
 .../report/identifier/MetadataIdentifierTest.java  |   1 -
 .../store/InMemoryWritableMetadataServiceTest.java |   1 -
 .../store/RemoteWritableMeatadataServiceTest.java  |   3 -
 dubbo-metadata/dubbo-metadata-processor/pom.xml    | 161 +++++++
 .../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  |  89 ++++
 .../AbstractAnnotatedMethodParameterProcessor.java |  52 +++
 .../rest/AbstractServiceRestMetadataProcessor.java | 232 ++++++++++
 .../rest/AnnotatedMethodParameterProcessor.java    |  62 +++
 .../rest/DefaultServiceRestMetadataProcessor.java  |  59 +++
 .../ServiceRestMetadataAnnotationProcessor.java    |  87 ++++
 .../rest/ServiceRestMetadataProcessor.java         |  53 +++
 .../rest/ServiceRestMetadataStorage.java           |  66 +++
 .../rest/jaxrs/DefaultValueParameterProcessor.java |  78 ++++
 .../rest/jaxrs/FormParamParameterProcessor.java    |  22 +-
 .../rest/jaxrs/HeaderParamParameterProcessor.java  |  50 +++
 .../jaxrs/JAXRSServiceRestMetadataProcessor.java   | 113 +++++
 .../rest/jaxrs/MatrixParamParameterProcessor.java  |  22 +-
 .../jaxrs/ParamAnnotationParameterProcessor.java   |  38 ++
 .../rest/jaxrs/QueryParamParameterProcessor.java   |  22 +-
 ...bstractRequestAnnotationParameterProcessor.java |  69 +++
 .../springmvc/RequestHeaderParameterProcessor.java |  41 ++
 .../springmvc/RequestParamParameterProcessor.java  |  42 ++
 .../SpringMvcServiceRestMetadataProcessor.java     | 157 +++++++
 .../processing/util/AnnotationUtils.java           | 233 ++++++++++
 .../annotation/processing/util/FieldUtils.java     | 146 +++++++
 .../annotation/processing/util/LoggerUtils.java    |  31 +-
 .../annotation/processing/util/MemberUtils.java    |  94 +++++
 .../annotation/processing/util/MethodUtils.java    | 155 +++++++
 .../processing/util/ServiceAnnotationUtils.java    | 121 ++++++
 .../annotation/processing/util/TypeUtils.java      | 382 +++++++++++++++++
 .../services/javax.annotation.processing.Processor |   2 +
 ...tation.processing.builder.TypeDefinitionBuilder |   7 +
 ...ocessing.rest.AnnotatedMethodParameterProcessor |  10 +
 ...on.processing.rest.ServiceRestMetadataProcessor |   3 +
 .../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           |  30 +-
 .../processing/model/CollectionTypeModel.java      |  34 +-
 .../annotation/processing/model/Color.java         |  38 +-
 .../annotation/processing/model/MapTypeModel.java  |  33 +-
 .../annotation/processing/model/Model.java         |  89 ++++
 .../processing/model/PrimitiveTypeModel.java       |  67 ++-
 .../processing/model/SimpleTypeModel.java          | 161 +++++++
 .../processing/util/AnnotationUtilsTest.java       | 232 ++++++++++
 .../annotation/processing/util/FieldUtilsTest.java | 259 ++++++++++++
 .../processing/util/LoggerUtilsTest.java           |  34 +-
 .../processing/util/MemberUtilsTest.java           | 113 +++++
 .../processing/util/MethodUtilsTest.java           | 195 +++++++++
 .../util/ServiceAnnotationUtilsTest.java           | 136 ++++++
 .../annotation/processing/util/TypeUtilsTest.java  | 467 +++++++++++++++++++++
 .../org/apache/dubbo/metadata/tools/Ancestor.java  |  29 +-
 .../org/apache/dubbo/metadata/tools/Compiler.java  | 116 +++++
 .../apache/dubbo/metadata/tools/CompilerTest.java  |  25 +-
 .../dubbo/metadata/tools/DefaultTestService.java   |  63 +++
 .../dubbo/metadata/tools/GenericTestService.java   |  26 +-
 .../org/apache/dubbo/metadata/tools/Parent.java    |  59 ++-
 .../apache/dubbo/metadata/tools/RestService.java   |  34 +-
 .../dubbo/metadata/tools/RestServiceTest.java      |  21 +-
 .../dubbo/metadata/tools/SpringRestService.java    |  97 +++++
 .../metadata/tools/SpringRestServiceTest.java      |  19 +-
 .../dubbo/metadata/tools/StandardRestService.java  | 107 +++++
 .../metadata/tools/StandardRestServiceTest.java    |  19 +-
 .../apache/dubbo/metadata/tools/TestProcessor.java |  46 ++
 .../apache/dubbo/metadata/tools/TestService.java   |  46 +-
 .../dubbo/metadata/tools/TestServiceImpl.java      |  37 +-
 .../java/org/apache/dubbo/metadata/tools/User.java |  61 +++
 dubbo-metadata/pom.xml                             |   1 +
 .../registry/client/ServiceDiscoveryRegistry.java  |   8 +-
 .../CustomizableServiceInstanceListener.java       |   2 +-
 108 files changed, 7985 insertions(+), 380 deletions(-)

diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml
index d988195..80d1ee3 100644
--- a/dubbo-common/pom.xml
+++ b/dubbo-common/pom.xml
@@ -15,7 +15,8 @@
   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>
@@ -31,11 +32,19 @@
         <skip_maven_deploy>false</skip_maven_deploy>
     </properties>
     <dependencies>
+
+        <!-- Java Extension Libs -->
+        <dependency>
+            <groupId>javax.annotation</groupId>
+            <artifactId>javax.annotation-api</artifactId>
+        </dependency>
+
         <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-api</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
             <groupId>commons-logging</groupId>
             <artifactId>commons-logging</artifactId>
@@ -44,11 +53,13 @@
             <groupId>log4j</groupId>
             <artifactId>log4j</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-api</artifactId>
             <scope>provided</scope>
         </dependency>
+
         <dependency>
             <groupId>org.apache.logging.log4j</groupId>
             <artifactId>log4j-core</artifactId>
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..c4e8dbc
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert;
+
+import org.apache.dubbo.common.lang.Prioritized;
+
+import java.util.function.Function;
+
+/**
+ * An interface converts an source instance of type {@link S} to an target instance of type {@link T}
+ *
+ * @param <S> the source type
+ * @param <T> the target type
+ * @since 2.7.5
+ */
+public interface Converter<S, T> extends Function<S, T>, Prioritized {
+
+    /**
+     * Tests whether or not the specified the source type and the target type
+     *
+     * @param sourceType the source type
+     * @param targetType the target type
+     * @return <code>true</code> if support to convert
+     */
+    default boolean accept(Class<S> sourceType, Class<T> targetType) {
+        return true;
+    }
+
+    /**
+     * Converts an source instance of type {@link S} to an target instance of type {@link T}
+     *
+     * @param source an source instance of type {@link S}
+     * @return an target instance of type {@link T}
+     */
+    T convert(S source);
+
+    @Override
+    default T apply(S s) {
+        return convert(s);
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
index b3b27e6..ddb99a1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/StringConverter.java
@@ -14,27 +14,13 @@
  * 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 java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.common.convert;
 
 /**
- * {@link DubboServiceLoader} Test
+ * A converter converts a {@link String} value to the target instance of type {@link T}
  *
+ * @param <T> the target type
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
+public interface StringConverter<T> extends Converter<String, T> {
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java
new file mode 100644
index 0000000..7bc1b48
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Predicates.java
@@ -0,0 +1,115 @@
+/*
+ * 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.function;
+
+import java.util.function.BiFunction;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+import static java.lang.Boolean.TRUE;
+import static java.util.stream.Stream.of;
+
+/**
+ * The utilities class for Java {@link Predicate}
+ *
+ * @since 2.7.5
+ */
+public interface Predicates {
+
+    Predicate[] EMPTY_ARRAY = new Predicate[0];
+
+    /**
+     * {@link Predicate} always return <code>true</code>
+     *
+     * @param <T> the type to test
+     * @return <code>true</code>
+     */
+    static <T> Predicate<T> alwaysTrue() {
+        return e -> true;
+    }
+
+    /**
+     * {@link Predicate} always return <code>false</code>
+     *
+     * @param <T> the type to test
+     * @return <code>false</code>
+     */
+    static <T> Predicate<T> alwaysFalse() {
+        return e -> false;
+    }
+
+
+    static <E, T> Predicate<T> map(Function<E, Predicate<T>> function, E element) {
+        return function.apply(element);
+    }
+
+    //
+//    static <E, T> Predicate<T> map(Function<E, Predicate<T>> function, E... elements) {
+//        return and(predicates(function, elements));
+//    }
+//
+
+    static <E, T> Predicate<T>[] predicates(Function<E, Predicate<T>> function, E... elements) {
+        return of(elements)
+                .map(e -> function.apply(e))
+                .toArray(Predicate[]::new);
+    }
+
+    static <E, T> Predicate<T>[] predicates(BiFunction<E, T, Predicate<T>> function, T value, E... elements) {
+        return of(elements)
+                .map(e -> function.apply(e, value))
+                .toArray(Predicate[]::new);
+    }
+
+    static <E, T> Predicate<T> predicate(BiFunction<E, T, Predicate<T>> function, T value, E... elements) {
+        return and(predicates(function, value, elements));
+    }
+
+    /**
+     * Convert a {@link Function} to {@link Predicate}
+     *
+     * @param function a {@link Function}
+     * @param <T>      the type to test
+     * @return non-null
+     */
+    static <T> Predicate<T> predicate(Function<T, Boolean> function) {
+        return t -> TRUE.equals(function.apply(t));
+    }
+
+    /**
+     * a composed predicate that represents a short-circuiting logical AND of {@link Predicate predicates}
+     *
+     * @param predicates {@link Predicate predicates}
+     * @param <T>        the type to test
+     * @return non-null
+     */
+    static <T> Predicate<T> and(Predicate<T>... predicates) {
+        return of(predicates).reduce((a, b) -> a.and(b)).orElseGet(Predicates::alwaysTrue);
+    }
+
+    /**
+     * a composed predicate that represents a short-circuiting logical OR of {@link Predicate predicates}
+     *
+     * @param predicates {@link Predicate predicates}
+     * @param <T>        the detected type
+     * @return non-null
+     */
+    static <T> Predicate<T> or(Predicate<T>... predicates) {
+        return of(predicates).reduce((a, b) -> a.or(b)).orElse(e -> true);
+    }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.java b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.java
new file mode 100644
index 0000000..65e4fa6
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/function/Streams.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.function;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import static java.util.stream.Collectors.toList;
+import static java.util.stream.StreamSupport.stream;
+import static org.apache.dubbo.common.function.Predicates.and;
+import static org.apache.dubbo.common.function.Predicates.or;
+
+/**
+ * The utilities class for {@link Stream}
+ *
+ * @since 2.7.5
+ */
+public interface Streams {
+
+    static <T, S extends Iterable<T>> Stream<T> filterStream(S values, Predicate<T> predicate) {
+        return stream(values.spliterator(), false).filter(predicate);
+    }
+
+    static <T, S extends Iterable<T>> List<T> filterList(S values, Predicate<T> predicate) {
+        return filterStream(values, predicate).collect(toList());
+    }
+
+    static <T, S extends Iterable<T>> Set<T> filterSet(S values, Predicate<T> predicate) {
+        // new Set with insertion order
+        return filterStream(values, predicate).collect(LinkedHashSet::new, Set::add, Set::addAll);
+    }
+
+    static <T, S extends Iterable<T>> S filter(S values, Predicate<T> predicate) {
+        final boolean isSet = Set.class.isAssignableFrom(values.getClass());
+        return (S) (isSet ? filterSet(values, predicate) : filterList(values, predicate));
+    }
+
+    static <T, S extends Iterable<T>> S filterAll(S values, Predicate<T>... predicates) {
+        return filter(values, and(predicates));
+    }
+
+    static <T, S extends Iterable<T>> S filterAny(S values, Predicate<T>... predicates) {
+        return filter(values, or(predicates));
+    }
+
+    static <T> T filterFirst(Iterable<T> values, Predicate<T>... predicates) {
+        return stream(values.spliterator(), false)
+                .filter(and(predicates))
+                .findFirst()
+                .orElse(null);
+    }
+}
+
+
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
index a5555e8..41d6dee 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
@@ -22,7 +22,7 @@ import java.util.List;
 
 import static java.util.Collections.sort;
 import static org.apache.dubbo.common.function.ThrowableAction.execute;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.load;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
 
 /**
  * The compose {@link ShutdownHookCallback} class to manipulate one and more {@link ShutdownHookCallback} instances
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 40baecd..d3d8cc0 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
@@ -21,8 +21,14 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
+import java.util.HashSet;
 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;
 
 public class CollectionUtils {
 
@@ -217,4 +223,17 @@ public class CollectionUtils {
         return !isEmptyMap(map);
     }
 
+    /**
+     * Convert to multiple values to be {@link HashSet}
+     *
+     * @param values one or more values
+     * @param <T>    the type of <code>values</code>
+     * @return read-only {@link HashSet}
+     */
+    public static <T> Set<T> asHashSet(T... values) {
+        if (values == null || values.length < 1) {
+            return emptySet();
+        }
+        return unmodifiableSet(new HashSet(asList(values)));
+    }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
similarity index 95%
rename from dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
index 637440a..dcbcd27 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/DubboServiceLoader.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PrioritizedServiceLoader.java
@@ -27,13 +27,13 @@ import static java.util.stream.Collectors.toList;
 import static java.util.stream.StreamSupport.stream;
 
 /**
- * An extension class of {@link ServiceLoader} to help the ease for use of Dubbo services/components
+ * An extension class of {@link ServiceLoader} with {@link Prioritized} feature
  *
  * @see ServiceLoader
  * @see Prioritized
  * @since 2.7.5
  */
-public class DubboServiceLoader {
+public interface PrioritizedServiceLoader {
 
     /**
      * Load a {@link Stream stream} of services by the specified {@link Class type} and {@link ClassLoader}
@@ -51,7 +51,7 @@ public class DubboServiceLoader {
 
         ClassLoader actualClassLoader = classLoader;
         if (actualClassLoader == null) {
-            actualClassLoader = DubboServiceLoader.class.getClassLoader();
+            actualClassLoader = PrioritizedServiceLoader.class.getClassLoader();
         }
 
         ServiceLoader<S> serviceLoader = ServiceLoader.load(serviceClass, actualClassLoader);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
index 53557a3..c3d81a1 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
@@ -32,6 +32,7 @@ import java.util.TreeMap;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import static java.lang.String.valueOf;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
 import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX;
@@ -57,6 +58,34 @@ public final class StringUtils {
     private static final Pattern INT_PATTERN = Pattern.compile("^\\d+$");
     private static final int PAD_LIMIT = 8192;
 
+    /**
+     * @since 2.7.5
+     */
+    public static final char EQUAL_CHAR = '=';
+
+    public static final String EQUAL = valueOf(EQUAL_CHAR);
+
+    public static final char AND_CHAR = '&';
+
+    public static final String AND = valueOf(AND_CHAR);
+
+    public static final char SEMICOLON_CHAR = ';';
+
+    public static final String SEMICOLON = valueOf(SEMICOLON_CHAR);
+
+    public static final char QUESTION_MASK_CHAR = '?';
+
+    public static final String QUESTION_MASK = valueOf(QUESTION_MASK_CHAR);
+
+    public static final char SLASH_CHAR = '/';
+
+    public static final String SLASH = valueOf(SLASH_CHAR);
+
+    /**
+     * The empty value
+     */
+    public static final String EMPTY_VALUE = "";
+
     private StringUtils() {
     }
 
@@ -819,7 +848,7 @@ public final class StringUtils {
         if (str != null && !isEmpty(str)) {
             int sz = str.length();
 
-            for(int i = 0; i < sz; ++i) {
+            for (int i = 0; i < sz; ++i) {
                 if (!Character.isUpperCase(str.charAt(i))) {
                     return false;
                 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
index b3b27e6..d2d0cf6 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
@@ -20,11 +20,11 @@ import org.junit.jupiter.api.Test;
 
 import java.util.List;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link PrioritizedServiceLoader} Test
  *
  * @since 2.7.5
  */
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
index 8b13373..867d5d8 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/annotation/Service.java
@@ -274,6 +274,7 @@ public @interface Service {
 
     /**
      * methods support
+     *
      * @return
      */
     Method[] methods() default {};
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index 3c5b432..f95cee2 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -89,6 +89,16 @@
     </issueManagement>
 
     <properties>
+        <!-- Java Extension Libs -->
+        <servlet_version>3.1.0</servlet_version>
+        <annotation_version>1.3.1</annotation_version>
+        <validation_version>1.1.0.Final</validation_version>
+        <rs_api_version>2.0</rs_api_version>
+        <jcache_version>1.0.0</jcache_version>
+        <jaxb_version>2.2.7</jaxb_version>
+        <activation_version>1.2.0</activation_version>
+        <portlet_version>2.0</portlet_version>
+
         <!-- Common libs -->
         <spring_version>4.3.16.RELEASE</spring_version>
         <javassist_version>3.20.0-GA</javassist_version>
@@ -110,12 +120,10 @@
         <thrift_version>0.12.0</thrift_version>
         <hessian_version>4.0.38</hessian_version>
         <protobuf-java_version>3.6.0</protobuf-java_version>
-        <servlet_version>3.1.0</servlet_version>
+
         <jetty_version>9.4.11.v20180605</jetty_version>
-        <validation_version>1.1.0.Final</validation_version>
         <hibernate_validator_version>5.4.1.Final</hibernate_validator_version>
         <jel_version>3.0.1-b08</jel_version>
-        <jcache_version>1.0.0</jcache_version>
         <kryo_version>4.0.1</kryo_version>
         <kryo_serializers_version>0.42</kryo_serializers_version>
         <fst_version>2.48-jdk-6</fst_version>
@@ -125,7 +133,6 @@
         <commons_lang3_version>3.8.1</commons_lang3_version>
         <protostuff_version>1.5.9</protostuff_version>
 
-        <rs_api_version>2.0</rs_api_version>
         <resteasy_version>3.0.19.Final</resteasy_version>
         <tomcat_embed_version>8.5.31</tomcat_embed_version>
         <jetcd_version>0.3.0</jetcd_version>
@@ -144,8 +151,6 @@
         <!-- Eureka -->
         <eureka.version>1.9.12</eureka.version>
 
-        <jaxb_version>2.2.7</jaxb_version>
-        <activation_version>1.2.0</activation_version>
         <test_container_version>1.11.2</test_container_version>
         <etcd_launcher_version>0.3.0</etcd_launcher_version>
         <hessian_lite_version>3.2.5</hessian_lite_version>
@@ -157,13 +162,62 @@
         <gson_version>2.8.5</gson_version>
         <jsonrpc_version>1.2.0</jsonrpc_version>
         <mortbay_jetty_version>6.1.26</mortbay_jetty_version>
-        <portlet_version>2.0</portlet_version>
         <maven_flatten_version>1.1.0</maven_flatten_version>
         <revision>2.7.5-cloudnative-SNAPSHOT</revision>
     </properties>
 
     <dependencyManagement>
         <dependencies>
+
+            <!-- Java Extension Libs -->
+            <dependency>
+                <groupId>javax.servlet</groupId>
+                <artifactId>javax.servlet-api</artifactId>
+                <version>${servlet_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.annotation</groupId>
+                <artifactId>javax.annotation-api</artifactId>
+                <version>${annotation_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.validation</groupId>
+                <artifactId>validation-api</artifactId>
+                <version>${validation_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.cache</groupId>
+                <artifactId>cache-api</artifactId>
+                <version>${jcache_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.ws.rs</groupId>
+                <artifactId>javax.ws.rs-api</artifactId>
+                <version>${rs_api_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.xml.bind</groupId>
+                <artifactId>jaxb-api</artifactId>
+                <version>${jaxb_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.activation</groupId>
+                <artifactId>javax.activation-api</artifactId>
+                <version>${activation_version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>javax.portlet</groupId>
+                <artifactId>portlet-api</artifactId>
+                <version>${portlet_version}</version>
+            </dependency>
+
             <!-- Common libs -->
             <dependency>
                 <groupId>org.springframework</groupId>
@@ -311,11 +365,7 @@
                 <artifactId>protobuf-java-util</artifactId>
                 <version>${protobuf-java_version}</version>
             </dependency>
-            <dependency>
-                <groupId>javax.servlet</groupId>
-                <artifactId>javax.servlet-api</artifactId>
-                <version>${servlet_version}</version>
-            </dependency>
+
             <dependency>
                 <groupId>org.eclipse.jetty</groupId>
                 <artifactId>jetty-server</artifactId>
@@ -332,11 +382,7 @@
                 <version>${mortbay_jetty_version}</version>
                 <optional>true</optional>
             </dependency>
-            <dependency>
-                <groupId>javax.validation</groupId>
-                <artifactId>validation-api</artifactId>
-                <version>${validation_version}</version>
-            </dependency>
+
             <dependency>
                 <groupId>org.hibernate</groupId>
                 <artifactId>hibernate-validator</artifactId>
@@ -348,11 +394,6 @@
                 <version>${jel_version}</version>
             </dependency>
             <dependency>
-                <groupId>javax.cache</groupId>
-                <artifactId>cache-api</artifactId>
-                <version>${jcache_version}</version>
-            </dependency>
-            <dependency>
                 <groupId>com.esotericsoftware</groupId>
                 <artifactId>kryo</artifactId>
                 <version>${kryo_version}</version>
@@ -383,11 +424,6 @@
                 <version>${protostuff_version}</version>
             </dependency>
             <dependency>
-                <groupId>javax.ws.rs</groupId>
-                <artifactId>javax.ws.rs-api</artifactId>
-                <version>${rs_api_version}</version>
-            </dependency>
-            <dependency>
                 <groupId>org.jboss.resteasy</groupId>
                 <artifactId>resteasy-jaxrs</artifactId>
                 <version>${resteasy_version}</version>
@@ -513,11 +549,6 @@
 
             <!-- for dubbo-rpc-webservice -->
             <dependency>
-                <groupId>javax.xml.bind</groupId>
-                <artifactId>jaxb-api</artifactId>
-                <version>${jaxb_version}</version>
-            </dependency>
-            <dependency>
                 <groupId>com.sun.xml.bind</groupId>
                 <artifactId>jaxb-impl</artifactId>
                 <version>${jaxb_version}</version>
@@ -527,11 +558,7 @@
                 <artifactId>jaxb-core</artifactId>
                 <version>${jaxb_version}</version>
             </dependency>
-            <dependency>
-                <groupId>javax.activation</groupId>
-                <artifactId>javax.activation-api</artifactId>
-                <version>${activation_version}</version>
-            </dependency>
+
             <dependency>
                 <groupId>com.sun.activation</groupId>
                 <artifactId>javax.activation</artifactId>
@@ -620,11 +647,6 @@
                 <artifactId>jsonrpc4j</artifactId>
                 <version>${jsonrpc_version}</version>
             </dependency>
-            <dependency>
-                <groupId>javax.portlet</groupId>
-                <artifactId>portlet-api</artifactId>
-                <version>${portlet_version}</version>
-            </dependency>
             <!-- for dubbo-configcenter-etcd -->
             <dependency>
                 <groupId>io.etcd</groupId>
diff --git a/dubbo-metadata/dubbo-metadata-api/pom.xml b/dubbo-metadata/dubbo-metadata-api/pom.xml
index 8c9a80c..cb3002a 100644
--- a/dubbo-metadata/dubbo-metadata-api/pom.xml
+++ b/dubbo-metadata/dubbo-metadata-api/pom.xml
@@ -44,7 +44,7 @@
             <artifactId>dubbo-cluster</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
-        
+
         <dependency>
             <groupId>com.google.code.gson</groupId>
             <artifactId>gson</artifactId>
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..830840d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RequestMetadata.java
@@ -0,0 +1,225 @@
+/*
+ * 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.StringUtils.isBlank;
+import static org.apache.dubbo.metadata.util.HttpUtils.normalizePath;
+
+/**
+ * The metadata class for REST request
+ *
+ * @since 2.7.5
+ */
+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 this.getFirst(params, name);
+    }
+
+    public String getHeader(String name) {
+        return this.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/RestMethodMetadata.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
new file mode 100644
index 0000000..e43fce7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/rest/RestMethodMetadata.java
@@ -0,0 +1,187 @@
+/*
+ * 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.5
+ */
+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) {
+        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(getIndexToName(), that.getIndexToName()) &&
+                Objects.equals(getFormParams(), that.getFormParams()) &&
+                Objects.equals(getIndexToEncoded(), that.getIndexToEncoded());
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(getMethod(), getRequest(), getUrlIndex(), getBodyIndex(), getHeaderMapIndex(), getBodyType(), getIndexToName(), 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..34cddd6
--- /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.5
+ */
+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/store/BaseWritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
index c751226..764d035 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/BaseWritableMetadataService.java
@@ -4,17 +4,13 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.MetadataService;
-import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
 
 import java.util.Collection;
 import java.util.Map;
 import java.util.SortedSet;
 import java.util.concurrent.ConcurrentNavigableMap;
 import java.util.concurrent.ConcurrentSkipListMap;
-import java.util.function.BiConsumer;
 import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
 
 /**
  * @author cvictory ON 2019-08-14
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
index eed9e43..448ddc8 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/store/RemoteWritableMetadataServiceDelegate.java
@@ -1,7 +1,6 @@
 package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.InmemoryConfiguration;
 import org.apache.dubbo.metadata.WritableMetadataService;
 
 import java.util.SortedSet;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java
new file mode 100644
index 0000000..20095a4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/util/HttpUtils.java
@@ -0,0 +1,266 @@
+/*
+ * 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.util;
+
+
+import org.apache.dubbo.common.utils.StringUtils;
+
+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.5
+ */
+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-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
index 90df3db..3a58933 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.metadata.report.identifier;
 
 import org.apache.dubbo.metadata.MetadataConstants;
-import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.Test;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
index c032843..2bd9137 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/InMemoryWritableMetadataServiceTest.java
@@ -2,7 +2,6 @@ package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.metadata.report.MetadataReportInstance;
 
 import org.junit.jupiter.api.Assertions;
 import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
index b6dfa48..94cc577 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/store/RemoteWritableMeatadataServiceTest.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.metadata.store;
 
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.metadata.WritableMetadataService;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
 import org.apache.dubbo.metadata.report.MetadataReportInstance;
 import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
@@ -34,8 +33,6 @@ import org.junit.jupiter.api.Test;
 
 import java.util.Map;
 
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
-
 /**
  * 2018/9/14
  */
diff --git a/dubbo-metadata/dubbo-metadata-processor/pom.xml b/dubbo-metadata/dubbo-metadata-processor/pom.xml
new file mode 100644
index 0000000..9be4ddb
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/pom.xml
@@ -0,0 +1,161 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<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..e5af1ad
--- /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.5
+ */
+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);
+    }
+
+    private FileObject createResource(String resourceName) throws IOException {
+        return filer.createResource(CLASS_OUTPUT, "", resourceName);
+    }
+
+    private Optional<FileObject> getResource(String resourceName) {
+        try {
+            FileObject fileObject = filer.getResource(CLASS_OUTPUT, "", resourceName);
+            return ofNullable(fileObject);
+        } catch (IOException e) {
+            warn(e.getMessage());
+        }
+        return empty();
+    }
+
+    private Writer getWriter(String resourceName) throws IOException {
+        FileObject fileObject = createResource(resourceName);
+        info("The resource[path : %s , deleted : %s] will be written", fileObject.toUri().getPath(), fileObject.delete());
+        return fileObject.openWriter();
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.java
new file mode 100644
index 0000000..837cdec
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/ServiceDefinitionMetadataAnnotationProcessor.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.metadata.annotation.processing;
+
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+
+import com.google.gson.Gson;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.typesIn;
+import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
+
+/**
+ * The {@link Processor} class to generate the metadata of {@link ServiceDefinition} whose classes are annotated by Dubbo's @Service
+ *
+ * @see Processor
+ * @since 2.7.5
+ */
+public class ServiceDefinitionMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
+
+    private List<ServiceDefinition> serviceDefinitions = new LinkedList<>();
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+        typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
+
+        if (roundEnv.processingOver()) {
+            ClassPathMetadataStorage writer = new ClassPathMetadataStorage(processingEnv);
+            writer.write(() -> new Gson().toJson(serviceDefinitions), "META-INF/dubbo/service-definitions.json");
+        }
+
+        return false;
+    }
+
+    private void process(ProcessingEnvironment processingEnv, TypeElement serviceType, Set<? extends TypeElement> annotations) {
+        serviceDefinitions.add(build(processingEnv, serviceType));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java
new file mode 100644
index 0000000..d7ebc3a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilder.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeMirror;
+import java.lang.reflect.Array;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Array}
+ *
+ * @since 2.7.5
+ */
+public class ArrayTypeDefinitionBuilder implements TypeDefinitionBuilder<ArrayType> {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+        return isArrayType(type);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, ArrayType type, TypeDefinition typeDefinition) {
+        TypeMirror componentType = type.getComponentType();
+        typeDefinition.getItems().add(TypeDefinitionBuilder.build(processingEnv, componentType));
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 4;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.java
new file mode 100644
index 0000000..3ed2b45
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilder.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.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.Collection;
+import java.util.Objects;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Collection}
+ *
+ * @since 2.7.5
+ */
+public class CollectionTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+        Elements elements = processingEnv.getElementUtils();
+        TypeElement collectionTypeElement = elements.getTypeElement(Collection.class.getTypeName());
+        TypeMirror collectionType = collectionTypeElement.asType();
+        Types types = processingEnv.getTypeUtils();
+        TypeMirror erasedType = types.erasure(type);
+        return types.isAssignable(erasedType, collectionType);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+        // Generic Type arguments
+        type.getTypeArguments()
+                .stream()
+                .map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
+                .filter(Objects::nonNull)
+                .forEach(typeDefinition.getItems()::add);                              // Add into the declared TypeDefinition
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 5;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.java
new file mode 100644
index 0000000..b12dcef
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/DeclaredTypeDefinitionBuilder.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.annotation.processing.builder;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+
+/**
+ * An interface of {@link TypeDefinitionBuilder} for {@link DeclaredType}
+ *
+ * @since 2.7.5
+ */
+public interface DeclaredTypeDefinitionBuilder extends TypeDefinitionBuilder<DeclaredType> {
+
+    @Override
+    default boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        if (declaredType == null) {
+            return false;
+        }
+        return accept(processingEnv, declaredType);
+    }
+
+    /**
+     * Test the specified {@link DeclaredType type} is accepted or not
+     *
+     * @param processingEnv {@link ProcessingEnvironment}
+     * @param type          {@link DeclaredType type}
+     * @return <code>true</code> if accepted
+     */
+    boolean accept(ProcessingEnvironment processingEnv, DeclaredType type);
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.java
new file mode 100644
index 0000000..c0ed002
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilder.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.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.util.FieldUtils;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Enum}
+ *
+ * @since 2.7.5
+ */
+public class EnumTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+        return isEnumType(type);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+        getDeclaredFields(type, FieldUtils::isEnumMemberField)
+                .stream()
+                .map(Element::getSimpleName)
+                .map(Name::toString)
+                .forEach(typeDefinition.getEnums()::add);
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 2;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java
new file mode 100644
index 0000000..f9c648c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilder.java
@@ -0,0 +1,65 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
+
+/**
+ * {@link TypeDefinitionBuilder} for General Object
+ *
+ * @since 2.7.5
+ */
+public class GeneralTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+        return isClassType(type);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+
+        String typeName = type.toString();
+
+        TypeElement typeElement = getType(processingEnv, typeName);
+
+        buildProperties(processingEnv, typeElement, typeDefinition);
+    }
+
+    protected void buildProperties(ProcessingEnvironment processingEnv, TypeElement type, TypeDefinition definition) {
+        getNonStaticFields(type).forEach(field -> {
+            String fieldName = field.getSimpleName().toString();
+            TypeDefinition propertyType = TypeDefinitionBuilder.build(processingEnv, field);
+            if (propertyType != null) {
+                definition.getProperties().put(fieldName, propertyType);
+            }
+        });
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.java
new file mode 100644
index 0000000..a0a204d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilder.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.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link Map}
+ *
+ * @since 2.7.5
+ */
+public class MapTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+        Elements elements = processingEnv.getElementUtils();
+        TypeElement mapTypeElement = elements.getTypeElement(Map.class.getTypeName());
+        TypeMirror mapType = mapTypeElement.asType();
+        Types types = processingEnv.getTypeUtils();
+        TypeMirror erasedType = types.erasure(type);
+        return types.isAssignable(erasedType, mapType);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+        // Generic Type arguments
+        type.getTypeArguments()
+                .stream()
+                .map(typeArgument -> TypeDefinitionBuilder.build(processingEnv, typeArgument)) // build the TypeDefinition from typeArgument
+                .filter(Objects::nonNull)
+                .forEach(typeDefinition.getItems()::add);                              // Add into the declared TypeDefinition
+
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 6;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java
new file mode 100644
index 0000000..c2bad78
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/MethodDefinitionBuilder.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import java.util.List;
+import java.util.stream.Collectors;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getReturnType;
+
+/**
+ * A Builder class for {@link MethodDefinition}
+ *
+ * @see MethodDefinition
+ * @since 2.7.5
+ */
+public interface MethodDefinitionBuilder {
+
+    static MethodDefinition build(ProcessingEnvironment processingEnv, ExecutableElement method) {
+        MethodDefinition methodDefinition = new MethodDefinition();
+        methodDefinition.setName(getMethodName(method));
+        methodDefinition.setReturnType(getReturnType(method));
+        methodDefinition.setParameterTypes(getMethodParameterTypes(method));
+        methodDefinition.setParameters(getMethodParameters(processingEnv, method));
+        return methodDefinition;
+    }
+
+    static List<TypeDefinition> getMethodParameters(ProcessingEnvironment processingEnv, ExecutableElement method) {
+        return method.getParameters().stream()
+                .map(element -> TypeDefinitionBuilder.build(processingEnv, element))
+                .collect(Collectors.toList());
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java
new file mode 100644
index 0000000..903c15f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilder.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.PrimitiveType;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
+
+/**
+ * {@link TypeDefinitionBuilder} for Java {@link PrimitiveType primitve type}
+ *
+ * @since 2.7.5
+ */
+public class PrimitiveTypeDefinitionBuilder implements TypeDefinitionBuilder<PrimitiveType> {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, TypeMirror type) {
+        return isPrimitiveType(type);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, PrimitiveType type, TypeDefinition typeDefinition) {
+        // DO NOTHING
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 3;
+    }
+}
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java
new file mode 100644
index 0000000..8563e00
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilder.java
@@ -0,0 +1,56 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
+
+/**
+ * A Builder for {@link ServiceDefinition}
+ *
+ * @see ServiceDefinition
+ * @since 2.7.5
+ */
+public interface ServiceDefinitionBuilder {
+
+    static ServiceDefinition build(ProcessingEnvironment processingEnv, TypeElement type) {
+        ServiceDefinition serviceDefinition = new ServiceDefinition();
+        serviceDefinition.setCanonicalName(type.toString());
+        serviceDefinition.setCodeSource(getResourceName(type.toString()));
+
+        // Get all super types and interface excluding the specified type
+        // and then the result will be added into ServiceDefinition#getTypes()
+        getHierarchicalTypes(type.asType(), Object.class)
+                .stream()
+                .map(t -> TypeDefinitionBuilder.build(processingEnv, t))
+                .forEach(serviceDefinition.getTypes()::add);
+
+        // Get all declared methods that will be added into ServiceDefinition#getMethods()
+        getPublicNonStaticMethods(type, Object.class)
+                .stream()
+                .map(method -> MethodDefinitionBuilder.build(processingEnv, method))
+                .forEach(serviceDefinition.getMethods()::add);
+
+        return serviceDefinition;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.java
new file mode 100644
index 0000000..634d7be
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilder.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.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.util.TypeUtils;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.type.DeclaredType;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
+
+
+/**
+ * {@link TypeDefinitionBuilder} for {@link TypeUtils#SIMPLE_TYPES Java Simple Type}
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeDefinitionBuilder implements DeclaredTypeDefinitionBuilder {
+
+    @Override
+    public boolean accept(ProcessingEnvironment processingEnv, DeclaredType type) {
+        return isSimpleType(type);
+    }
+
+    @Override
+    public void build(ProcessingEnvironment processingEnv, DeclaredType type, TypeDefinition typeDefinition) {
+        //  DO NOTHING
+    }
+
+    @Override
+    public int getPriority() {
+        return MIN_PRIORITY - 1;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java
new file mode 100644
index 0000000..415754b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/builder/TypeDefinitionBuilder.java
@@ -0,0 +1,89 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.type.TypeMirror;
+
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
+
+/**
+ * A class builds the instance of {@link TypeDefinition}
+ *
+ * @since 2.7.5
+ */
+public interface TypeDefinitionBuilder<T extends TypeMirror> extends Prioritized {
+
+    /**
+     * Test the specified {@link TypeMirror type} is accepted or not
+     *
+     * @param processingEnv {@link ProcessingEnvironment}
+     * @param type          {@link TypeMirror type}
+     * @return <code>true</code> if accepted
+     */
+    boolean accept(ProcessingEnvironment processingEnv, TypeMirror type);
+
+    /**
+     * Build the instance of {@link TypeDefinition}
+     *
+     * @param processingEnv  {@link ProcessingEnvironment}
+     * @param type           {@link T type}
+     * @param typeDefinition {@link TypeDefinition} to be built
+     * @return an instance of {@link TypeDefinition}
+     */
+    void build(ProcessingEnvironment processingEnv, T type, TypeDefinition typeDefinition);
+
+    /**
+     * Build the instance of {@link TypeDefinition} from the specified {@link Element element}
+     *
+     * @param processingEnv {@link ProcessingEnvironment}
+     * @param element       {@link Element source element}
+     * @return non-null
+     */
+    static TypeDefinition build(ProcessingEnvironment processingEnv, Element element) {
+        TypeDefinition typeDefinition = build(processingEnv, element.asType());
+        typeDefinition.set$ref(element.toString());
+        return typeDefinition;
+    }
+
+    /**
+     * Build the instance of {@link TypeDefinition} from the specified {@link TypeMirror type}
+     *
+     * @param processingEnv {@link ProcessingEnvironment}
+     * @param type          {@link TypeMirror type}
+     * @return non-null
+     */
+    static TypeDefinition build(ProcessingEnvironment processingEnv, TypeMirror type) {
+        String typeName = type.toString();
+        TypeDefinition typeDefinition = new TypeDefinition(typeName);
+
+        // Build by all instances of TypeDefinitionBuilder that were loaded By Java SPI
+        load(TypeDefinitionBuilder.class, TypeDefinitionBuilder.class.getClassLoader())
+                .filter(builder -> builder.accept(processingEnv, type))
+                .findFirst()
+                .ifPresent(builder -> {
+                    builder.build(processingEnv, type, typeDefinition);
+                    // typeDefinition.setTypeBuilderName(builder.getClass().getName());
+                });
+
+        return typeDefinition;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..51ef786
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractAnnotatedMethodParameterProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractAnnotatedMethodParameterProcessor implements AnnotatedMethodParameterProcessor {
+
+    @Override
+    public final void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+        String annotationValue = getAnnotationValue(annotation, parameter, parameterIndex);
+        String defaultValue = getDefaultValue(annotation, parameter, parameterIndex);
+        process(annotationValue, defaultValue, annotation, parameter, parameterIndex, method, restMethodMetadata);
+    }
+
+    protected abstract void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
+                                    ExecutableElement method, RestMethodMetadata restMethodMetadata);
+
+    protected String getAnnotationValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+        return getValue(annotation);
+    }
+
+    protected String getDefaultValue(AnnotationMirror annotation, VariableElement parameter, int parameterIndex) {
+        return buildDefaultValue(parameterIndex);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..36fee79
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AbstractServiceRestMetadataProcessor.java
@@ -0,0 +1,232 @@
+/*
+ * 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.rest;
+
+import org.apache.dubbo.metadata.definition.model.MethodDefinition;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import static java.lang.ThreadLocal.withInitial;
+import static java.util.Collections.emptyList;
+import static java.util.Optional.empty;
+import static java.util.Optional.of;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
+import static org.apache.dubbo.metadata.annotation.processing.builder.MethodDefinitionBuilder.build;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getGroup;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getVersion;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.resolveServiceInterfaceName;
+
+/**
+ * Abstract {@link ServiceRestMetadataProcessor} implementation
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractServiceRestMetadataProcessor implements ServiceRestMetadataProcessor {
+
+    private final static ThreadLocal<Map<String, Object>> threadLocalCache = withInitial(HashMap::new);
+
+    private final static Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = loadAnnotatedMethodParameterProcessors();
+
+    private final String processorName = getClass().getSimpleName();
+
+    @Override
+    public final ServiceRestMetadata process(ProcessingEnvironment processingEnv,
+                                             TypeElement serviceType,
+                                             Set<? extends TypeElement> annotations) {
+
+        info("%s is processing the service type[%s] with annotations[%s]", processorName, serviceType,
+                annotations.stream().map(t -> "@" + t.toString()).collect(Collectors.joining(",")));
+
+        ServiceRestMetadata serviceRestMetadata = new ServiceRestMetadata();
+
+        try {
+            AnnotationMirror serviceAnnotation = getAnnotation(serviceType);
+            serviceRestMetadata.setServiceInterface(resolveServiceInterfaceName(serviceType, serviceAnnotation));
+            serviceRestMetadata.setGroup(getGroup(serviceAnnotation));
+            serviceRestMetadata.setVersion(getVersion(serviceAnnotation));
+
+            List<? extends ExecutableElement> methods = getPublicNonStaticMethods(serviceType, Object.class);
+
+            methods.forEach(method -> {
+                processRestMethodMetadata(processingEnv, serviceType, method)
+                        .ifPresent(serviceRestMetadata.getMeta()::add);
+            });
+        } finally {
+            clearCache();
+        }
+
+        info("The %s's process result : %s", processorName, serviceRestMetadata);
+
+        return serviceRestMetadata;
+    }
+
+    protected Optional<RestMethodMetadata> processRestMethodMetadata(ProcessingEnvironment processingEnv,
+                                                                     TypeElement serviceType, ExecutableElement method) {
+
+        String requestPath = getRequestPath(processingEnv, serviceType, method); // requestPath is required
+
+        if (requestPath == null) {
+            return empty();
+        }
+
+        String requestMethod = getRequestMethod(processingEnv, serviceType, method); // requestMethod is required
+
+        if (requestMethod == null) {
+            return empty();
+        }
+
+        RestMethodMetadata metadata = new RestMethodMetadata();
+
+        MethodDefinition methodDefinition = getMethodDefinition(processingEnv, serviceType, method);
+        // Set MethodDefinition
+        metadata.setMethod(methodDefinition);
+
+        // process the annotated method parameters
+        processAnnotatedMethodParameters(method, serviceType, metadata);
+
+        // process produces
+        Set<String> produces = new LinkedHashSet<>();
+        processProduces(processingEnv, serviceType, method, produces);
+
+        // process consumes
+        Set<String> consumes = new LinkedHashSet<>();
+        processConsumes(processingEnv, serviceType, method, consumes);
+
+        // Initialize RequestMetadata
+        RequestMetadata request = metadata.getRequest();
+        request.setPath(requestPath);
+        request.setMethod(requestMethod);
+        request.setProduces(produces);
+        request.setConsumes(consumes);
+
+        // Post-Process
+        postProcessRestMethodMetadata(processingEnv, serviceType, method, metadata);
+
+        return of(metadata);
+    }
+
+    /**
+     * Post-Process for {@link RestMethodMetadata}, sub-type could override this method for further works
+     *
+     * @param processingEnv {@link ProcessingEnvironment}
+     * @param serviceType   The type that @Service annotated
+     * @param method        The public method of <code>serviceType</code>
+     * @param metadata      {@link RestMethodMetadata} maybe updated
+     */
+    protected void postProcessRestMethodMetadata(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                                 ExecutableElement method, RestMethodMetadata metadata) {
+    }
+
+    protected abstract String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                             ExecutableElement method);
+
+    protected abstract String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                               ExecutableElement method);
+
+    protected MethodDefinition getMethodDefinition(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                                   ExecutableElement method) {
+        return build(processingEnv, method);
+    }
+
+    protected void processAnnotatedMethodParameters(ExecutableElement method, TypeElement type,
+                                                    RestMethodMetadata metadata) {
+        List<? extends VariableElement> methodParameters = method.getParameters();
+        int size = methodParameters.size();
+        for (int i = 0; i < size; i++) {
+            VariableElement parameter = methodParameters.get(i);
+            // Add indexed parameter name
+            metadata.addIndexToName(i, parameter.getSimpleName().toString());
+            processAnnotatedMethodParameter(parameter, i, method, type, metadata);
+        }
+    }
+
+    protected void processAnnotatedMethodParameter(VariableElement parameter, int parameterIndex,
+                                                   ExecutableElement method, TypeElement serviceType,
+                                                   RestMethodMetadata metadata) {
+
+        parameter.getAnnotationMirrors().forEach(annotation -> {
+            String annotationType = annotation.getAnnotationType().toString();
+            parameterProcessorsMap.getOrDefault(annotationType, emptyList())
+                    .forEach(parameterProcessor -> {
+                        parameterProcessor.process(annotation, parameter, parameterIndex, method, metadata);
+                    });
+        });
+    }
+
+    protected abstract void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                            ExecutableElement method, Set<String> produces);
+
+    protected abstract void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                            ExecutableElement method, Set<String> consumes);
+
+    protected static final void put(String name, Object value) {
+        Map<String, Object> cache = getCache();
+        cache.put(name, value);
+    }
+
+    protected static final <T> T get(String name) throws ClassCastException {
+        Map<String, Object> cache = getCache();
+        return (T) cache.get(name);
+    }
+
+    protected static final <V> V computeIfAbsent(String name, Function<? super String, ? extends V> mappingFunction) {
+        return (V) getCache().computeIfAbsent(name, mappingFunction);
+    }
+
+    private static Map<String, List<AnnotatedMethodParameterProcessor>> loadAnnotatedMethodParameterProcessors() {
+        Map<String, List<AnnotatedMethodParameterProcessor>> parameterProcessorsMap = new LinkedHashMap<>();
+
+        load(AnnotatedMethodParameterProcessor.class, AnnotatedMethodParameterProcessor.class.getClassLoader())
+                .forEach(processor -> {
+                    List<AnnotatedMethodParameterProcessor> processors =
+                            parameterProcessorsMap.computeIfAbsent(processor.getAnnotationType(), k -> new LinkedList<>());
+                    processors.add(processor);
+                });
+
+        return parameterProcessorsMap;
+    }
+
+    private static Map<String, Object> getCache() {
+        return threadLocalCache.get();
+    }
+
+    private static void clearCache() {
+        Map<String, Object> cache = getCache();
+        cache.clear();
+        threadLocalCache.remove();
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.java
new file mode 100644
index 0000000..523f932
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/AnnotatedMethodParameterProcessor.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.annotation.processing.rest;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The interface to process the parameter of method that was annotated
+ *
+ * @since 2.7.5
+ */
+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 AnnotationMirror the target annotation} whose type is {@link #getAnnotationType()}
+     * @param parameter          {@link VariableElement method parameter}
+     * @param parameterIndex     the index of parameter in the method
+     * @param method             {@link ExecutableElement method that parameter belongs to}
+     * @param restMethodMetadata {@link RestMethodMetadata the metadata is used to update}
+     */
+    void process(AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method,
+                 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-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..73772db
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/DefaultServiceRestMetadataProcessor.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.annotation.processing.rest;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * The default implementation of {@link ServiceRestMetadataProcessor}
+ *
+ * @since 2.7.5
+ */
+public class DefaultServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+    @Override
+    public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+        return true;
+    }
+
+    @Override
+    protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                    ExecutableElement method) {
+        return null;
+    }
+
+    @Override
+    protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                      ExecutableElement method) {
+        return null;
+    }
+
+    @Override
+    protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> produces) {
+
+    }
+
+    @Override
+    protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> consumes) {
+
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java
new file mode 100644
index 0000000..5c1a400
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataAnnotationProcessor.java
@@ -0,0 +1,87 @@
+/*
+ * 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.rest;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractServiceAnnotationProcessor;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.util.ElementFilter.typesIn;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.isServiceAnnotationPresent;
+
+/**
+ * The {@link Processor} class to generate the metadata of REST from the classes that are annotated by Dubbo's
+ *
+ * @Service
+ * @see Processor
+ * @since 2.7.5
+ */
+public class ServiceRestMetadataAnnotationProcessor extends AbstractServiceAnnotationProcessor {
+
+    private List<ServiceRestMetadataProcessor> metadataProcessors;
+
+    private ServiceRestMetadataStorage serviceRestMetadataWriter;
+
+    private Set<ServiceRestMetadata> serviceRestMetadata = new LinkedHashSet<>();
+
+    @Override
+    public synchronized void init(ProcessingEnvironment processingEnv) {
+        super.init(processingEnv);
+        this.metadataProcessors = loadServices(ServiceRestMetadataProcessor.class, getClass().getClassLoader());
+        this.serviceRestMetadataWriter = new ServiceRestMetadataStorage(processingEnv);
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+
+        typesIn(roundEnv.getRootElements()).forEach(serviceType -> process(processingEnv, serviceType, annotations));
+
+        if (roundEnv.processingOver()) {
+            try {
+                serviceRestMetadataWriter.append(serviceRestMetadata);
+            } catch (IOException e) {
+                throw new IllegalStateException(e);
+            }
+        }
+
+        return false;
+    }
+
+    private void process(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                         Set<? extends TypeElement> annotations) {
+        metadataProcessors
+                .stream()
+                .filter(processor -> supports(processor, processingEnv, serviceType))
+                .map(processor -> processor.process(processingEnv, serviceType, annotations))
+                .forEach(serviceRestMetadata::add);
+    }
+
+    private boolean supports(ServiceRestMetadataProcessor processor, ProcessingEnvironment processingEnv,
+                             TypeElement serviceType) {
+        //  @Service must be present in service type
+        return isServiceAnnotationPresent(serviceType) && processor.supports(processingEnv, serviceType);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..8e2af64
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataProcessor.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest;
+
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * The class to process {@link ServiceRestMetadata} based on Annotation Processor Tool
+ *
+ * @since 2.7.5
+ */
+public interface ServiceRestMetadataProcessor extends Prioritized {
+
+    /**
+     * Supports or not to the specified service type
+     *
+     * @param processingEnvironment {@link ProcessingEnvironment}
+     * @param serviceType           Dubbo service type or interface
+     * @return if supports, return <code>true</code>, or <code>false</code>
+     */
+    boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType);
+
+    /**
+     * Process the {@link ServiceRestMetadata} from given service type
+     *
+     * @param processingEnvironment {@link ProcessingEnvironment}
+     * @param serviceType           Dubbo service type or interface
+     * @param annotations
+     * @return non-null
+     */
+    ServiceRestMetadata process(ProcessingEnvironment processingEnvironment,
+                                TypeElement serviceType,
+                                Set<? extends TypeElement> annotations);
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.java
new file mode 100644
index 0000000..7365363
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/ServiceRestMetadataStorage.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.annotation.processing.rest;
+
+import org.apache.dubbo.metadata.annotation.processing.ClassPathMetadataStorage;
+import org.apache.dubbo.metadata.rest.ServiceRestMetadata;
+
+import com.google.gson.Gson;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import static com.google.gson.reflect.TypeToken.getParameterized;
+
+/**
+ * The storage for {@link ServiceRestMetadata}
+ */
+public class ServiceRestMetadataStorage {
+
+    public static final String METADATA_RESOURCE_PATH = "META-INF/dubbo/service-rest-metadata.json";
+
+    private final ClassPathMetadataStorage storage;
+
+    public ServiceRestMetadataStorage(ProcessingEnvironment processingEnv) {
+        this.storage = new ClassPathMetadataStorage(processingEnv);
+    }
+
+    public void append(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
+        Set<ServiceRestMetadata> allServiceRestMetadata = new LinkedHashSet<>();
+        storage.read(METADATA_RESOURCE_PATH, reader -> {
+            Gson gson = new Gson();
+            return (List) gson.fromJson(reader, getParameterized(List.class, ServiceRestMetadata.class).getType());
+        }).ifPresent(existedMetadata -> {
+            // Add all existed ServiceRestMetadata
+            allServiceRestMetadata.addAll(existedMetadata);
+        });
+        // Add all new ServiceRestMetadata
+        allServiceRestMetadata.addAll(serviceRestMetadata);
+        write(serviceRestMetadata);
+    }
+
+    public void write(Set<ServiceRestMetadata> serviceRestMetadata) throws IOException {
+        if (serviceRestMetadata.isEmpty()) {
+            return;
+        }
+        storage.write(() -> new Gson().toJson(serviceRestMetadata), METADATA_RESOURCE_PATH);
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.java
new file mode 100644
index 0000000..0818ff3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/DefaultValueParameterProcessor.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.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+import java.util.List;
+import java.util.Map;
+
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @DefaultValue
+ * *
+ *
+ * @since 2.7.5
+ */
+public class DefaultValueParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    /**
+     * The annotation class name of @DefaultValue
+     */
+    public static final String DEFAULT_VALUE_ANNOTATION_CLASS_NAME = "javax.ws.rs.DefaultValue";
+
+    @Override
+    public String getAnnotationType() {
+        return DEFAULT_VALUE_ANNOTATION_CLASS_NAME;
+    }
+
+    @Override
+    protected void process(String annotationValue, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement 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-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
index b3b27e6..c323e8a 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/FormParamParameterProcessor.java
@@ -14,27 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
 
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
 
 /**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @FormParam
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class FormParamParameterProcessor extends ParamAnnotationParameterProcessor {
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    @Override
+    public String getAnnotationType() {
+        return "javax.ws.rs.FormParam";
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java
new file mode 100644
index 0000000..278cf93
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/HeaderParamParameterProcessor.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor.buildDefaultValue;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @HeaderParam
+ *
+ * @since 2.7.5
+ */
+public class HeaderParamParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return "javax.ws.rs.HeaderParam";
+    }
+
+    @Override
+    protected void process(String headerName, String defaultValue, AnnotationMirror annotation,
+                           VariableElement parameter, int parameterIndex,
+                           ExecutableElement 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-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..564760f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/JAXRSServiceRestMetadataProcessor.java
@@ -0,0 +1,113 @@
+/*
+ * 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.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.AnnotatedConstruct;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
+
+/**
+ * {@link ServiceRestMetadataProcessor} implementation for JAX-RS 2 and 1
+ *
+ * @since 2.7.5
+ */
+public class JAXRSServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+    /**
+     * The annotation name of @Path
+     */
+    public static final String PATH_ANNOTATION_CLASS_NAME = "javax.ws.rs.Path";
+
+    /**
+     * The annotation name of @HttpMethod
+     */
+    public static final String HTTP_METHOD_ANNOTATION_CLASS_NAME = "javax.ws.rs.HttpMethod";
+
+    /**
+     * The annotation class name of @Produces
+     */
+    public static final String PRODUCES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Produces";
+
+    /**
+     * The annotation class name of @Consumes
+     */
+    public static final String CONSUMES_ANNOTATION_CLASS_NAME = "javax.ws.rs.Consumes";
+
+    @Override
+    public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+        return isAnnotationPresent(serviceType, PATH_ANNOTATION_CLASS_NAME);
+    }
+
+    @Override
+    protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
+        String pathFromType = getPathValue(processingEnv, serviceType);
+        String pathFromMethod = getPathValue(method);
+        return buildPath(pathFromType, pathFromMethod);
+    }
+
+    @Override
+    protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType, ExecutableElement method) {
+        AnnotationMirror annotation = findMetaAnnotation(method, HTTP_METHOD_ANNOTATION_CLASS_NAME);
+        return getValue(annotation);
+    }
+
+    @Override
+    protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> produces) {
+        addAnnotationValues(method, PRODUCES_ANNOTATION_CLASS_NAME, produces);
+    }
+
+    @Override
+    protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> consumes) {
+        addAnnotationValues(method, CONSUMES_ANNOTATION_CLASS_NAME, consumes);
+    }
+
+
+    private void addAnnotationValues(Element element, String annotationAttributeName, Set<String> result) {
+        AnnotationMirror annotation = findAnnotation(element, annotationAttributeName);
+        String[] value = getValue(annotation);
+        if (value != null) {
+            Stream.of(value).forEach(result::add);
+        }
+    }
+
+    private String getPathValue(ProcessingEnvironment processingEnv, TypeElement serviceType) {
+        AnnotationMirror annotation = findAnnotation(serviceType, PATH_ANNOTATION_CLASS_NAME);
+        return getValue(annotation);
+    }
+
+    private String getPathValue(AnnotatedConstruct annotatedConstruct) {
+        AnnotationMirror annotation = getAnnotation(annotatedConstruct, PATH_ANNOTATION_CLASS_NAME);
+        return getValue(annotation);
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
index b3b27e6..026b648 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/MatrixParamParameterProcessor.java
@@ -14,27 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
 
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
 
 /**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @MatrixParam
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class MatrixParamParameterProcessor extends ParamAnnotationParameterProcessor {
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    @Override
+    public String getAnnotationType() {
+        return "javax.ws.rs.MatrixParam";
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/ParamAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/ParamAnnotationParameterProcessor.java
new file mode 100644
index 0000000..d615cdc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/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.annotation.processing.rest.jaxrs;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RequestMetadata;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @*Param
+ */
+public abstract class ParamAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+    protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex,
+                           ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+        RequestMetadata requestMetadata = restMethodMetadata.getRequest();
+        requestMetadata.addParam(name, defaultValue);
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
index b3b27e6..42e14ab 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/jaxrs/QueryParamParameterProcessor.java
@@ -14,27 +14,19 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.rest.jaxrs;
 
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
 
 /**
- * {@link DubboServiceLoader} Test
+ * The {@link AnnotatedMethodParameterProcessor} implementation for JAX-RS's @QueryParam
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class QueryParamParameterProcessor extends ParamAnnotationParameterProcessor {
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    @Override
+    public String getAnnotationType() {
+        return "javax.ws.rs.QueryParam";
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.java
new file mode 100644
index 0000000..1fa5285
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/AbstractRequestAnnotationParameterProcessor.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.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractAnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+
+/**
+ * The abstract {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @Request*
+ */
+public abstract class AbstractRequestAnnotationParameterProcessor extends AbstractAnnotatedMethodParameterProcessor {
+
+
+    protected abstract void process(String name, String defaultValue, AnnotationMirror annotation,
+                                    VariableElement parameter, int parameterIndex,
+                                    ExecutableElement method,
+                                    RestMethodMetadata restMethodMetadata);
+
+    @Override
+    protected String getAnnotationValue(AnnotationMirror annotation, VariableElement 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.getSimpleName().toString();
+        }
+
+        return name;
+    }
+
+    protected String getDefaultValue(AnnotationMirror annotation, VariableElement 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-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java
new file mode 100644
index 0000000..94929bc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestHeaderParameterProcessor.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestHeader
+ */
+public class RequestHeaderParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return "org.springframework.web.bind.annotation.RequestHeader";
+    }
+
+    @Override
+    protected void process(String name, String defaultValue, AnnotationMirror annotation, VariableElement parameter, int parameterIndex, ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+        restMethodMetadata.getRequest().addHeader(name, defaultValue);
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.java
new file mode 100644
index 0000000..1292025
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/RequestParamParameterProcessor.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.annotation.processing.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor;
+import org.apache.dubbo.metadata.rest.RestMethodMetadata;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.VariableElement;
+
+/**
+ * The {@link AnnotatedMethodParameterProcessor} implementation for Spring Web MVC's @RequestParam
+ */
+public class RequestParamParameterProcessor extends AbstractRequestAnnotationParameterProcessor {
+
+    @Override
+    public String getAnnotationType() {
+        return "org.springframework.web.bind.annotation.RequestParam";
+    }
+
+    @Override
+    protected void process(String name, String defaultValue, AnnotationMirror annotation,
+                           VariableElement parameter, int parameterIndex,
+                           ExecutableElement method, RestMethodMetadata restMethodMetadata) {
+        restMethodMetadata.getRequest().addParam(name, defaultValue);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java
new file mode 100644
index 0000000..b9f7009
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/rest/springmvc/SpringMvcServiceRestMetadataProcessor.java
@@ -0,0 +1,157 @@
+/*
+ * 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.rest.springmvc;
+
+import org.apache.dubbo.metadata.annotation.processing.rest.AbstractServiceRestMetadataProcessor;
+import org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import java.lang.reflect.Array;
+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.function.Streams.filterFirst;
+import static org.apache.dubbo.common.utils.ArrayUtils.isEmpty;
+import static org.apache.dubbo.common.utils.ArrayUtils.isNotEmpty;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAllAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.util.HttpUtils.buildPath;
+
+/**
+ * {@link ServiceRestMetadataProcessor}
+ *
+ * @since 2.7.5
+ */
+public class SpringMvcServiceRestMetadataProcessor extends AbstractServiceRestMetadataProcessor {
+
+    private static final int FIRST_ELEMENT_INDEX = 0;
+
+    public static final String CONTROLLER_ANNOTATION_CLASS_NAME = "org.springframework.stereotype.Controller";
+
+    public static final String REQUEST_MAPPING_ANNOTATION_CLASS_NAME = "org.springframework.web.bind.annotation.RequestMapping";
+
+    @Override
+    public boolean supports(ProcessingEnvironment processingEnvironment, TypeElement serviceType) {
+        return isAnnotationPresent(serviceType, CONTROLLER_ANNOTATION_CLASS_NAME);
+    }
+
+    @Override
+    protected String getRequestPath(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                    ExecutableElement method) {
+
+        String requestPathFromType = getRequestPath(serviceType);
+
+        String requestPathFromMethod = getRequestPath(method);
+
+        return buildPath(requestPathFromType, requestPathFromMethod);
+    }
+
+
+    @Override
+    protected String getRequestMethod(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                      ExecutableElement method) {
+
+        AnnotationMirror requestMapping = getRequestMapping(method);
+
+        // 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));
+    }
+
+    private AnnotationMirror getRequestMapping(Element element) {
+        // try "@RequestMapping" first
+        AnnotationMirror requestMapping = findAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+        // try the annotation meta-annotated later
+        if (requestMapping == null) {
+            requestMapping = findMetaAnnotation(element, REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+        }
+        return requestMapping;
+    }
+
+    @Override
+    protected void processProduces(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> produces) {
+        addMediaTypes(method, "produces", produces);
+    }
+
+    @Override
+    protected void processConsumes(ProcessingEnvironment processingEnv, TypeElement serviceType,
+                                   ExecutableElement method, Set<String> consumes) {
+        addMediaTypes(method, "consumes", consumes);
+    }
+
+    private void addMediaTypes(ExecutableElement method, String annotationAttributeName, Set<String> mediaTypesSet) {
+
+        AnnotationMirror mappingAnnotation = getMappingAnnotation(method);
+
+        String[] mediaTypes = getAttribute(mappingAnnotation, annotationAttributeName);
+
+        if (isNotEmpty(mediaTypes)) {
+            of(mediaTypes).forEach(mediaTypesSet::add);
+        }
+    }
+
+    private AnnotationMirror getMappingAnnotation(Element element) {
+        return computeIfAbsent(valueOf(element), key ->
+                filterFirst(getAllAnnotations(element), annotation -> {
+                    DeclaredType annotationType = annotation.getAnnotationType();
+                    // try "@RequestMapping" first
+                    if (REQUEST_MAPPING_ANNOTATION_CLASS_NAME.equals(annotationType.toString())) {
+                        return true;
+                    }
+                    // try meta annotation
+                    return isAnnotationPresent(annotationType.asElement(), REQUEST_MAPPING_ANNOTATION_CLASS_NAME);
+                })
+        );
+    }
+
+    private String getRequestPath(Element element) {
+        AnnotationMirror mappingAnnotation = getMappingAnnotation(element);
+        return getRequestPath(mappingAnnotation);
+    }
+
+    private String getRequestPath(AnnotationMirror mappingAnnotation) {
+        // 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];
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java
new file mode 100644
index 0000000..ac3877d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtils.java
@@ -0,0 +1,233 @@
+/*
+ * 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.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.AnnotatedConstruct;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.ArrayType;
+import javax.lang.model.type.TypeMirror;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.lang.Enum.valueOf;
+import static java.util.Collections.emptyList;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSameType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isTypeElement;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+
+/**
+ * The utilities class for annotation in the package "javax.lang.model.*"
+ *
+ * @since 2.7.5
+ */
+public interface AnnotationUtils {
+
+    static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct,
+                                          Class<? extends Annotation> annotationClass) {
+        return annotationClass == null ?
+                null :
+                getAnnotation(annotatedConstruct, annotationClass.getTypeName());
+    }
+
+    static AnnotationMirror getAnnotation(AnnotatedConstruct annotatedConstruct, CharSequence annotationClassName) {
+        List<AnnotationMirror> annotations = getAnnotations(annotatedConstruct, annotationClassName);
+        return annotations.isEmpty() ? null : annotations.get(0);
+    }
+
+    static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct, Class<? extends Annotation> annotationClass) {
+        return annotationClass == null ?
+                emptyList() :
+                getAnnotations(annotatedConstruct, annotationClass.getTypeName());
+    }
+
+    static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
+                                                 CharSequence annotationClassName) {
+        return getAnnotations(annotatedConstruct,
+                annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
+    }
+
+    static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct) {
+        return getAnnotations(annotatedConstruct, EMPTY_ARRAY);
+    }
+
+    static List<AnnotationMirror> getAnnotations(AnnotatedConstruct annotatedConstruct,
+                                                 Predicate<AnnotationMirror>... annotationFilters) {
+
+        AnnotatedConstruct actualAnnotatedConstruct = annotatedConstruct;
+
+        if (annotatedConstruct instanceof TypeMirror) {
+            actualAnnotatedConstruct = ofTypeElement((TypeMirror) actualAnnotatedConstruct);
+        }
+
+        return actualAnnotatedConstruct == null ?
+                emptyList() :
+                filterAll((List<AnnotationMirror>) actualAnnotatedConstruct.getAnnotationMirrors(), annotationFilters);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(TypeMirror type) {
+        return getAllAnnotations(ofTypeElement(type));
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(Element element) {
+        return getAllAnnotations(element, EMPTY_ARRAY);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Class<? extends Annotation> annotationClass) {
+        return getAllAnnotations(ofTypeElement(type), annotationClass);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(Element element, Class<? extends Annotation> annotationClass) {
+        return element == null || annotationClass == null ?
+                emptyList() :
+                getAllAnnotations(element, annotationClass.getTypeName());
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(TypeMirror type, CharSequence annotationClassName) {
+        return getAllAnnotations(ofTypeElement(type), annotationClassName);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(Element element, CharSequence annotationClassName) {
+        return getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName));
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(TypeMirror type, Predicate<AnnotationMirror>... annotationFilters) {
+        return getAllAnnotations(ofTypeElement(type), annotationFilters);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(Element element, Predicate<AnnotationMirror>... annotationFilters) {
+
+        List<AnnotationMirror> allAnnotations = isTypeElement(element) ?
+                getHierarchicalTypes(ofTypeElement(element))
+                        .stream()
+                        .map(AnnotationUtils::getAnnotations)
+                        .flatMap(Collection::stream)
+                        .collect(Collectors.toList()) :
+                element == null ? emptyList() : (List<AnnotationMirror>) element.getAnnotationMirrors();
+
+        return filterAll(allAnnotations, annotationFilters);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType) {
+        return getAllAnnotations(processingEnv, annotatedType, EMPTY_ARRAY);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, Type annotatedType,
+                                                    Predicate<AnnotationMirror>... annotationFilters) {
+        return annotatedType == null ?
+                emptyList() :
+                getAllAnnotations(processingEnv, annotatedType.getTypeName(), annotationFilters);
+    }
+
+    static List<AnnotationMirror> getAllAnnotations(ProcessingEnvironment processingEnv, CharSequence annotatedTypeName,
+                                                    Predicate<AnnotationMirror>... annotationFilters) {
+        return getAllAnnotations(getType(processingEnv, annotatedTypeName), annotationFilters);
+    }
+
+    static AnnotationMirror findAnnotation(TypeMirror type, Class<? extends Annotation> annotationClass) {
+        return annotationClass == null ? null : findAnnotation(type, annotationClass.getTypeName());
+    }
+
+    static AnnotationMirror findAnnotation(TypeMirror type, CharSequence annotationClassName) {
+        return findAnnotation(ofTypeElement(type), annotationClassName);
+    }
+
+    static AnnotationMirror findAnnotation(Element element, Class<? extends Annotation> annotationClass) {
+        return annotationClass == null ? null : findAnnotation(element, annotationClass.getTypeName());
+    }
+
+    static AnnotationMirror findAnnotation(Element element, CharSequence annotationClassName) {
+        return filterFirst(getAllAnnotations(element, annotation -> isSameType(annotation.getAnnotationType(), annotationClassName)));
+    }
+
+    static AnnotationMirror findMetaAnnotation(Element annotatedConstruct, CharSequence metaAnnotationClassName) {
+        return annotatedConstruct == null ?
+                null :
+                getAnnotations(annotatedConstruct)
+                        .stream()
+                        .map(annotation -> findAnnotation(annotation.getAnnotationType(), metaAnnotationClassName))
+                        .filter(Objects::nonNull)
+                        .findFirst()
+                        .orElse(null);
+    }
+
+    static boolean isAnnotationPresent(Element element, CharSequence annotationClassName) {
+        return findAnnotation(element, annotationClassName) != null ||
+                findMetaAnnotation(element, annotationClassName) != null;
+    }
+
+    static <T> T getAttribute(AnnotationMirror annotation, String attributeName) {
+        return annotation == null ? null : getAttribute(annotation.getElementValues(), attributeName);
+    }
+
+    static <T> T getAttribute(Map<? extends ExecutableElement, ? extends AnnotationValue> attributesMap,
+                              String attributeName) {
+        T annotationValue = null;
+        for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : attributesMap.entrySet()) {
+            ExecutableElement attributeMethod = entry.getKey();
+            if (Objects.equals(attributeName, attributeMethod.getSimpleName().toString())) {
+                TypeMirror attributeType = attributeMethod.getReturnType();
+                AnnotationValue value = entry.getValue();
+                if (attributeType instanceof ArrayType) { // array-typed attribute values
+                    ArrayType arrayType = (ArrayType) attributeType;
+                    String componentType = arrayType.getComponentType().toString();
+                    ClassLoader classLoader = AnnotationUtils.class.getClassLoader();
+                    List<AnnotationValue> values = (List<AnnotationValue>) value.getValue();
+                    int size = values.size();
+                    try {
+                        Class componentClass = classLoader.loadClass(componentType);
+                        boolean isEnum = componentClass.isEnum();
+                        Object array = Array.newInstance(componentClass, values.size());
+                        for (int i = 0; i < size; i++) {
+                            Object element = values.get(i).getValue();
+                            if (isEnum) {
+                                element = valueOf(componentClass, element.toString());
+                            }
+                            Array.set(array, i, element);
+                        }
+                        annotationValue = (T) array;
+                    } catch (ClassNotFoundException e) {
+                        throw new RuntimeException(e);
+                    }
+                } else {
+                    annotationValue = (T) value.getValue();
+                }
+                break;
+            }
+        }
+        return annotationValue;
+    }
+
+    static <T> T getValue(AnnotationMirror annotation) {
+        return (T) getAttribute(annotation, "value");
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java
new file mode 100644
index 0000000..b6c7346
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtils.java
@@ -0,0 +1,146 @@
+/*
+ * 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.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.Collection;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.ElementKind.ENUM_CONSTANT;
+import static javax.lang.model.element.ElementKind.FIELD;
+import static javax.lang.model.element.Modifier.STATIC;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.hasModifiers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matches;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+
+/**
+ * The utilities class for the field in the package "javax.lang.model."
+ *
+ * @since 2.7.5
+ */
+public interface FieldUtils {
+
+    static List<VariableElement> getDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
+        return element == null ? emptyList() : getDeclaredFields(element.asType(), fieldFilters);
+    }
+
+    static List<VariableElement> getDeclaredFields(Element element) {
+        return getDeclaredFields(element, EMPTY_ARRAY);
+    }
+
+    static List<VariableElement> getDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
+        return filterAll(fieldsIn(getDeclaredMembers(type)), fieldFilters);
+    }
+
+    static List<VariableElement> getDeclaredFields(TypeMirror type) {
+        return getDeclaredFields(type, EMPTY_ARRAY);
+    }
+
+    static List<VariableElement> getAllDeclaredFields(Element element, Predicate<VariableElement>... fieldFilters) {
+        return element == null ? emptyList() : getAllDeclaredFields(element.asType(), fieldFilters);
+    }
+
+    static List<VariableElement> getAllDeclaredFields(Element element) {
+        return getAllDeclaredFields(element, EMPTY_ARRAY);
+    }
+
+    static List<VariableElement> getAllDeclaredFields(TypeMirror type, Predicate<VariableElement>... fieldFilters) {
+        return getHierarchicalTypes(type)
+                .stream()
+                .map(t -> getDeclaredFields(t, fieldFilters))
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
+
+    static List<VariableElement> getAllDeclaredFields(TypeMirror type) {
+        return getAllDeclaredFields(type, EMPTY_ARRAY);
+    }
+
+    static VariableElement getDeclaredField(Element element, String fieldName) {
+        return element == null ? null : getDeclaredField(element.asType(), fieldName);
+    }
+
+    static VariableElement getDeclaredField(TypeMirror type, String fieldName) {
+        return filterFirst(getDeclaredFields(type, field -> fieldName.equals(field.getSimpleName().toString())));
+    }
+
+    static VariableElement findField(Element element, String fieldName) {
+        return element == null ? null : findField(element.asType(), fieldName);
+    }
+
+    static VariableElement findField(TypeMirror type, String fieldName) {
+        return filterFirst(getAllDeclaredFields(type, field -> equals(field, fieldName)));
+    }
+
+    /**
+     * is Enum's member field or not
+     *
+     * @param field {@link VariableElement} must be public static final fields
+     * @return if field is public static final, return <code>true</code>, or <code>false</code>
+     */
+    static boolean isEnumMemberField(VariableElement field) {
+        if (field == null || !isEnumType(field.getEnclosingElement())) {
+            return false;
+        }
+        return ENUM_CONSTANT.equals(field.getKind());
+    }
+
+    static boolean isNonStaticField(VariableElement field) {
+        return isField(field) && !hasModifiers(field, STATIC);
+    }
+
+    static boolean isField(VariableElement field) {
+        return matches(field, FIELD) || isEnumMemberField(field);
+    }
+
+    static boolean isField(VariableElement field, Modifier... modifiers) {
+        return isField(field) && hasModifiers(field, modifiers);
+    }
+
+    static List<VariableElement> getNonStaticFields(TypeMirror type) {
+        return getDeclaredFields(type, FieldUtils::isNonStaticField);
+    }
+
+    static List<VariableElement> getNonStaticFields(Element element) {
+        return element == null ? emptyList() : getNonStaticFields(element.asType());
+    }
+
+    static List<VariableElement> getAllNonStaticFields(TypeMirror type) {
+        return getAllDeclaredFields(type, FieldUtils::isNonStaticField);
+    }
+
+    static List<VariableElement> getAllNonStaticFields(Element element) {
+        return element == null ? emptyList() : getAllNonStaticFields(element.asType());
+    }
+
+    static boolean equals(VariableElement field, CharSequence fieldName) {
+        return field != null && fieldName != null && field.getSimpleName().toString().equals(fieldName.toString());
+    }
+
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
index b3b27e6..f43ffd9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtils.java
@@ -14,27 +14,32 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.util;
 
-import org.junit.jupiter.api.Test;
 
-import java.util.List;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static java.lang.String.format;
 
 /**
- * {@link DubboServiceLoader} Test
+ * Logger Utils
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public interface LoggerUtils {
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    Logger LOGGER = LoggerFactory.getLogger("dubbo-metadata-processor");
+
+    static void info(String format, Object... args) {
+        if (LOGGER.isInfoEnabled()) {
+            LOGGER.info(format(format, args));
+        }
+    }
+
+    static void warn(String format, Object... args) {
+        if (LOGGER.isWarnEnabled()) {
+            LOGGER.warn(format(format, args));
+        }
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java
new file mode 100644
index 0000000..fc617a1
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtils.java
@@ -0,0 +1,94 @@
+/*
+ * 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.util;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+
+/**
+ * The utilities class for the members in the package "javax.lang.model.", such as "field", "method", "constructor"
+ *
+ * @since 2.7.5
+ */
+public interface MemberUtils {
+
+    static boolean matches(Element member, ElementKind kind) {
+        return member == null || kind == null ? false : kind.equals(member.getKind());
+    }
+
+    static boolean isPublicNonStatic(Element member) {
+        return hasModifiers(member, PUBLIC) && !hasModifiers(member, STATIC);
+    }
+
+    static boolean hasModifiers(Element member, Modifier... modifiers) {
+        if (member == null || modifiers == null) {
+            return false;
+        }
+        Set<Modifier> actualModifiers = member.getModifiers();
+        for (Modifier modifier : modifiers) {
+            if (!actualModifiers.contains(modifier)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    static List<? extends Element> getDeclaredMembers(TypeMirror type) {
+        TypeElement element = ofTypeElement(type);
+        return element == null ? emptyList() : element.getEnclosedElements();
+    }
+
+    static List<? extends Element> getAllDeclaredMembers(TypeMirror type) {
+        return getHierarchicalTypes(type)
+                .stream()
+                .map(MemberUtils::getDeclaredMembers)
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
+
+    static boolean matchParameterTypes(List<? extends VariableElement> parameters, CharSequence... parameterTypes) {
+
+        int size = parameters.size();
+
+        if (size != parameterTypes.length) {
+            return false;
+        }
+
+        for (int i = 0; i < size; i++) {
+            VariableElement parameter = parameters.get(i);
+            if (!Objects.equals(parameter.asType().toString(), parameterTypes[i])) {
+                return false;
+            }
+        }
+        return true;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java
new file mode 100644
index 0000000..ab7c8c7
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtils.java
@@ -0,0 +1,155 @@
+/*
+ * 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.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static javax.lang.model.element.ElementKind.METHOD;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filter;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+import static org.apache.dubbo.common.function.Streams.filterFirst;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.isPublicNonStatic;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matchParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+
+/**
+ * The utilities class for method in the package "javax.lang.model."
+ *
+ * @since 2.7.5
+ */
+public interface MethodUtils {
+
+    static List<ExecutableElement> getDeclaredMethods(TypeElement type, Predicate<ExecutableElement>... methodFilters) {
+        return type == null ? emptyList() : getDeclaredMethods(type.asType(), methodFilters);
+    }
+
+    static List<ExecutableElement> getDeclaredMethods(TypeMirror type, Predicate<ExecutableElement>... methodFilters) {
+        return filterAll(methodsIn(getDeclaredMembers(type)), methodFilters);
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeElement type, Predicate<ExecutableElement>... methodFilters) {
+        return type == null ? emptyList() : getAllDeclaredMethods(type.asType(), methodFilters);
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeElement type) {
+        return getAllDeclaredMethods(type, EMPTY_ARRAY);
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type, Predicate<ExecutableElement>... methodFilters) {
+        return getHierarchicalTypes(type)
+                .stream()
+                .map(t -> getDeclaredMethods(t, methodFilters))
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type) {
+        return getAllDeclaredMethods(type, EMPTY_ARRAY);
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeElement type, Type... excludedTypes) {
+        return type == null ? emptyList() : getAllDeclaredMethods(type.asType(), excludedTypes);
+    }
+
+    static List<ExecutableElement> getAllDeclaredMethods(TypeMirror type, Type... excludedTypes) {
+        return getHierarchicalTypes(type, excludedTypes)
+                .stream()
+                .map(t -> getDeclaredMethods(t))
+                .flatMap(Collection::stream)
+                .collect(Collectors.toList());
+    }
+
+    static List<ExecutableElement> getPublicNonStaticMethods(TypeElement type, Type... excludedTypes) {
+        return getPublicNonStaticMethods(ofDeclaredType(type), excludedTypes);
+    }
+
+    static List<ExecutableElement> getPublicNonStaticMethods(TypeMirror type, Type... excludedTypes) {
+        return filter(getAllDeclaredMethods(type, excludedTypes), MethodUtils::isPublicNonStaticMethod);
+    }
+
+    static boolean isMethod(ExecutableElement method) {
+        return method == null ? false : METHOD.equals(method.getKind());
+    }
+
+    static boolean isPublicNonStaticMethod(ExecutableElement method) {
+        return isMethod(method) && isPublicNonStatic(method);
+    }
+
+    static ExecutableElement findMethod(TypeElement type, String methodName, Type oneParameterType, Type... otherParameterTypes) {
+        return type == null ? null : findMethod(type.asType(), methodName, oneParameterType, otherParameterTypes);
+    }
+
+    static ExecutableElement findMethod(TypeMirror type, String methodName, Type oneParameterType, Type... otherParameterTypes) {
+        List<Type> parameterTypes = new LinkedList<>();
+        parameterTypes.add(oneParameterType);
+        parameterTypes.addAll(asList(otherParameterTypes));
+        return findMethod(type, methodName, parameterTypes.stream().map(Type::getTypeName).toArray(String[]::new));
+    }
+
+    static ExecutableElement findMethod(TypeElement type, String methodName, CharSequence... parameterTypes) {
+        return type == null ? null : findMethod(type.asType(), methodName, parameterTypes);
+    }
+
+    static ExecutableElement findMethod(TypeMirror type, String methodName, CharSequence... parameterTypes) {
+        return filterFirst(getAllDeclaredMethods(type),
+                method -> methodName.equals(method.getSimpleName().toString()),
+                method -> matchParameterTypes(method.getParameters(), parameterTypes)
+        );
+    }
+
+    static ExecutableElement getOverrideMethod(ProcessingEnvironment processingEnv, TypeElement type,
+                                               ExecutableElement declaringMethod) {
+        Elements elements = processingEnv.getElementUtils();
+        return filterFirst(getAllDeclaredMethods(type), method -> elements.overrides(method, declaringMethod, type));
+    }
+
+
+    static String getMethodName(ExecutableElement method) {
+        return method == null ? null : method.getSimpleName().toString();
+    }
+
+    static String getReturnType(ExecutableElement method) {
+        return method == null ? null : method.getReturnType().toString();
+    }
+
+    static String[] getMethodParameterTypes(ExecutableElement method) {
+        return method == null ?
+                new String[0] :
+                method.getParameters()
+                        .stream()
+                        .map(Element::asType)
+                        .map(TypeMirror::toString)
+                        .toArray(String[]::new);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java
new file mode 100644
index 0000000..889e59f
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtils.java
@@ -0,0 +1,121 @@
+/*
+ * 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.util;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.TypeElement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.lang.String.valueOf;
+import static java.util.Arrays.asList;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+
+/**
+ * The utilities class for @Service annotation
+ *
+ * @since 2.7.5
+ */
+public interface ServiceAnnotationUtils {
+
+    /**
+     * The class name of @Service
+     */
+    String SERVICE_ANNOTATION_TYPE = "org.apache.dubbo.config.annotation.Service";
+
+    /**
+     * The class name of the legacy @Service
+     */
+    @Deprecated
+    String LEGACY_SERVICE_ANNOTATION_TYPE = "com.alibaba.dubbo.config.annotation.Service";
+
+    /**
+     * the attribute name of @Service.interfaceClass()
+     */
+    String INTERFACE_CLASS_ATTRIBUTE_NAME = "interfaceClass";
+
+    /**
+     * the attribute name of @Service.interfaceName()
+     */
+    String INTERFACE_NAME_ATTRIBUTE_NAME = "interfaceName";
+
+    /**
+     * the attribute name of @Service.group()
+     */
+    String GROUP_ATTRIBUTE_NAME = "group";
+
+    /**
+     * the attribute name of @Service.version()
+     */
+    String VERSION_ATTRIBUTE_NAME = "version";
+
+    Set<String> SUPPORTED_ANNOTATION_TYPES = unmodifiableSet(new HashSet(asList(SERVICE_ANNOTATION_TYPE, LEGACY_SERVICE_ANNOTATION_TYPE)));
+
+    static boolean isServiceAnnotationPresent(TypeElement annotatedType) {
+        return isAnnotationPresent(annotatedType, SERVICE_ANNOTATION_TYPE) ||
+                isAnnotationPresent(annotatedType, LEGACY_SERVICE_ANNOTATION_TYPE);
+    }
+
+    static AnnotationMirror getAnnotation(TypeElement annotatedClass) {
+        return getAnnotation(annotatedClass.getAnnotationMirrors());
+    }
+
+    static AnnotationMirror getAnnotation(Iterable<? extends AnnotationMirror> annotationMirrors) {
+        AnnotationMirror matchedAnnotationMirror = null;
+        for (AnnotationMirror annotationMirror : annotationMirrors) {
+            String annotationType = annotationMirror.getAnnotationType().toString();
+            if (SERVICE_ANNOTATION_TYPE.equals(annotationType)) {
+                matchedAnnotationMirror = annotationMirror;
+                break;
+            } else if (LEGACY_SERVICE_ANNOTATION_TYPE.equals(annotationType)) {
+                matchedAnnotationMirror = annotationMirror;
+            }
+        }
+
+        if (matchedAnnotationMirror == null) {
+            throw new IllegalArgumentException("The annotated element must be implemented the interface "
+                    + SERVICE_ANNOTATION_TYPE + " or " + LEGACY_SERVICE_ANNOTATION_TYPE);
+        }
+
+        return matchedAnnotationMirror;
+    }
+
+    static String resolveServiceInterfaceName(TypeElement annotatedClass, AnnotationMirror serviceAnnotation) {
+        Object interfaceClass = getAttribute(serviceAnnotation, INTERFACE_CLASS_ATTRIBUTE_NAME);
+
+        if (interfaceClass == null) { // try to find the "interfaceName" attribute
+            interfaceClass = getAttribute(serviceAnnotation, INTERFACE_NAME_ATTRIBUTE_NAME);
+        }
+
+        if (interfaceClass == null) {
+            // last, get the interface class from first one
+            interfaceClass = ((TypeElement) annotatedClass).getInterfaces().get(0);
+        }
+
+        return valueOf(interfaceClass);
+    }
+
+    static String getGroup(AnnotationMirror serviceAnnotation) {
+        return getAttribute(serviceAnnotation, GROUP_ATTRIBUTE_NAME);
+    }
+
+    static String getVersion(AnnotationMirror serviceAnnotation) {
+        return getAttribute(serviceAnnotation, VERSION_ATTRIBUTE_NAME);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java
new file mode 100644
index 0000000..3283d50
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtils.java
@@ -0,0 +1,382 @@
+/*
+ * 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.util;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Elements;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.Predicate;
+
+import static java.lang.String.valueOf;
+import static java.util.Arrays.asList;
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySet;
+import static java.util.stream.Collectors.toSet;
+import static java.util.stream.Stream.of;
+import static java.util.stream.StreamSupport.stream;
+import static javax.lang.model.element.ElementKind.ANNOTATION_TYPE;
+import static javax.lang.model.element.ElementKind.CLASS;
+import static javax.lang.model.element.ElementKind.ENUM;
+import static javax.lang.model.element.ElementKind.INTERFACE;
+import static org.apache.dubbo.common.function.Predicates.EMPTY_ARRAY;
+import static org.apache.dubbo.common.function.Streams.filterAll;
+
+/**
+ * The utilities class for type in the package "javax.lang.model.*"
+ *
+ * @since 2.7.5
+ */
+public interface TypeUtils {
+
+    List<String> SIMPLE_TYPES = asList(
+            Void.class.getName(),
+            Boolean.class.getName(),
+            Character.class.getName(),
+            Byte.class.getName(),
+            Short.class.getName(),
+            Integer.class.getName(),
+            Long.class.getName(),
+            Float.class.getName(),
+            Double.class.getName(),
+            String.class.getName(),
+            BigDecimal.class.getName(),
+            BigInteger.class.getName(),
+            Date.class.getName()
+    );
+
+    static boolean isSimpleType(Element element) {
+        return element != null && isSimpleType(element.asType());
+    }
+
+    static boolean isSimpleType(TypeMirror type) {
+        return type != null && SIMPLE_TYPES.contains(type.toString());
+    }
+
+    static boolean isSameType(TypeMirror type, CharSequence typeName) {
+        if (type == null || typeName == null) {
+            return false;
+        }
+        return Objects.equals(valueOf(type), valueOf(typeName));
+    }
+
+    static boolean isSameType(TypeMirror typeMirror, Type type) {
+        return type != null && isSameType(typeMirror, type.getTypeName());
+    }
+
+    static boolean isArrayType(TypeMirror type) {
+        return type != null && TypeKind.ARRAY.equals(type.getKind());
+    }
+
+    static boolean isArrayType(Element element) {
+        return element != null && isArrayType(element.asType());
+    }
+
+    static boolean isEnumType(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        return declaredType != null && ENUM.equals(declaredType.asElement().getKind());
+    }
+
+    static boolean isEnumType(Element element) {
+        return element != null && isEnumType(element.asType());
+    }
+
+    static boolean isClassType(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        return declaredType != null && isClassType(declaredType.asElement());
+    }
+
+    static boolean isClassType(Element element) {
+        return element != null && CLASS.equals(element.getKind());
+    }
+
+    static boolean isPrimitiveType(TypeMirror type) {
+        return type != null && type.getKind().isPrimitive();
+    }
+
+    static boolean isPrimitiveType(Element element) {
+        return element != null && isPrimitiveType(element.asType());
+    }
+
+    static boolean isInterfaceType(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        return declaredType != null && isInterfaceType(declaredType.asElement());
+    }
+
+    static boolean isInterfaceType(Element element) {
+        return element != null && INTERFACE.equals(element.getKind());
+    }
+
+    static boolean isAnnotationType(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        return declaredType != null && isAnnotationType(declaredType.asElement());
+    }
+
+    static boolean isAnnotationType(Element element) {
+        return element != null && ANNOTATION_TYPE.equals(element.getKind());
+    }
+
+    static Set<TypeElement> getHierarchicalTypes(TypeElement type) {
+        return getHierarchicalTypes(type, true, true, true);
+    }
+
+    static Set<DeclaredType> getHierarchicalTypes(TypeMirror type) {
+        return getHierarchicalTypes(type, EMPTY_ARRAY);
+    }
+
+    static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, Predicate<DeclaredType>... typeFilters) {
+        return filterAll(ofDeclaredTypes(getHierarchicalTypes(ofTypeElement(type))), typeFilters);
+    }
+
+    static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, Type... excludedTypes) {
+        return getHierarchicalTypes(type, of(excludedTypes).map(Type::getTypeName).toArray(String[]::new));
+    }
+
+    static Set<DeclaredType> getHierarchicalTypes(TypeMirror type, CharSequence... excludedTypeNames) {
+        Set<String> typeNames = of(excludedTypeNames).map(CharSequence::toString).collect(toSet());
+        return getHierarchicalTypes(type, t -> !typeNames.contains(t.toString()));
+    }
+
+    static Set<TypeElement> getHierarchicalTypes(TypeElement type,
+                                                 boolean includeSelf,
+                                                 boolean includeSuperTypes,
+                                                 boolean includeSuperInterfaces,
+                                                 Predicate<TypeElement>... typeFilters) {
+
+        if (type == null) {
+            return emptySet();
+        }
+
+        Set<TypeElement> hierarchicalTypes = new LinkedHashSet<>();
+
+        if (includeSelf) {
+            hierarchicalTypes.add(type);
+        }
+
+        if (includeSuperTypes) {
+            hierarchicalTypes.addAll(getAllSuperTypes(type));
+        }
+
+        if (includeSuperInterfaces) {
+            hierarchicalTypes.addAll(getAllInterfaces(type));
+        }
+
+        return filterAll(hierarchicalTypes, typeFilters);
+    }
+
+    static Set<DeclaredType> getHierarchicalTypes(TypeMirror type,
+                                                  boolean includeSelf,
+                                                  boolean includeSuperTypes,
+                                                  boolean includeSuperInterfaces) {
+        return ofDeclaredTypes(getHierarchicalTypes(ofTypeElement(type),
+                includeSelf,
+                includeSuperTypes,
+                includeSuperInterfaces));
+    }
+
+    static List<TypeMirror> getInterfaces(TypeElement type, Predicate<TypeMirror>... interfaceFilters) {
+        return type == null ? emptyList() : filterAll((List<TypeMirror>) ofTypeElement(type).getInterfaces(), interfaceFilters);
+    }
+
+    static List<TypeMirror> getInterfaces(TypeMirror type, Predicate<TypeMirror>... interfaceFilters) {
+        return getInterfaces(ofTypeElement(type), interfaceFilters);
+    }
+
+    static Set<TypeElement> getAllInterfaces(TypeElement type, Predicate<TypeElement>... interfaceFilters) {
+        return type == null ? emptySet() : filterAll(ofTypeElements(getAllInterfaces(type.asType())), interfaceFilters);
+    }
+
+    static Set<? extends TypeMirror> getAllInterfaces(TypeMirror type, Predicate<TypeMirror>... interfaceFilters) {
+        if (type == null) {
+            return emptySet();
+        }
+        Set<TypeMirror> allInterfaces = new LinkedHashSet<>();
+        getInterfaces(type).forEach(i -> {
+            // Add current type's interfaces
+            allInterfaces.add(i);
+            // Add
+            allInterfaces.addAll(getAllInterfaces(i));
+        });
+        // Add all super types' interfaces
+        getAllSuperTypes(type).forEach(superType -> allInterfaces.addAll(getAllInterfaces(superType)));
+        return filterAll(allInterfaces, interfaceFilters);
+    }
+
+    static TypeElement getType(ProcessingEnvironment processingEnv, Type type) {
+        return type == null ? null : getType(processingEnv, type.getTypeName());
+    }
+
+    static TypeElement getType(ProcessingEnvironment processingEnv, TypeMirror type) {
+        return type == null ? null : getType(processingEnv, type.toString());
+    }
+
+    static TypeElement getType(ProcessingEnvironment processingEnv, CharSequence typeName) {
+        if (processingEnv == null || typeName == null) {
+            return null;
+        }
+        Elements elements = processingEnv.getElementUtils();
+        return elements.getTypeElement(typeName);
+    }
+
+    static TypeElement getSuperType(TypeElement type) {
+        return type == null ? null : ofTypeElement(type.getSuperclass());
+    }
+
+    static DeclaredType getSuperType(TypeMirror type) {
+        TypeElement superType = getSuperType(ofTypeElement(type));
+        return superType == null ? null : ofDeclaredType(superType.asType());
+    }
+
+    static Set<TypeElement> getAllSuperTypes(TypeElement type) {
+        return getAllSuperTypes(type, EMPTY_ARRAY);
+    }
+
+    static Set<TypeElement> getAllSuperTypes(TypeElement type, Predicate<TypeElement>... typeFilters) {
+        if (type == null) {
+            return emptySet();
+        }
+
+        Set<TypeElement> allSuperTypes = new LinkedHashSet<>();
+        TypeElement superType = getSuperType(type);
+        if (superType != null) {
+            // add super type
+            allSuperTypes.add(superType);
+            // add ancestors' types
+            allSuperTypes.addAll(getAllSuperTypes(superType));
+        }
+        return filterAll(allSuperTypes, typeFilters);
+    }
+
+    static Set<DeclaredType> getAllSuperTypes(TypeMirror type) {
+        return getAllSuperTypes(type, EMPTY_ARRAY);
+    }
+
+    static Set<DeclaredType> getAllSuperTypes(TypeMirror type, Predicate<DeclaredType>... typeFilters) {
+        return filterAll(ofDeclaredTypes(getAllSuperTypes(ofTypeElement(type))), typeFilters);
+    }
+
+    static boolean isDeclaredType(Element element) {
+        return element != null && isDeclaredType(element.asType());
+    }
+
+    static boolean isDeclaredType(TypeMirror type) {
+        return type instanceof DeclaredType;
+    }
+
+    static DeclaredType ofDeclaredType(Element element) {
+        return element == null ? null : ofDeclaredType(element.asType());
+    }
+
+    static DeclaredType ofDeclaredType(TypeMirror type) {
+        return isDeclaredType(type) ? DeclaredType.class.cast(type) : null;
+    }
+
+    static boolean isTypeElement(Element element) {
+        return element instanceof TypeElement;
+    }
+
+    static boolean isTypeElement(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        return declaredType != null && isTypeElement(declaredType.asElement());
+    }
+
+    static TypeElement ofTypeElement(Element element) {
+        return isTypeElement(element) ? TypeElement.class.cast(element) : null;
+    }
+
+    static TypeElement ofTypeElement(TypeMirror type) {
+        DeclaredType declaredType = ofDeclaredType(type);
+        if (declaredType != null) {
+            return ofTypeElement(declaredType.asElement());
+        }
+        return null;
+    }
+
+    static Set<DeclaredType> ofDeclaredTypes(Iterable<? extends Element> elements) {
+        return elements == null ?
+                emptySet() :
+                stream(elements.spliterator(), false)
+                        .map(TypeUtils::ofTypeElement)
+                        .filter(Objects::nonNull)
+                        .map(Element::asType)
+                        .map(TypeUtils::ofDeclaredType)
+                        .filter(Objects::nonNull)
+                        .collect(LinkedHashSet::new, Set::add, Set::addAll);
+    }
+
+    static Set<TypeElement> ofTypeElements(Iterable<? extends TypeMirror> types) {
+        return types == null ?
+                emptySet() :
+                stream(types.spliterator(), false)
+                        .map(TypeUtils::ofTypeElement)
+                        .filter(Objects::nonNull)
+                        .collect(LinkedHashSet::new, Set::add, Set::addAll);
+    }
+
+    static List<DeclaredType> listDeclaredTypes(Iterable<? extends Element> elements) {
+        return new ArrayList<>(ofDeclaredTypes(elements));
+    }
+
+    static List<TypeElement> listTypeElements(Iterable<? extends TypeMirror> types) {
+        return new ArrayList<>(ofTypeElements(types));
+    }
+
+    static URL getResource(ProcessingEnvironment processingEnv, Element type) {
+        return getResource(processingEnv, ofDeclaredType(type));
+    }
+
+    static URL getResource(ProcessingEnvironment processingEnv, TypeMirror type) {
+        return type == null ? null : getResource(processingEnv, type.toString());
+    }
+
+    static URL getResource(ProcessingEnvironment processingEnv, CharSequence type) {
+        String relativeName = getResourceName(type);
+        URL resource = null;
+        try {
+            if (relativeName != null) {
+                FileObject fileObject = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, "", relativeName);
+                resource = fileObject.toUri().toURL();
+                // try to open it
+                resource.getContent();
+            }
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        }
+
+        return resource;
+    }
+
+    static String getResourceName(CharSequence type) {
+        return type == null ? null : type.toString().replace('.', '/').concat(".class");
+    }
+}
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000..6c5909c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1,2 @@
+org.apache.dubbo.metadata.annotation.processing.ServiceDefinitionMetadataAnnotationProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataAnnotationProcessor
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
new file mode 100644
index 0000000..2ec903a
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder
@@ -0,0 +1,7 @@
+org.apache.dubbo.metadata.annotation.processing.builder.ArrayTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.CollectionTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.EnumTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.GeneralTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.MapTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.PrimitiveTypeDefinitionBuilder
+org.apache.dubbo.metadata.annotation.processing.builder.SimpleTypeDefinitionBuilder
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
new file mode 100644
index 0000000..0428626
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.AnnotatedMethodParameterProcessor
@@ -0,0 +1,10 @@
+# JAX-RS's implementations
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.QueryParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.FormParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.MatrixParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.HeaderParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.DefaultValueParameterProcessor
+
+# Spring Web MVC's implementations
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.RequestParamParameterProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.RequestHeaderParameterProcessor
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor
new file mode 100644
index 0000000..43c307d
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/main/resources/META-INF/services/org.apache.dubbo.metadata.annotation.processing.rest.ServiceRestMetadataProcessor
@@ -0,0 +1,3 @@
+# org.apache.dubbo.metadata.annotation.processing.rest.DefaultServiceRestMetadataProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.jaxrs.JAXRSServiceRestMetadataProcessor
+org.apache.dubbo.metadata.annotation.processing.rest.springmvc.SpringMvcServiceRestMetadataProcessor
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.java
new file mode 100644
index 0000000..0e5adf4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/AbstractAnnotationProcessingTest.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.annotation.processing;
+
+import org.apache.dubbo.metadata.annotation.processing.util.TypeUtils;
+import org.apache.dubbo.metadata.tools.Compiler;
+import org.apache.dubbo.metadata.tools.TestProcessor;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+/**
+ * Abstract {@link Annotation} Processing Test case
+ *
+ * @since 2.7.5
+ */
+public abstract class AbstractAnnotationProcessingTest {
+
+    protected ProcessingEnvironment processingEnv;
+
+    protected Elements elements;
+
+    protected Types types;
+
+    @BeforeEach
+    public final void init() throws IOException {
+        Set<Class<?>> classesToBeCompiled = new LinkedHashSet<>();
+        classesToBeCompiled.add(getClass());
+        addCompiledClasses(classesToBeCompiled);
+        TestProcessor testProcessor = new TestProcessor();
+        Compiler compiler = new Compiler();
+        compiler.processors(testProcessor);
+        compiler.compile(classesToBeCompiled.toArray(new Class[0]));
+        processingEnv = testProcessor.getProcessingEnvironment();
+        elements = processingEnv.getElementUtils();
+        types = processingEnv.getTypeUtils();
+        beforeEach();
+    }
+
+    protected abstract void addCompiledClasses(Set<Class<?>> classesToBeCompiled);
+
+    protected abstract void beforeEach();
+
+    protected TypeElement getType(Class<?> type) {
+        return TypeUtils.getType(processingEnv, type);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..efab557
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ArrayTypeDefinitionBuilderTest.java
@@ -0,0 +1,121 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link ArrayTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class ArrayTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private ArrayTypeDefinitionBuilder builder;
+
+    private TypeElement testType;
+
+    private VariableElement integersField;
+
+    private VariableElement stringsField;
+
+    private VariableElement primitiveTypeModelsField;
+
+    private VariableElement modelsField;
+
+    private VariableElement colorsField;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(ArrayTypeModel.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new ArrayTypeDefinitionBuilder();
+        testType = getType(ArrayTypeModel.class);
+        integersField = findField(testType, "integers");
+        stringsField = findField(testType, "strings");
+        primitiveTypeModelsField = findField(testType, "primitiveTypeModels");
+        modelsField = findField(testType, "models");
+        colorsField = findField(testType, "colors");
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, integersField.asType()));
+        assertTrue(builder.accept(processingEnv, stringsField.asType()));
+        assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+        assertTrue(builder.accept(processingEnv, modelsField.asType()));
+        assertTrue(builder.accept(processingEnv, colorsField.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+
+        buildAndAssertTypeDefinition(processingEnv, integersField, "int[]", "int", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, stringsField, "java.lang.String[]", "java.lang.String", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+                "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel[]",
+                "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, modelsField,
+                "org.apache.dubbo.metadata.annotation.processing.model.Model[]",
+                "org.apache.dubbo.metadata.annotation.processing.model.Model", builder, (def, subDef) -> {
+                    TypeElement subType = elements.getTypeElement(subDef.getType());
+                    assertEquals(ElementKind.CLASS, subType.getKind());
+                });
+
+        buildAndAssertTypeDefinition(processingEnv, colorsField,
+                "org.apache.dubbo.metadata.annotation.processing.model.Color[]",
+                "org.apache.dubbo.metadata.annotation.processing.model.Color", builder, (def, subDef) -> {
+                    TypeElement subType = elements.getTypeElement(subDef.getType());
+                    assertEquals(ElementKind.ENUM, subType.getKind());
+                });
+
+    }
+
+    static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
+                                             String expectedType, String compositeType, TypeDefinitionBuilder builder,
+                                             BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
+        TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+        TypeDefinition subTypeDefinition = typeDefinition.getItems().get(0);
+        assertEquals(expectedType, typeDefinition.getType());
+        assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+        assertEquals(compositeType, subTypeDefinition.getType());
+//        assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+        Stream.of(assertions).forEach(assertion -> assertion.accept(typeDefinition, subTypeDefinition));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..1bfb32e
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/CollectionTypeDefinitionBuilderTest.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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.CollectionTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.ArrayTypeDefinitionBuilderTest.buildAndAssertTypeDefinition;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link CollectionTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class CollectionTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private CollectionTypeDefinitionBuilder builder;
+
+    private VariableElement stringsField;
+
+    private VariableElement colorsField;
+
+    private VariableElement primitiveTypeModelsField;
+
+    private VariableElement modelsField;
+
+    private VariableElement modelArraysField;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(CollectionTypeModel.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new CollectionTypeDefinitionBuilder();
+        TypeElement testType = getType(CollectionTypeModel.class);
+        stringsField = findField( testType, "strings");
+        colorsField = findField( testType, "colors");
+        primitiveTypeModelsField = findField( testType, "primitiveTypeModels");
+        modelsField = findField( testType, "models");
+        modelArraysField = findField( testType, "modelArrays");
+
+        assertEquals("strings", stringsField.getSimpleName().toString());
+        assertEquals("colors", colorsField.getSimpleName().toString());
+        assertEquals("primitiveTypeModels", primitiveTypeModelsField.getSimpleName().toString());
+        assertEquals("models", modelsField.getSimpleName().toString());
+        assertEquals("modelArrays", modelArraysField.getSimpleName().toString());
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, stringsField.asType()));
+        assertTrue(builder.accept(processingEnv, colorsField.asType()));
+        assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+        assertTrue(builder.accept(processingEnv, modelsField.asType()));
+        assertTrue(builder.accept(processingEnv, modelArraysField.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+
+        buildAndAssertTypeDefinition(processingEnv, stringsField, "java.util.Collection<java.lang.String>", "java.lang.String", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, colorsField, "java.util.List<org.apache.dubbo.metadata.annotation.processing.model.Color>",
+                "org.apache.dubbo.metadata.annotation.processing.model.Color", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+                "java.util.Queue<org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel>",
+                "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, modelsField,
+                "java.util.Deque<org.apache.dubbo.metadata.annotation.processing.model.Model>",
+                "org.apache.dubbo.metadata.annotation.processing.model.Model", builder);
+
+        buildAndAssertTypeDefinition(processingEnv, modelArraysField,
+                "java.util.Set<org.apache.dubbo.metadata.annotation.processing.model.Model[]>",
+                "org.apache.dubbo.metadata.annotation.processing.model.Model[]", builder);
+
+
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..52f33aa
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/EnumTypeDefinitionBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.builder.TypeDefinitionBuilder.build;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link EnumTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class EnumTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private EnumTypeDefinitionBuilder builder;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(Color.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new EnumTypeDefinitionBuilder();
+    }
+
+    @Test
+    public void testAccept() {
+        TypeElement typeElement = getType(Color.class);
+        assertTrue(builder.accept(processingEnv, typeElement.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+        TypeElement typeElement = getType(Color.class);
+        TypeDefinition typeDefinition = build(processingEnv, typeElement);
+        assertEquals(Color.class.getName(), typeDefinition.getType());
+        assertEquals(asList("RED", "YELLOW", "BLUE"), typeDefinition.getEnums());
+//        assertEquals(typeDefinition.getTypeBuilderName(), builder.getClass().getName());
+    }
+
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..8be38dc
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/GeneralTypeDefinitionBuilderTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.CollectionTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.SimpleTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link GeneralTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class GeneralTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private GeneralTypeDefinitionBuilder builder;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(Model.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new GeneralTypeDefinitionBuilder();
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, getType(Model.class).asType()));
+        assertTrue(builder.accept(processingEnv, getType(PrimitiveTypeModel.class).asType()));
+        assertTrue(builder.accept(processingEnv, getType(SimpleTypeModel.class).asType()));
+        assertTrue(builder.accept(processingEnv, getType(ArrayTypeModel.class).asType()));
+        assertTrue(builder.accept(processingEnv, getType(CollectionTypeModel.class).asType()));
+        assertFalse(builder.accept(processingEnv, getType(Color.class).asType()));
+    }
+
+    @Test
+    public void testBuild() {
+
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..3229c31
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/MapTypeDefinitionBuilderTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.MapTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+import java.util.function.BiConsumer;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link MapTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class MapTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private MapTypeDefinitionBuilder builder;
+
+    private VariableElement stringsField;
+
+    private VariableElement colorsField;
+
+    private VariableElement primitiveTypeModelsField;
+
+    private VariableElement modelsField;
+
+    private VariableElement modelArraysField;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(MapTypeModel.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new MapTypeDefinitionBuilder();
+        TypeElement testType = getType(MapTypeModel.class);
+        stringsField = findField( testType, "strings");
+        colorsField = findField( testType, "colors");
+        primitiveTypeModelsField = findField( testType, "primitiveTypeModels");
+        modelsField = findField( testType, "models");
+        modelArraysField = findField( testType, "modelArrays");
+
+        assertEquals("strings", stringsField.getSimpleName().toString());
+        assertEquals("colors", colorsField.getSimpleName().toString());
+        assertEquals("primitiveTypeModels", primitiveTypeModelsField.getSimpleName().toString());
+        assertEquals("models", modelsField.getSimpleName().toString());
+        assertEquals("modelArrays", modelArraysField.getSimpleName().toString());
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, stringsField.asType()));
+        assertTrue(builder.accept(processingEnv, colorsField.asType()));
+        assertTrue(builder.accept(processingEnv, primitiveTypeModelsField.asType()));
+        assertTrue(builder.accept(processingEnv, modelsField.asType()));
+        assertTrue(builder.accept(processingEnv, modelArraysField.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+
+        buildAndAssertTypeDefinition(processingEnv, stringsField,
+                "java.util.Map<java.lang.String,java.lang.String>",
+                "java.lang.String",
+                "java.lang.String",
+                builder);
+
+        buildAndAssertTypeDefinition(processingEnv, colorsField,
+                "java.util.SortedMap<java.lang.String,org.apache.dubbo.metadata.annotation.processing.model.Color>",
+                "java.lang.String",
+                "org.apache.dubbo.metadata.annotation.processing.model.Color",
+                builder);
+
+        buildAndAssertTypeDefinition(processingEnv, primitiveTypeModelsField,
+                "java.util.NavigableMap<org.apache.dubbo.metadata.annotation.processing.model.Color,org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel>",
+                "org.apache.dubbo.metadata.annotation.processing.model.Color",
+                "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel",
+                builder);
+
+        buildAndAssertTypeDefinition(processingEnv, modelsField,
+                "java.util.HashMap<java.lang.String,org.apache.dubbo.metadata.annotation.processing.model.Model>",
+                "java.lang.String",
+                "org.apache.dubbo.metadata.annotation.processing.model.Model",
+                builder);
+
+        buildAndAssertTypeDefinition(processingEnv, modelArraysField,
+                "java.util.TreeMap<org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel,org.apache.dubbo.metadata.annotation.processing.model.Model[]>",
+                "org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel",
+                "org.apache.dubbo.metadata.annotation.processing.model.Model[]",
+                builder);
+    }
+
+    static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field,
+                                             String expectedType, String keyType, String valueType,
+                                             TypeDefinitionBuilder builder,
+                                             BiConsumer<TypeDefinition, TypeDefinition>... assertions) {
+        TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+        TypeDefinition keyTypeDefinition = typeDefinition.getItems().get(0);
+        TypeDefinition valueTypeDefinition = typeDefinition.getItems().get(1);
+        assertEquals(expectedType, typeDefinition.getType());
+        assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+        assertEquals(keyType, keyTypeDefinition.getType());
+        assertEquals(valueType, valueTypeDefinition.getType());
+//        assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+        Stream.of(assertions).forEach(assertion -> assertion.accept(typeDefinition, keyTypeDefinition));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..0953885
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/PrimitiveTypeDefinitionBuilderTest.java
@@ -0,0 +1,130 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.definition.model.TypeDefinition;
+
+import org.junit.jupiter.api.Test;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+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 PrimitiveTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class PrimitiveTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private PrimitiveTypeDefinitionBuilder builder;
+
+    private VariableElement zField;
+
+    private VariableElement bField;
+
+    private VariableElement cField;
+
+    private VariableElement sField;
+
+    private VariableElement iField;
+
+    private VariableElement lField;
+
+    private VariableElement fField;
+
+    private VariableElement dField;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(PrimitiveTypeModel.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+
+        builder = new PrimitiveTypeDefinitionBuilder();
+
+        TypeElement testType = getType(PrimitiveTypeModel.class);
+
+        zField = findField( testType, "z");
+        bField = findField( testType, "b");
+        cField = findField( testType, "c");
+        sField = findField( testType, "s");
+        iField = findField( testType, "i");
+        lField = findField( testType, "l");
+        fField = findField( testType, "f");
+        dField = findField( testType, "d");
+
+        assertEquals("boolean", zField.asType().toString());
+        assertEquals("byte", bField.asType().toString());
+        assertEquals("char", cField.asType().toString());
+        assertEquals("short", sField.asType().toString());
+        assertEquals("int", iField.asType().toString());
+        assertEquals("long", lField.asType().toString());
+        assertEquals("float", fField.asType().toString());
+        assertEquals("double", dField.asType().toString());
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, zField.asType()));
+        assertTrue(builder.accept(processingEnv, bField.asType()));
+        assertTrue(builder.accept(processingEnv, cField.asType()));
+        assertTrue(builder.accept(processingEnv, sField.asType()));
+        assertTrue(builder.accept(processingEnv, iField.asType()));
+        assertTrue(builder.accept(processingEnv, lField.asType()));
+        assertTrue(builder.accept(processingEnv, fField.asType()));
+        assertTrue(builder.accept(processingEnv, dField.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+        buildAndAssertTypeDefinition(processingEnv, zField, builder);
+        buildAndAssertTypeDefinition(processingEnv, bField, builder);
+        buildAndAssertTypeDefinition(processingEnv, cField, builder);
+        buildAndAssertTypeDefinition(processingEnv, sField, builder);
+        buildAndAssertTypeDefinition(processingEnv, iField, builder);
+        buildAndAssertTypeDefinition(processingEnv, lField, builder);
+        buildAndAssertTypeDefinition(processingEnv, zField, builder);
+        buildAndAssertTypeDefinition(processingEnv, fField, builder);
+        buildAndAssertTypeDefinition(processingEnv, dField, builder);
+    }
+
+    static void buildAndAssertTypeDefinition(ProcessingEnvironment processingEnv, VariableElement field, TypeDefinitionBuilder builder) {
+        TypeDefinition typeDefinition = TypeDefinitionBuilder.build(processingEnv, field);
+        assertBasicTypeDefinition(typeDefinition, field.asType().toString(), builder);
+        assertEquals(field.getSimpleName().toString(), typeDefinition.get$ref());
+    }
+
+    static void assertBasicTypeDefinition(TypeDefinition typeDefinition, String type, TypeDefinitionBuilder builder) {
+        assertEquals(type, typeDefinition.getType());
+//        assertEquals(builder.getClass().getName(), typeDefinition.getTypeBuilderName());
+        assertTrue(typeDefinition.getProperties().isEmpty());
+        assertTrue(typeDefinition.getItems().isEmpty());
+        assertTrue(typeDefinition.getEnums().isEmpty());
+        assertNull(typeDefinition.getId());
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.java
new file mode 100644
index 0000000..c891f87
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/ServiceDefinitionBuilderTest.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.metadata.annotation.processing.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.ServiceDefinitionBuilder.build;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link ServiceDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class ServiceDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(TestServiceImpl.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+    }
+
+    @Test
+    public void testBuild() {
+        ServiceDefinition serviceDefinition = build(processingEnv, getType(TestServiceImpl.class));
+        assertEquals(TestServiceImpl.class.getTypeName(), serviceDefinition.getCanonicalName());
+        assertEquals("org/apache/dubbo/metadata/tools/TestServiceImpl.class", serviceDefinition.getCodeSource());
+        // types
+        int i = 0;
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("java.lang.AutoCloseable", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("java.io.Serializable", serviceDefinition.getTypes().get(i++).getType());
+        assertEquals("java.util.EventListener", serviceDefinition.getTypes().get(i++).getType());
+        // methods
+        assertEquals(14, serviceDefinition.getMethods().size());
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java
new file mode 100644
index 0000000..365ac56
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/builder/SimpleTypeDefinitionBuilderTest.java
@@ -0,0 +1,146 @@
+/*
+ * 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.builder;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.SimpleTypeModel;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.builder.PrimitiveTypeDefinitionBuilderTest.buildAndAssertTypeDefinition;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+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 SimpleTypeDefinitionBuilder} Test
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeDefinitionBuilderTest extends AbstractAnnotationProcessingTest {
+
+    private SimpleTypeDefinitionBuilder builder;
+
+    private VariableElement vField;
+
+    private VariableElement zField;
+
+    private VariableElement cField;
+
+    private VariableElement bField;
+
+    private VariableElement sField;
+
+    private VariableElement iField;
+
+    private VariableElement lField;
+
+    private VariableElement fField;
+
+    private VariableElement dField;
+
+    private VariableElement strField;
+
+    private VariableElement bdField;
+
+    private VariableElement biField;
+
+    private VariableElement dtField;
+
+    private VariableElement invalidField;
+
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(SimpleTypeModel.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        builder = new SimpleTypeDefinitionBuilder();
+        TypeElement testType = getType(SimpleTypeModel.class);
+        vField = findField(testType, "v");
+        zField = findField(testType, "z");
+        cField = findField(testType, "c");
+        bField = findField(testType, "b");
+        sField = findField(testType, "s");
+        iField = findField(testType, "i");
+        lField = findField(testType, "l");
+        fField = findField(testType, "f");
+        dField = findField(testType, "d");
+        strField = findField(testType, "str");
+        bdField = findField(testType, "bd");
+        biField = findField(testType, "bi");
+        dtField = findField(testType, "dt");
+        invalidField = findField(testType, "invalid");
+
+        assertEquals("java.lang.Void", vField.asType().toString());
+        assertEquals("java.lang.Boolean", zField.asType().toString());
+        assertEquals("java.lang.Character", cField.asType().toString());
+        assertEquals("java.lang.Byte", bField.asType().toString());
+        assertEquals("java.lang.Short", sField.asType().toString());
+        assertEquals("java.lang.Integer", iField.asType().toString());
+        assertEquals("java.lang.Long", lField.asType().toString());
+        assertEquals("java.lang.Float", fField.asType().toString());
+        assertEquals("java.lang.Double", dField.asType().toString());
+        assertEquals("java.lang.String", strField.asType().toString());
+        assertEquals("java.math.BigDecimal", bdField.asType().toString());
+        assertEquals("java.math.BigInteger", biField.asType().toString());
+        assertEquals("java.util.Date", dtField.asType().toString());
+        assertEquals("int", invalidField.asType().toString());
+    }
+
+    @Test
+    public void testAccept() {
+        assertTrue(builder.accept(processingEnv, vField.asType()));
+        assertTrue(builder.accept(processingEnv, zField.asType()));
+        assertTrue(builder.accept(processingEnv, cField.asType()));
+        assertTrue(builder.accept(processingEnv, bField.asType()));
+        assertTrue(builder.accept(processingEnv, sField.asType()));
+        assertTrue(builder.accept(processingEnv, iField.asType()));
+        assertTrue(builder.accept(processingEnv, lField.asType()));
+        assertTrue(builder.accept(processingEnv, fField.asType()));
+        assertTrue(builder.accept(processingEnv, dField.asType()));
+        assertTrue(builder.accept(processingEnv, strField.asType()));
+        assertTrue(builder.accept(processingEnv, bdField.asType()));
+        assertTrue(builder.accept(processingEnv, biField.asType()));
+        assertTrue(builder.accept(processingEnv, dtField.asType()));
+        // false condition
+        assertFalse(builder.accept(processingEnv, invalidField.asType()));
+    }
+
+    @Test
+    public void testBuild() {
+        buildAndAssertTypeDefinition(processingEnv, vField, builder);
+        buildAndAssertTypeDefinition(processingEnv, zField, builder);
+        buildAndAssertTypeDefinition(processingEnv, cField, builder);
+        buildAndAssertTypeDefinition(processingEnv, sField, builder);
+        buildAndAssertTypeDefinition(processingEnv, iField, builder);
+        buildAndAssertTypeDefinition(processingEnv, lField, builder);
+        buildAndAssertTypeDefinition(processingEnv, fField, builder);
+        buildAndAssertTypeDefinition(processingEnv, dField, builder);
+        buildAndAssertTypeDefinition(processingEnv, strField, builder);
+        buildAndAssertTypeDefinition(processingEnv, bdField, builder);
+        buildAndAssertTypeDefinition(processingEnv, biField, builder);
+        buildAndAssertTypeDefinition(processingEnv, dtField, builder);
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
index b3b27e6..db6874a 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/ArrayTypeModel.java
@@ -14,27 +14,23 @@
  * 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 java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
 
 /**
- * {@link DubboServiceLoader} Test
+ * Array Type Model
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class ArrayTypeModel {
+
+    private int[] integers;                           // Primitive type array
+
+    private String[] strings;                         // Simple type array
+
+    private PrimitiveTypeModel[] primitiveTypeModels; // Complex type array
+
+    private Model[] models;                           // Hierarchical Complex type array
+
+    private Color[] colors;                           // Enum type array
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
index b3b27e6..b2ce91d 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/CollectionTypeModel.java
@@ -14,27 +14,29 @@
  * 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;
+package org.apache.dubbo.metadata.annotation.processing.model;
 
+import java.util.Collection;
+import java.util.Deque;
 import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.Queue;
+import java.util.Set;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link Collection} Type Model
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
+public class CollectionTypeModel {
+
+    private Collection<String> strings; // The composite element is simple type
+
+    private List<Color> colors;     // The composite element is Enum type
+
+    private Queue<PrimitiveTypeModel> primitiveTypeModels;  // The composite element is POJO type
+
+    private Deque<Model> models;  // The composite element is hierarchical POJO type
+
+    private Set<Model[]> modelArrays; // The composite element is hierarchical POJO type
+
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
index b3b27e6..6c34404 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Color.java
@@ -14,27 +14,33 @@
  * 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 java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
 
 /**
- * {@link DubboServiceLoader} Test
+ * Color enumeration
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public enum Color {
+
+    RED(1),
+    YELLOW(2),
+    BLUE(3);
+
+    private final int value;
+
+    Color(int value) {
+        this.value = value;
+    }
+
+    @Override
+    public String toString() {
+        return "Color{" +
+                "value=" + value +
+                "} " + super.toString();
+    }
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public int getValue() {
+        return value;
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
similarity index 53%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
index b3b27e6..f1613ae 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/MapTypeModel.java
@@ -14,27 +14,28 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.model;
 
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NavigableMap;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link Map} Type model
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class MapTypeModel {
+
+    private Map<String, String> strings; // The composite element is simple type
+
+    private SortedMap<String, Color> colors;     // The composite element is Enum type
+
+    private NavigableMap<Color, PrimitiveTypeModel> primitiveTypeModels;  // The composite element is POJO type
+
+    private HashMap<String, Model> models;  // The composite element is hierarchical POJO type
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
+    private TreeMap<PrimitiveTypeModel, Model[]> modelArrays; // The composite element is hierarchical POJO type
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java
new file mode 100644
index 0000000..e3c72a5
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/Model.java
@@ -0,0 +1,89 @@
+/*
+ * 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.model;
+
+import org.apache.dubbo.metadata.tools.Parent;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Model Object
+ */
+public class Model extends Parent {
+
+    private float f;
+
+    private double d;
+
+    private TimeUnit tu;
+
+    private String str;
+
+    private BigInteger bi;
+
+    private BigDecimal bd;
+
+    public float getF() {
+        return f;
+    }
+
+    public void setF(float f) {
+        this.f = f;
+    }
+
+    public double getD() {
+        return d;
+    }
+
+    public void setD(double d) {
+        this.d = d;
+    }
+
+    public TimeUnit getTu() {
+        return tu;
+    }
+
+    public void setTu(TimeUnit tu) {
+        this.tu = tu;
+    }
+
+    public String getStr() {
+        return str;
+    }
+
+    public void setStr(String str) {
+        this.str = str;
+    }
+
+    public BigInteger getBi() {
+        return bi;
+    }
+
+    public void setBi(BigInteger bi) {
+        this.bi = bi;
+    }
+
+    public BigDecimal getBd() {
+        return bd;
+    }
+
+    public void setBd(BigDecimal bd) {
+        this.bd = bd;
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
similarity index 54%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
index b3b27e6..7adc685 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/PrimitiveTypeModel.java
@@ -14,27 +14,60 @@
  * 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 java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+package org.apache.dubbo.metadata.annotation.processing.model;
 
 /**
- * {@link DubboServiceLoader} Test
+ * Primitive Type model
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+public class PrimitiveTypeModel {
+
+    private boolean z;
+
+    private byte b;
+
+    private char c;
+
+    private short s;
+
+    private int i;
+
+    private long l;
+
+    private float f;
+
+    private double d;
+
+    public boolean isZ() {
+        return z;
+    }
+
+    public byte getB() {
+        return b;
+    }
+
+    public char getC() {
+        return c;
+    }
+
+    public short getS() {
+        return s;
+    }
+
+    public int getI() {
+        return i;
+    }
+
+    public long getL() {
+        return l;
+    }
+
+    public float getF() {
+        return f;
+    }
+
+    public double getD() {
+        return d;
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java
new file mode 100644
index 0000000..b6f40ec
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/model/SimpleTypeModel.java
@@ -0,0 +1,161 @@
+/*
+ * 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.model;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.Date;
+
+/**
+ * Simple Type model
+ *
+ * @since 2.7.5
+ */
+public class SimpleTypeModel {
+
+    private Void v;
+
+    private Boolean z;
+
+    private Character c;
+
+    private Byte b;
+
+    private Short s;
+
+    private Integer i;
+
+    private Long l;
+
+    private Float f;
+
+    private Double d;
+
+    private String str;
+
+    private BigDecimal bd;
+
+    private BigInteger bi;
+
+    private Date dt;
+
+    private int invalid;
+
+    public Void getV() {
+        return v;
+    }
+
+    public void setV(Void v) {
+        this.v = v;
+    }
+
+    public Boolean getZ() {
+        return z;
+    }
+
+    public void setZ(Boolean z) {
+        this.z = z;
+    }
+
+    public Character getC() {
+        return c;
+    }
+
+    public void setC(Character c) {
+        this.c = c;
+    }
+
+    public Byte getB() {
+        return b;
+    }
+
+    public void setB(Byte b) {
+        this.b = b;
+    }
+
+    public Short getS() {
+        return s;
+    }
+
+    public void setS(Short s) {
+        this.s = s;
+    }
+
+    public Integer getI() {
+        return i;
+    }
+
+    public void setI(Integer i) {
+        this.i = i;
+    }
+
+    public Long getL() {
+        return l;
+    }
+
+    public void setL(Long l) {
+        this.l = l;
+    }
+
+    public Float getF() {
+        return f;
+    }
+
+    public void setF(Float f) {
+        this.f = f;
+    }
+
+    public Double getD() {
+        return d;
+    }
+
+    public void setD(Double d) {
+        this.d = d;
+    }
+
+    public String getStr() {
+        return str;
+    }
+
+    public void setStr(String str) {
+        this.str = str;
+    }
+
+    public BigDecimal getBd() {
+        return bd;
+    }
+
+    public void setBd(BigDecimal bd) {
+        this.bd = bd;
+    }
+
+    public BigInteger getBi() {
+        return bi;
+    }
+
+    public void setBi(BigInteger bi) {
+        this.bi = bi;
+    }
+
+    public Date getDt() {
+        return dt;
+    }
+
+    public void setDt(Date dt) {
+        this.dt = dt;
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java
new file mode 100644
index 0000000..a68cc23
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/AnnotationUtilsTest.java
@@ -0,0 +1,232 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.tools.SpringRestService;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import javax.ws.rs.Path;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.findMetaAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAllAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAnnotations;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getAttribute;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.getValue;
+import static org.apache.dubbo.metadata.annotation.processing.util.AnnotationUtils.isAnnotationPresent;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getAllDeclaredMethods;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The {@link AnnotationUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class AnnotationUtilsTest extends AbstractAnnotationProcessingTest {
+
+    private TypeElement testType;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+    }
+
+    @Override
+    protected void beforeEach() {
+        testType = getType(TestServiceImpl.class);
+    }
+
+    @Test
+    public void testGetAnnotation() {
+        AnnotationMirror serviceAnnotation = getAnnotation(testType, Service.class);
+        assertEquals("3.0.0", getAttribute(serviceAnnotation, "version"));
+        assertEquals("test", getAttribute(serviceAnnotation, "group"));
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(serviceAnnotation, "interfaceName"));
+
+        assertNull(getAnnotation(testType, (Class) null));
+        assertNull(getAnnotation(testType, (String) null));
+
+        assertNull(getAnnotation(testType.asType(), (Class) null));
+        assertNull(getAnnotation(testType.asType(), (String) null));
+
+        assertNull(getAnnotation((Element) null, (Class) null));
+        assertNull(getAnnotation((Element) null, (String) null));
+
+        assertNull(getAnnotation((TypeElement) null, (Class) null));
+        assertNull(getAnnotation((TypeElement) null, (String) null));
+    }
+
+    @Test
+    public void testGetAnnotations() {
+        List<AnnotationMirror> annotations = getAnnotations(testType);
+        Iterator<AnnotationMirror> iterator = annotations.iterator();
+
+        assertEquals(2, annotations.size());
+        assertEquals("com.alibaba.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+        assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+        annotations = getAnnotations(testType, Service.class);
+        iterator = annotations.iterator();
+        assertEquals(1, annotations.size());
+        assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+        annotations = getAnnotations(testType.asType(), Service.class);
+        iterator = annotations.iterator();
+        assertEquals(1, annotations.size());
+        assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+        annotations = getAnnotations(testType.asType(), Service.class.getTypeName());
+        iterator = annotations.iterator();
+        assertEquals(1, annotations.size());
+        assertEquals("org.apache.dubbo.config.annotation.Service", iterator.next().getAnnotationType().toString());
+
+        annotations = getAnnotations(testType, Override.class);
+        assertEquals(0, annotations.size());
+
+        annotations = getAnnotations(testType, com.alibaba.dubbo.config.annotation.Service.class);
+        assertEquals(1, annotations.size());
+
+        assertTrue(getAnnotations(null, (Class) null).isEmpty());
+        assertTrue(getAnnotations(null, (String) null).isEmpty());
+        assertTrue(getAnnotations(testType, (Class) null).isEmpty());
+        assertTrue(getAnnotations(testType, (String) null).isEmpty());
+
+        assertTrue(getAnnotations(null, Service.class).isEmpty());
+        assertTrue(getAnnotations(null, Service.class.getTypeName()).isEmpty());
+    }
+
+    @Test
+    public void testGetAllAnnotations() {
+
+        List<AnnotationMirror> annotations = getAllAnnotations(testType);
+        assertEquals(5, annotations.size());
+
+        annotations = getAllAnnotations(testType.asType(), annotation -> true);
+        assertEquals(5, annotations.size());
+
+        annotations = getAllAnnotations(processingEnv, TestServiceImpl.class);
+        assertEquals(5, annotations.size());
+
+        annotations = getAllAnnotations(testType.asType(), Service.class);
+        assertEquals(2, annotations.size());
+
+        annotations = getAllAnnotations(testType, Override.class);
+        assertEquals(0, annotations.size());
+
+        annotations = getAllAnnotations(testType.asType(), com.alibaba.dubbo.config.annotation.Service.class);
+        assertEquals(2, annotations.size());
+
+        assertTrue(getAllAnnotations((Element) null, (Class) null).isEmpty());
+        assertTrue(getAllAnnotations((TypeMirror) null, (String) null).isEmpty());
+        assertTrue(getAllAnnotations((ProcessingEnvironment) null, (Class) null).isEmpty());
+        assertTrue(getAllAnnotations((ProcessingEnvironment) null, (String) null).isEmpty());
+
+        assertTrue(getAllAnnotations((Element) null).isEmpty());
+        assertTrue(getAllAnnotations((TypeMirror) null).isEmpty());
+        assertTrue(getAllAnnotations(processingEnv, (Class) null).isEmpty());
+        assertTrue(getAllAnnotations(processingEnv, (String) null).isEmpty());
+
+
+        assertTrue(getAllAnnotations(testType, (Class) null).isEmpty());
+        assertTrue(getAllAnnotations(testType.asType(), (Class) null).isEmpty());
+
+        assertTrue(getAllAnnotations(testType, (String) null).isEmpty());
+        assertTrue(getAllAnnotations(testType.asType(), (String) null).isEmpty());
+
+        assertTrue(getAllAnnotations((Element) null, Service.class).isEmpty());
+        assertTrue(getAllAnnotations((TypeMirror) null, Service.class.getTypeName()).isEmpty());
+    }
+
+
+    @Test
+    public void testFindAnnotation() {
+
+        assertEquals("org.apache.dubbo.config.annotation.Service", findAnnotation(testType, Service.class).getAnnotationType().toString());
+        assertEquals("com.alibaba.dubbo.config.annotation.Service", findAnnotation(testType, com.alibaba.dubbo.config.annotation.Service.class).getAnnotationType().toString());
+        assertEquals("javax.ws.rs.Path", findAnnotation(testType, Path.class).getAnnotationType().toString());
+        assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class).getAnnotationType().toString());
+        assertEquals("javax.ws.rs.Path", findAnnotation(testType.asType(), Path.class.getTypeName()).getAnnotationType().toString());
+        assertNull(findAnnotation(testType, Override.class));
+
+        assertNull(findAnnotation((Element) null, (Class) null));
+        assertNull(findAnnotation((Element) null, (String) null));
+        assertNull(findAnnotation((TypeMirror) null, (Class) null));
+        assertNull(findAnnotation((TypeMirror) null, (String) null));
+
+        assertNull(findAnnotation(testType, (Class) null));
+        assertNull(findAnnotation(testType, (String) null));
+        assertNull(findAnnotation(testType.asType(), (Class) null));
+        assertNull(findAnnotation(testType.asType(), (String) null));
+    }
+
+    @Test
+    public void testFindMetaAnnotation() {
+        getAllDeclaredMethods(getType(TestService.class)).forEach(method -> {
+            assertEquals("javax.ws.rs.HttpMethod", findMetaAnnotation(method, "javax.ws.rs.HttpMethod").getAnnotationType().toString());
+        });
+    }
+
+    @Test
+    public void testGetAttribute() {
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(findAnnotation(testType, Service.class), "interfaceName"));
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", getAttribute(findAnnotation(testType, Service.class).getElementValues(), "interfaceName"));
+        assertEquals("/echo", getAttribute(findAnnotation(testType, Path.class), "value"));
+
+        assertNull(getAttribute(findAnnotation(testType, Path.class), null));
+        assertNull(getAttribute(findAnnotation(testType, (Class) null), null));
+
+        ExecutableElement method = findMethod(getType(SpringRestService.class), "param", String.class);
+
+        AnnotationMirror annotation = findAnnotation(method, GetMapping.class);
+
+        assertArrayEquals(new String[]{"/param"}, (String[]) getAttribute(annotation, "value"));
+        assertNull(getAttribute(annotation, "path"));
+    }
+
+    @Test
+    public void testGetValue() {
+        AnnotationMirror pathAnnotation = getAnnotation(getType(TestService.class), Path.class);
+        assertEquals("/echo", getValue(pathAnnotation));
+    }
+
+    @Test
+    public void testIsAnnotationPresent() {
+        assertTrue(isAnnotationPresent(testType, "org.apache.dubbo.config.annotation.Service"));
+        assertTrue(isAnnotationPresent(testType, "com.alibaba.dubbo.config.annotation.Service"));
+        assertTrue(isAnnotationPresent(testType, "javax.ws.rs.Path"));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java
new file mode 100644
index 0000000..5776791
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/FieldUtilsTest.java
@@ -0,0 +1,259 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import static javax.lang.model.element.Modifier.FINAL;
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.element.Modifier.PUBLIC;
+import static javax.lang.model.element.Modifier.STATIC;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getAllDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getAllNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getNonStaticFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isEnumMemberField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.isNonStaticField;
+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 FieldUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class FieldUtilsTest extends AbstractAnnotationProcessingTest {
+
+    private TypeElement testType;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+    }
+
+    @Override
+    protected void beforeEach() {
+        testType = getType(TestServiceImpl.class);
+    }
+
+    @Test
+    public void testGetDeclaredFields() {
+        TypeElement type = getType(Model.class);
+        List<VariableElement> fields = getDeclaredFields(type);
+        assertModelFields(fields);
+
+        fields = getDeclaredFields(type.asType());
+        assertModelFields(fields);
+
+        assertTrue(getDeclaredFields((Element) null).isEmpty());
+        assertTrue(getDeclaredFields((TypeMirror) null).isEmpty());
+
+        fields = getDeclaredFields(type, f -> "f".equals(f.getSimpleName().toString()));
+        assertEquals(1, fields.size());
+        assertEquals("f", fields.get(0).getSimpleName().toString());
+    }
+
+    @Test
+    public void testGetAllDeclaredFields() {
+        TypeElement type = getType(Model.class);
+
+        List<VariableElement> fields = getAllDeclaredFields(type);
+
+        assertModelAllFields(fields);
+
+        assertTrue(getAllDeclaredFields((Element) null).isEmpty());
+        assertTrue(getAllDeclaredFields((TypeMirror) null).isEmpty());
+
+        fields = getAllDeclaredFields(type, f -> "f".equals(f.getSimpleName().toString()));
+        assertEquals(1, fields.size());
+        assertEquals("f", fields.get(0).getSimpleName().toString());
+    }
+
+    @Test
+    public void testGetDeclaredField() {
+        TypeElement type = getType(Model.class);
+        testGetDeclaredField(type, "f", float.class);
+        testGetDeclaredField(type, "d", double.class);
+        testGetDeclaredField(type, "tu", TimeUnit.class);
+        testGetDeclaredField(type, "str", String.class);
+        testGetDeclaredField(type, "bi", BigInteger.class);
+        testGetDeclaredField(type, "bd", BigDecimal.class);
+
+        assertNull(getDeclaredField(type, "b"));
+        assertNull(getDeclaredField(type, "s"));
+        assertNull(getDeclaredField(type, "i"));
+        assertNull(getDeclaredField(type, "l"));
+        assertNull(getDeclaredField(type, "z"));
+
+        assertNull(getDeclaredField((Element) null, "z"));
+        assertNull(getDeclaredField((TypeMirror) null, "z"));
+    }
+
+    @Test
+    public void testFindField() {
+        TypeElement type = getType(Model.class);
+        testFindField(type, "f", float.class);
+        testFindField(type, "d", double.class);
+        testFindField(type, "tu", TimeUnit.class);
+        testFindField(type, "str", String.class);
+        testFindField(type, "bi", BigInteger.class);
+        testFindField(type, "bd", BigDecimal.class);
+        testFindField(type, "b", byte.class);
+        testFindField(type, "s", short.class);
+        testFindField(type, "i", int.class);
+        testFindField(type, "l", long.class);
+        testFindField(type, "z", boolean.class);
+
+        assertNull(findField((Element) null, "f"));
+        assertNull(findField((Element) null, null));
+
+        assertNull(findField((TypeMirror) null, "f"));
+        assertNull(findField((TypeMirror) null, null));
+
+        assertNull(findField(type, null));
+        assertNull(findField(type.asType(), null));
+    }
+
+    @Test
+    public void testIsEnumField() {
+        TypeElement type = getType(Color.class);
+        VariableElement field = findField(type, "RED");
+        assertTrue(isEnumMemberField(field));
+
+        field = findField(type, "YELLOW");
+        assertTrue(isEnumMemberField(field));
+
+        field = findField(type, "BLUE");
+        assertTrue(isEnumMemberField(field));
+
+        type = getType(Model.class);
+        field = findField(type, "f");
+        assertFalse(isEnumMemberField(field));
+
+        assertFalse(isEnumMemberField(null));
+    }
+
+    @Test
+    public void testIsNonStaticField() {
+        TypeElement type = getType(Model.class);
+        assertTrue(isNonStaticField(findField(type, "f")));
+
+        type = getType(Color.class);
+        assertFalse(isNonStaticField(findField(type, "BLUE")));
+    }
+
+    @Test
+    public void testIsField() {
+        TypeElement type = getType(Model.class);
+        assertTrue(isField(findField(type, "f")));
+        assertTrue(isField(findField(type, "f"), PRIVATE));
+
+        type = getType(Color.class);
+        assertTrue(isField(findField(type, "BLUE"), PUBLIC, STATIC, FINAL));
+
+
+        assertFalse(isField(null));
+        assertFalse(isField(null, PUBLIC, STATIC, FINAL));
+    }
+
+    @Test
+    public void testGetNonStaticFields() {
+        TypeElement type = getType(Model.class);
+
+        List<VariableElement> fields = getNonStaticFields(type);
+        assertModelFields(fields);
+
+        fields = getNonStaticFields(type.asType());
+        assertModelFields(fields);
+
+        assertTrue(getAllNonStaticFields((Element) null).isEmpty());
+        assertTrue(getAllNonStaticFields((TypeMirror) null).isEmpty());
+    }
+
+    @Test
+    public void testGetAllNonStaticFields() {
+        TypeElement type = getType(Model.class);
+
+        List<VariableElement> fields = getAllNonStaticFields(type);
+        assertModelAllFields(fields);
+
+        fields = getAllNonStaticFields(type.asType());
+        assertModelAllFields(fields);
+
+        assertTrue(getAllNonStaticFields((Element) null).isEmpty());
+        assertTrue(getAllNonStaticFields((TypeMirror) null).isEmpty());
+    }
+
+    private void assertModelFields(List<VariableElement> fields) {
+        assertEquals(6, fields.size());
+        assertEquals("d", fields.get(1).getSimpleName().toString());
+        assertEquals("tu", fields.get(2).getSimpleName().toString());
+        assertEquals("str", fields.get(3).getSimpleName().toString());
+        assertEquals("bi", fields.get(4).getSimpleName().toString());
+        assertEquals("bd", fields.get(5).getSimpleName().toString());
+    }
+
+    private void assertModelAllFields(List<VariableElement> fields) {
+        assertEquals(11, fields.size());
+        assertEquals("f", fields.get(0).getSimpleName().toString());
+        assertEquals("d", fields.get(1).getSimpleName().toString());
+        assertEquals("tu", fields.get(2).getSimpleName().toString());
+        assertEquals("str", fields.get(3).getSimpleName().toString());
+        assertEquals("bi", fields.get(4).getSimpleName().toString());
+        assertEquals("bd", fields.get(5).getSimpleName().toString());
+        assertEquals("b", fields.get(6).getSimpleName().toString());
+        assertEquals("s", fields.get(7).getSimpleName().toString());
+        assertEquals("i", fields.get(8).getSimpleName().toString());
+        assertEquals("l", fields.get(9).getSimpleName().toString());
+        assertEquals("z", fields.get(10).getSimpleName().toString());
+    }
+
+    private void testGetDeclaredField(TypeElement type, String fieldName, Type fieldType) {
+        VariableElement field = getDeclaredField(type, fieldName);
+        assertField(field, fieldName, fieldType);
+    }
+
+    private void testFindField(TypeElement type, String fieldName, Type fieldType) {
+        VariableElement field = findField(type, fieldName);
+        assertField(field, fieldName, fieldType);
+    }
+
+    private void assertField(VariableElement field, String fieldName, Type fieldType) {
+        assertEquals(fieldName, field.getSimpleName().toString());
+        assertEquals(fieldType.getTypeName(), field.asType().toString());
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
similarity index 54%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
index b3b27e6..a48b759 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/LoggerUtilsTest.java
@@ -14,27 +14,37 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.annotation.processing.util;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.info;
+import static org.apache.dubbo.metadata.annotation.processing.util.LoggerUtils.warn;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link LoggerUtils} Test
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class LoggerUtilsTest {
+
+    @Test
+    public void testLogger() {
+        assertNotNull(LoggerUtils.LOGGER);
+    }
+
+    @Test
+    public void testInfo() {
+        info("Hello,World");
+        info("Hello,%s", "World");
+        info("%s,%s", "Hello", "World");
+    }
 
     @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void testWarn() {
+        warn("Hello,World");
+        warn("Hello,%s", "World");
+        warn("%s,%s", "Hello", "World");
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java
new file mode 100644
index 0000000..3d3be6b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MemberUtilsTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import java.util.List;
+import java.util.Set;
+
+import static javax.lang.model.element.Modifier.PRIVATE;
+import static javax.lang.model.util.ElementFilter.fieldsIn;
+import static javax.lang.model.util.ElementFilter.methodsIn;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getAllDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.getDeclaredMembers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.hasModifiers;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.isPublicNonStatic;
+import static org.apache.dubbo.metadata.annotation.processing.util.MemberUtils.matchParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+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 MemberUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class MemberUtilsTest extends AbstractAnnotationProcessingTest {
+
+    private TypeElement testType;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+    }
+
+    @Override
+    protected void beforeEach() {
+        testType = getType(TestServiceImpl.class);
+    }
+
+    @Test
+    public void testIsPublicNonStatic() {
+        assertFalse(isPublicNonStatic(null));
+        methodsIn(getDeclaredMembers(testType.asType())).forEach(method -> assertTrue(isPublicNonStatic(method)));
+    }
+
+    @Test
+    public void testHasModifiers() {
+        assertFalse(hasModifiers(null));
+        List<? extends Element> members = getAllDeclaredMembers(testType.asType());
+        List<VariableElement> fields = fieldsIn(members);
+        assertTrue(hasModifiers(fields.get(0), PRIVATE));
+    }
+
+    @Test
+    public void testDeclaredMembers() {
+        TypeElement type = getType(Model.class);
+        List<? extends Element> members = getDeclaredMembers(type.asType());
+        List<VariableElement> fields = fieldsIn(members);
+        assertEquals(19, members.size());
+        assertEquals(6, fields.size());
+        assertEquals("f", fields.get(0).getSimpleName().toString());
+        assertEquals("d", fields.get(1).getSimpleName().toString());
+        assertEquals("tu", fields.get(2).getSimpleName().toString());
+        assertEquals("str", fields.get(3).getSimpleName().toString());
+        assertEquals("bi", fields.get(4).getSimpleName().toString());
+        assertEquals("bd", fields.get(5).getSimpleName().toString());
+
+        members = getAllDeclaredMembers(type.asType());
+        fields = fieldsIn(members);
+        assertEquals(11, fields.size());
+        assertEquals("f", fields.get(0).getSimpleName().toString());
+        assertEquals("d", fields.get(1).getSimpleName().toString());
+        assertEquals("tu", fields.get(2).getSimpleName().toString());
+        assertEquals("str", fields.get(3).getSimpleName().toString());
+        assertEquals("bi", fields.get(4).getSimpleName().toString());
+        assertEquals("bd", fields.get(5).getSimpleName().toString());
+        assertEquals("b", fields.get(6).getSimpleName().toString());
+        assertEquals("s", fields.get(7).getSimpleName().toString());
+        assertEquals("i", fields.get(8).getSimpleName().toString());
+        assertEquals("l", fields.get(9).getSimpleName().toString());
+        assertEquals("z", fields.get(10).getSimpleName().toString());
+    }
+
+    @Test
+    public void testMatchParameterTypes() {
+        ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+        assertTrue(matchParameterTypes(method.getParameters(), "java.lang.String"));
+        assertFalse(matchParameterTypes(method.getParameters(), "java.lang.Object"));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.java
new file mode 100644
index 0000000..b2f9162
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/MethodUtilsTest.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.annotation.processing.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+import java.util.List;
+import java.util.Set;
+
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.findMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getAllDeclaredMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getDeclaredMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodName;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getMethodParameterTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getOverrideMethod;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getPublicNonStaticMethods;
+import static org.apache.dubbo.metadata.annotation.processing.util.MethodUtils.getReturnType;
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link MethodUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class MethodUtilsTest extends AbstractAnnotationProcessingTest {
+
+    private TypeElement testType;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+    }
+
+    @Override
+    protected void beforeEach() {
+        testType = getType(TestServiceImpl.class);
+    }
+
+    @Test
+    public void testDeclaredMethods() {
+        TypeElement type = getType(Model.class);
+        List<ExecutableElement> methods = getDeclaredMethods(type);
+        assertEquals(12, methods.size());
+
+        methods = getAllDeclaredMethods(type);
+        assertEquals(34, methods.size());
+
+        assertTrue(getAllDeclaredMethods((TypeElement) null).isEmpty());
+        assertTrue(getAllDeclaredMethods((TypeMirror) null).isEmpty());
+    }
+
+    private List<? extends ExecutableElement> doGetAllDeclaredMethods() {
+        return getAllDeclaredMethods(testType, Object.class);
+    }
+
+    @Test
+    public void testGetAllDeclaredMethods() {
+        List<? extends ExecutableElement> methods = doGetAllDeclaredMethods();
+        assertEquals(14, methods.size());
+    }
+
+    @Test
+    public void testGetPublicNonStaticMethods() {
+        List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+        assertEquals(14, methods.size());
+
+        methods = getPublicNonStaticMethods(testType.asType(), Object.class);
+        assertEquals(14, methods.size());
+    }
+
+    @Test
+    public void testIsMethod() {
+        List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+        assertEquals(14, methods.stream().map(MethodUtils::isMethod).count());
+    }
+
+    @Test
+    public void testIsPublicNonStaticMethod() {
+        List<? extends ExecutableElement> methods = getPublicNonStaticMethods(testType, Object.class);
+        assertEquals(14, methods.stream().map(MethodUtils::isPublicNonStaticMethod).count());
+    }
+
+    @Test
+    public void testFindMethod() {
+        TypeElement type = getType(Model.class);
+        // Test methods from java.lang.Object
+        // Object#toString()
+        String methodName = "toString";
+        ExecutableElement method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#hashCode()
+        methodName = "hashCode";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#getClass()
+        methodName = "getClass";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#finalize()
+        methodName = "finalize";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#clone()
+        methodName = "clone";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#notify()
+        methodName = "notify";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#notifyAll()
+        methodName = "notifyAll";
+        method = findMethod(type.asType(), methodName);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#wait(long)
+        methodName = "wait";
+        method = findMethod(type.asType(), methodName, long.class);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#wait(long,int)
+        methodName = "wait";
+        method = findMethod(type.asType(), methodName, long.class, int.class);
+        assertEquals(method.getSimpleName().toString(), methodName);
+
+        // Object#equals(Object)
+        methodName = "equals";
+        method = findMethod(type.asType(), methodName, Object.class);
+        assertEquals(method.getSimpleName().toString(), methodName);
+    }
+
+    @Test
+    public void testGetOverrideMethod() {
+        List<? extends ExecutableElement> methods = doGetAllDeclaredMethods();
+
+        ExecutableElement overrideMethod = getOverrideMethod(processingEnv, testType, methods.get(0));
+        assertNull(overrideMethod);
+
+        ExecutableElement declaringMethod = findMethod(getType(TestService.class), "echo", "java.lang.String");
+
+        overrideMethod = getOverrideMethod(processingEnv, testType, declaringMethod);
+        assertEquals(methods.get(0), overrideMethod);
+    }
+
+    @Test
+    public void testGetMethodName() {
+        ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+        assertEquals("echo", getMethodName(method));
+        assertNull(getMethodName(null));
+    }
+
+    @Test
+    public void testReturnType() {
+        ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+        assertEquals("java.lang.String", getReturnType(method));
+        assertNull(getReturnType(null));
+    }
+
+    @Test
+    public void testMatchParameterTypes() {
+        ExecutableElement method = findMethod(testType, "echo", "java.lang.String");
+        assertArrayEquals(new String[]{"java.lang.String"}, getMethodParameterTypes(method));
+        assertTrue(getMethodParameterTypes(null).length == 0);
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java
new file mode 100644
index 0000000..a575d4e
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/ServiceAnnotationUtilsTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.tools.DefaultTestService;
+import org.apache.dubbo.metadata.tools.GenericTestService;
+import org.apache.dubbo.metadata.tools.TestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.TypeElement;
+import java.util.HashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.GROUP_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.INTERFACE_CLASS_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.INTERFACE_NAME_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.LEGACY_SERVICE_ANNOTATION_TYPE;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SERVICE_ANNOTATION_TYPE;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.SUPPORTED_ANNOTATION_TYPES;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.VERSION_ATTRIBUTE_NAME;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getAnnotation;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getGroup;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.getVersion;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.isServiceAnnotationPresent;
+import static org.apache.dubbo.metadata.annotation.processing.util.ServiceAnnotationUtils.resolveServiceInterfaceName;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link ServiceAnnotationUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class ServiceAnnotationUtilsTest extends AbstractAnnotationProcessingTest {
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+
+    }
+
+    @Override
+    protected void beforeEach() {
+
+    }
+
+    @Test
+    public void testConstants() {
+        assertEquals("org.apache.dubbo.config.annotation.Service", SERVICE_ANNOTATION_TYPE);
+        assertEquals("com.alibaba.dubbo.config.annotation.Service", LEGACY_SERVICE_ANNOTATION_TYPE);
+        assertEquals("interfaceClass", INTERFACE_CLASS_ATTRIBUTE_NAME);
+        assertEquals("interfaceName", INTERFACE_NAME_ATTRIBUTE_NAME);
+        assertEquals("group", GROUP_ATTRIBUTE_NAME);
+        assertEquals("version", VERSION_ATTRIBUTE_NAME);
+        assertEquals(new HashSet(asList("org.apache.dubbo.config.annotation.Service", "com.alibaba.dubbo.config.annotation.Service")), SUPPORTED_ANNOTATION_TYPES);
+    }
+
+    @Test
+    public void testIsServiceAnnotationPresent() {
+
+        assertTrue(isServiceAnnotationPresent(getType(TestServiceImpl.class)));
+        assertTrue(isServiceAnnotationPresent(getType(GenericTestService.class)));
+        assertTrue(isServiceAnnotationPresent(getType(DefaultTestService.class)));
+
+        assertFalse(isServiceAnnotationPresent(getType(TestService.class)));
+    }
+
+    @Test
+    public void testGetAnnotation() {
+        TypeElement type = getType(TestServiceImpl.class);
+        assertEquals("org.apache.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+        type = getType(GenericTestService.class);
+        assertEquals("com.alibaba.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+        type = getType(DefaultTestService.class);
+        assertEquals("org.apache.dubbo.config.annotation.Service", getAnnotation(type).getAnnotationType().toString());
+
+        assertThrows(IllegalArgumentException.class, () -> getAnnotation(getType(TestService.class)));
+    }
+
+    @Test
+    public void testResolveServiceInterfaceName() {
+        TypeElement type = getType(TestServiceImpl.class);
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+
+        type = getType(GenericTestService.class);
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+
+        type = getType(DefaultTestService.class);
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", resolveServiceInterfaceName(type, getAnnotation(type)));
+    }
+
+    @Test
+    public void testGetVersion() {
+        TypeElement type = getType(TestServiceImpl.class);
+        assertEquals("3.0.0", getVersion(getAnnotation(type)));
+
+        type = getType(GenericTestService.class);
+        assertEquals("2.0.0", getVersion(getAnnotation(type)));
+
+        type = getType(DefaultTestService.class);
+        assertEquals("1.0.0", getVersion(getAnnotation(type)));
+    }
+
+    @Test
+    public void testGetGroup() {
+        TypeElement type = getType(TestServiceImpl.class);
+        assertEquals("test",getGroup(getAnnotation(type)));
+
+        type = getType(GenericTestService.class);
+        assertEquals("generic", getGroup(getAnnotation(type)));
+
+        type = getType(DefaultTestService.class);
+        assertEquals("default", getGroup(getAnnotation(type)));
+    }
+}
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java
new file mode 100644
index 0000000..b3d5050
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/annotation/processing/util/TypeUtilsTest.java
@@ -0,0 +1,467 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.metadata.annotation.processing.AbstractAnnotationProcessingTest;
+import org.apache.dubbo.metadata.annotation.processing.model.ArrayTypeModel;
+import org.apache.dubbo.metadata.annotation.processing.model.Color;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+import org.apache.dubbo.metadata.annotation.processing.model.PrimitiveTypeModel;
+import org.apache.dubbo.metadata.tools.DefaultTestService;
+import org.apache.dubbo.metadata.tools.GenericTestService;
+import org.apache.dubbo.metadata.tools.TestServiceImpl;
+
+import org.junit.jupiter.api.Test;
+
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import java.io.File;
+import java.lang.reflect.Type;
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.findField;
+import static org.apache.dubbo.metadata.annotation.processing.util.FieldUtils.getDeclaredFields;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getAllInterfaces;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getAllSuperTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getHierarchicalTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getInterfaces;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResource;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getResourceName;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.getSuperType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isAnnotationType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isArrayType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isClassType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isDeclaredType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isEnumType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isInterfaceType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isPrimitiveType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSameType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isSimpleType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.isTypeElement;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.listDeclaredTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.listTypeElements;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredType;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofDeclaredTypes;
+import static org.apache.dubbo.metadata.annotation.processing.util.TypeUtils.ofTypeElement;
+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.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * The {@link TypeUtils} Test
+ *
+ * @since 2.7.5
+ */
+public class TypeUtilsTest extends AbstractAnnotationProcessingTest {
+
+    private TypeElement testType;
+
+    @Override
+    protected void addCompiledClasses(Set<Class<?>> classesToBeCompiled) {
+        classesToBeCompiled.add(ArrayTypeModel.class);
+        classesToBeCompiled.add(Color.class);
+    }
+
+    @Override
+    protected void beforeEach() {
+        testType = getType(TestServiceImpl.class);
+    }
+
+    @Test
+    public void testIsSimpleType() {
+
+        assertTrue(isSimpleType(getType(Void.class)));
+        assertTrue(isSimpleType(getType(Boolean.class)));
+        assertTrue(isSimpleType(getType(Character.class)));
+        assertTrue(isSimpleType(getType(Byte.class)));
+        assertTrue(isSimpleType(getType(Short.class)));
+        assertTrue(isSimpleType(getType(Integer.class)));
+        assertTrue(isSimpleType(getType(Long.class)));
+        assertTrue(isSimpleType(getType(Float.class)));
+        assertTrue(isSimpleType(getType(Double.class)));
+        assertTrue(isSimpleType(getType(String.class)));
+        assertTrue(isSimpleType(getType(BigDecimal.class)));
+        assertTrue(isSimpleType(getType(BigInteger.class)));
+        assertTrue(isSimpleType(getType(Date.class)));
+
+        assertFalse(isSimpleType(getType(getClass())));
+        assertFalse(isSimpleType((TypeElement) null));
+        assertFalse(isSimpleType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsSameType() {
+        assertTrue(isSameType(getType(Void.class).asType(), "java.lang.Void"));
+        assertFalse(isSameType(getType(String.class).asType(), "java.lang.Void"));
+
+        assertFalse(isSameType(getType(Void.class).asType(), (Type) null));
+        assertFalse(isSameType(null, (Type) null));
+
+        assertFalse(isSameType(getType(Void.class).asType(), (String) null));
+        assertFalse(isSameType(null, (String) null));
+    }
+
+    @Test
+    public void testIsArrayType() {
+        TypeElement type = getType(ArrayTypeModel.class);
+        assertTrue(isArrayType(findField(type.asType(), "integers").asType()));
+        assertTrue(isArrayType(findField(type.asType(), "strings").asType()));
+        assertTrue(isArrayType(findField(type.asType(), "primitiveTypeModels").asType()));
+        assertTrue(isArrayType(findField(type.asType(), "models").asType()));
+        assertTrue(isArrayType(findField(type.asType(), "colors").asType()));
+
+        assertFalse(isArrayType((Element) null));
+        assertFalse(isArrayType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsEnumType() {
+        TypeElement type = getType(Color.class);
+        assertTrue(isEnumType(type.asType()));
+
+        type = getType(ArrayTypeModel.class);
+        assertFalse(isEnumType(type.asType()));
+
+        assertFalse(isEnumType((Element) null));
+        assertFalse(isEnumType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsClassType() {
+        TypeElement type = getType(ArrayTypeModel.class);
+        assertTrue(isClassType(type.asType()));
+
+        type = getType(Model.class);
+        assertTrue(isClassType(type.asType()));
+
+        assertFalse(isClassType((Element) null));
+        assertFalse(isClassType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsPrimitiveType() {
+        TypeElement type = getType(PrimitiveTypeModel.class);
+        getDeclaredFields(type.asType())
+                .stream()
+                .map(VariableElement::asType)
+                .forEach(t -> assertTrue(isPrimitiveType(t)));
+
+        assertFalse(isPrimitiveType(getType(ArrayTypeModel.class)));
+
+        assertFalse(isPrimitiveType((Element) null));
+        assertFalse(isPrimitiveType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsInterfaceType() {
+        TypeElement type = getType(CharSequence.class);
+        assertTrue(isInterfaceType(type));
+        assertTrue(isInterfaceType(type.asType()));
+
+        type = getType(Model.class);
+        assertFalse(isInterfaceType(type));
+        assertFalse(isInterfaceType(type.asType()));
+
+        assertFalse(isInterfaceType((Element) null));
+        assertFalse(isInterfaceType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsAnnotationType() {
+        TypeElement type = getType(Override.class);
+
+        assertTrue(isAnnotationType(type));
+        assertTrue(isAnnotationType(type.asType()));
+
+        type = getType(Model.class);
+        assertFalse(isAnnotationType(type));
+        assertFalse(isAnnotationType(type.asType()));
+
+        assertFalse(isAnnotationType((Element) null));
+        assertFalse(isAnnotationType((TypeMirror) null));
+    }
+
+    @Test
+    public void testGetHierarchicalTypes() {
+        Set hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, true, true);
+        Iterator iterator = hierarchicalTypes.iterator();
+        assertEquals(8, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+        assertEquals("java.lang.Object", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(8, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+        assertEquals("java.lang.Object", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), Object.class);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(7, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, true, false);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(4, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.GenericTestService", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.DefaultTestService", iterator.next().toString());
+        assertEquals("java.lang.Object", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, false, true);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(5, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), false, false, true);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(4, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), true, false, false);
+        iterator = hierarchicalTypes.iterator();
+        assertEquals(1, hierarchicalTypes.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestServiceImpl", iterator.next().toString());
+
+        hierarchicalTypes = getHierarchicalTypes(testType.asType(), false, false, false);
+        assertEquals(0, hierarchicalTypes.size());
+
+        assertTrue(getHierarchicalTypes((TypeElement) null).isEmpty());
+        assertTrue(getHierarchicalTypes((TypeMirror) null).isEmpty());
+    }
+
+
+    @Test
+    public void testGetInterfaces() {
+        TypeElement type = getType(Model.class);
+        List<TypeMirror> interfaces = getInterfaces(type);
+        assertTrue(interfaces.isEmpty());
+
+        interfaces = getInterfaces(testType.asType());
+
+        assertEquals(3, interfaces.size());
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", interfaces.get(0).toString());
+        assertEquals("java.lang.AutoCloseable", interfaces.get(1).toString());
+        assertEquals("java.io.Serializable", interfaces.get(2).toString());
+
+        assertTrue(getInterfaces((TypeElement) null).isEmpty());
+        assertTrue(getInterfaces((TypeMirror) null).isEmpty());
+    }
+
+    @Test
+    public void testGetAllInterfaces() {
+        Set<? extends TypeMirror> interfaces = getAllInterfaces(testType.asType());
+        assertEquals(4, interfaces.size());
+        Iterator<? extends TypeMirror> iterator = interfaces.iterator();
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", iterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", iterator.next().toString());
+        assertEquals("java.io.Serializable", iterator.next().toString());
+        assertEquals("java.util.EventListener", iterator.next().toString());
+
+        Set<TypeElement> allInterfaces = getAllInterfaces(testType);
+        assertEquals(4, interfaces.size());
+
+        Iterator<TypeElement> allIterator = allInterfaces.iterator();
+        assertEquals("org.apache.dubbo.metadata.tools.TestService", allIterator.next().toString());
+        assertEquals("java.lang.AutoCloseable", allIterator.next().toString());
+        assertEquals("java.io.Serializable", allIterator.next().toString());
+        assertEquals("java.util.EventListener", allIterator.next().toString());
+
+        assertTrue(getAllInterfaces((TypeElement) null).isEmpty());
+        assertTrue(getAllInterfaces((TypeMirror) null).isEmpty());
+    }
+
+    @Test
+    public void testGetType() {
+        TypeElement element = TypeUtils.getType(processingEnv, String.class);
+        assertEquals(element, TypeUtils.getType(processingEnv, element.asType()));
+        assertEquals(element, TypeUtils.getType(processingEnv, "java.lang.String"));
+
+        assertNull(TypeUtils.getType(processingEnv, (Type) null));
+        assertNull(TypeUtils.getType(processingEnv, (TypeMirror) null));
+        assertNull(TypeUtils.getType(processingEnv, (CharSequence) null));
+        assertNull(TypeUtils.getType(null, (CharSequence) null));
+    }
+
+    @Test
+    public void testGetSuperType() {
+        TypeElement gtsTypeElement = getSuperType(testType);
+        assertEquals(gtsTypeElement, getType(GenericTestService.class));
+        TypeElement dtsTypeElement = getSuperType(gtsTypeElement);
+        assertEquals(dtsTypeElement, getType(DefaultTestService.class));
+
+        TypeMirror gtsType = getSuperType(testType.asType());
+        assertEquals(gtsType, getType(GenericTestService.class).asType());
+        TypeMirror dtsType = getSuperType(gtsType);
+        assertEquals(dtsType, getType(DefaultTestService.class).asType());
+
+        assertNull(getSuperType((TypeElement) null));
+        assertNull(getSuperType((TypeMirror) null));
+    }
+
+    @Test
+    public void testGetAllSuperTypes() {
+        Set<?> allSuperTypes = getAllSuperTypes(testType);
+        Iterator<?> iterator = allSuperTypes.iterator();
+        assertEquals(3, allSuperTypes.size());
+        assertEquals(iterator.next(), getType(GenericTestService.class));
+        assertEquals(iterator.next(), getType(DefaultTestService.class));
+        assertEquals(iterator.next(), getType(Object.class));
+
+        allSuperTypes = getAllSuperTypes(testType);
+        iterator = allSuperTypes.iterator();
+        assertEquals(3, allSuperTypes.size());
+        assertEquals(iterator.next(), getType(GenericTestService.class));
+        assertEquals(iterator.next(), getType(DefaultTestService.class));
+        assertEquals(iterator.next(), getType(Object.class));
+
+        assertTrue(getAllSuperTypes((TypeElement) null).isEmpty());
+        assertTrue(getAllSuperTypes((TypeMirror) null).isEmpty());
+    }
+
+    @Test
+    public void testIsDeclaredType() {
+        assertTrue(isDeclaredType(testType));
+        assertTrue(isDeclaredType(testType.asType()));
+        assertFalse(isDeclaredType((Element) null));
+        assertFalse(isDeclaredType((TypeMirror) null));
+        assertFalse(isDeclaredType(types.getNullType()));
+        assertFalse(isDeclaredType(types.getPrimitiveType(TypeKind.BYTE)));
+        assertFalse(isDeclaredType(types.getArrayType(types.getPrimitiveType(TypeKind.BYTE))));
+    }
+
+    @Test
+    public void testOfDeclaredType() {
+        assertEquals(testType.asType(), ofDeclaredType(testType));
+        assertEquals(testType.asType(), ofDeclaredType(testType.asType()));
+        assertEquals(ofDeclaredType(testType), ofDeclaredType(testType.asType()));
+
+        assertNull(ofDeclaredType((Element) null));
+        assertNull(ofDeclaredType((TypeMirror) null));
+    }
+
+    @Test
+    public void testIsTypeElement() {
+        assertTrue(isTypeElement(testType));
+        assertTrue(isTypeElement(testType.asType()));
+
+        assertFalse(isTypeElement((Element) null));
+        assertFalse(isTypeElement((TypeMirror) null));
+    }
+
+    @Test
+    public void testOfTypeElement() {
+        assertEquals(testType, ofTypeElement(testType));
+        assertEquals(testType, ofTypeElement(testType.asType()));
+
+        assertNull(ofTypeElement((Element) null));
+        assertNull(ofTypeElement((TypeMirror) null));
+    }
+
+    @Test
+    public void testOfDeclaredTypes() {
+        Set<DeclaredType> declaredTypes = ofDeclaredTypes(asList(getType(String.class), getType(TestServiceImpl.class), getType(Color.class)));
+        assertTrue(declaredTypes.contains(getType(String.class).asType()));
+        assertTrue(declaredTypes.contains(getType(TestServiceImpl.class).asType()));
+        assertTrue(declaredTypes.contains(getType(Color.class).asType()));
+
+        assertTrue(ofDeclaredTypes(null).isEmpty());
+    }
+
+    @Test
+    public void testListDeclaredTypes() {
+        List<DeclaredType> types = listDeclaredTypes(asList(testType, testType, testType));
+        assertEquals(1, types.size());
+        assertEquals(ofDeclaredType(testType), types.get(0));
+
+        types = listDeclaredTypes(asList(new Element[]{null}));
+        assertTrue(types.isEmpty());
+    }
+
+    @Test
+    public void testListTypeElements() {
+        List<TypeElement> typeElements = listTypeElements(asList(testType.asType(), ofDeclaredType(testType)));
+        assertEquals(1, typeElements.size());
+        assertEquals(testType, typeElements.get(0));
+
+        typeElements = listTypeElements(asList(types.getPrimitiveType(TypeKind.BYTE), types.getNullType(), types.getNoType(TypeKind.NONE)));
+        assertTrue(typeElements.isEmpty());
+
+        typeElements = listTypeElements(asList(new TypeMirror[]{null}));
+        assertTrue(typeElements.isEmpty());
+
+        typeElements = listTypeElements(null);
+        assertTrue(typeElements.isEmpty());
+    }
+
+    @Test
+    public void testGetResource() throws URISyntaxException {
+        URL resource = getResource(processingEnv, testType);
+        assertNotNull(resource);
+        assertTrue(new File(resource.toURI()).exists());
+        assertEquals(resource, getResource(processingEnv, testType.asType()));
+        assertEquals(resource, getResource(processingEnv, "org.apache.dubbo.metadata.tools.TestServiceImpl"));
+
+        assertThrows(RuntimeException.class, () -> getResource(processingEnv, "NotFound"));
+    }
+
+    @Test
+    public void testGetResourceName() {
+        assertEquals("java/lang/String.class", getResourceName("java.lang.String"));
+        assertNull(getResourceName(null));
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
index b3b27e6..52ccaf6 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Ancestor.java
@@ -14,27 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
-
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.Serializable;
 
 /**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
+ * Ancestor
  */
-public class DubboServiceLoaderTest {
+public class Ancestor implements Serializable {
+
+    private boolean z;
+
+    public boolean isZ() {
+        return z;
+    }
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void setZ(boolean z) {
+        this.z = z;
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java
new file mode 100644
index 0000000..a4ee1af
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Compiler.java
@@ -0,0 +1,116 @@
+/*
+ * 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.tools;
+
+import javax.annotation.processing.Processor;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardJavaFileManager;
+import javax.tools.StandardLocation;
+import javax.tools.ToolProvider;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import static java.util.Arrays.asList;
+
+/**
+ * The Java Compiler
+ */
+public class Compiler {
+
+    private final File sourceDirectory;
+
+    private final JavaCompiler javaCompiler;
+
+    private final StandardJavaFileManager javaFileManager;
+
+    private final Set<Processor> processors = new LinkedHashSet<>();
+
+    public Compiler() throws IOException {
+        this(defaultTargetDirectory());
+    }
+
+    public Compiler(File targetDirectory) throws IOException {
+        this(defaultSourceDirectory(), targetDirectory);
+    }
+
+    public Compiler(File sourceDirectory, File targetDirectory) throws IOException {
+        this.sourceDirectory = sourceDirectory;
+        this.javaCompiler = ToolProvider.getSystemJavaCompiler();
+        this.javaFileManager = javaCompiler.getStandardFileManager(null, null, null);
+        this.javaFileManager.setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(targetDirectory));
+        this.javaFileManager.setLocation(StandardLocation.SOURCE_OUTPUT, Collections.singleton(targetDirectory));
+    }
+
+    private static File defaultSourceDirectory() {
+        return new File(defaultRootDirectory(), "src/test/java");
+    }
+
+    private static File defaultRootDirectory() {
+        return detectClassPath(Compiler.class).getParentFile().getParentFile();
+    }
+
+    private static File defaultTargetDirectory() {
+        File dir = new File(defaultRootDirectory(), "target/generated-classes");
+        dir.mkdirs();
+        return dir;
+    }
+
+    private static File detectClassPath(Class<?> targetClass) {
+        URL classFileURL = targetClass.getProtectionDomain().getCodeSource().getLocation();
+        if ("file".equals(classFileURL.getProtocol())) {
+            return new File(classFileURL.getPath());
+        } else {
+            throw new RuntimeException("No support");
+        }
+    }
+
+    public Compiler processors(Processor... processors) {
+        this.processors.addAll(asList(processors));
+        return this;
+    }
+
+    private Iterable<? extends JavaFileObject> getJavaFileObjects(Class<?>... sourceClasses) {
+        int size = sourceClasses == null ? 0 : sourceClasses.length;
+        File[] javaSourceFiles = new File[size];
+        for (int i = 0; i < size; i++) {
+            File javaSourceFile = javaSourceFile(sourceClasses[i].getName());
+            javaSourceFiles[i] = javaSourceFile;
+        }
+        return javaFileManager.getJavaFileObjects(javaSourceFiles);
+    }
+
+    private File javaSourceFile(String sourceClassName) {
+        String javaSourceFilePath = sourceClassName.replace('.', '/').concat(".java");
+        return new File(sourceDirectory, javaSourceFilePath);
+    }
+
+    public boolean compile(Class<?>... sourceClasses) {
+        JavaCompiler.CompilationTask task = javaCompiler.getTask(null, this.javaFileManager, null,
+                asList("-parameters"),
+//                null,
+                null, getJavaFileObjects(sourceClasses));
+        if (!processors.isEmpty()) {
+            task.setProcessors(processors);
+        }
+        return task.call();
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
similarity index 58%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
index b3b27e6..e633e0f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/CompilerTest.java
@@ -14,27 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
 
 /**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
+ * The Compiler test case
  */
-public class DubboServiceLoaderTest {
+public class CompilerTest {
 
     @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void testCompile() throws IOException {
+        Compiler compiler = new Compiler();
+        compiler.compile(
+                TestServiceImpl.class,
+                DefaultTestService.class,
+                GenericTestService.class);
     }
 }
+
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java
new file mode 100644
index 0000000..5ac8257
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/DefaultTestService.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.metadata.tools;
+
+
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * {@link TestService} Implementation
+ *
+ * @since 2.7.5
+ */
+@Service(
+        interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+        version = "1.0.0",
+        group = "default"
+)
+public class DefaultTestService implements TestService {
+
+    private String name;
+
+    @Override
+    public String echo(String message) {
+        return "[ECHO] " + message;
+    }
+
+    @Override
+    public Model model(Model model) {
+        return model;
+    }
+
+    @Override
+    public String testPrimitive(boolean z, int i) {
+        return null;
+    }
+
+    @Override
+    public Model testEnum(TimeUnit timeUnit) {
+        return null;
+    }
+
+    @Override
+    public String testArray(String[] strArray, int[] intArray, Model[] modelArray) {
+        return null;
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
similarity index 56%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
index b3b27e6..c60953b 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/GenericTestService.java
@@ -14,27 +14,25 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
 
-import java.util.List;
+import com.alibaba.dubbo.config.annotation.Service;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.EventListener;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link TestService} Implementation
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+@Service(
+        version = "2.0.0",
+        group = "generic"
+)
+public class GenericTestService extends DefaultTestService implements TestService, EventListener {
+    @Override
+    public String echo(String message) {
+        return "[ECHO] " + message;
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
index b3b27e6..4273a0f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/Parent.java
@@ -14,27 +14,50 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
+/**
+ * Parent
+ */
+public class Parent extends Ancestor {
 
-import java.util.List;
+    private byte b;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+    private short s;
 
-/**
- * {@link DubboServiceLoader} Test
- *
- * @since 2.7.5
- */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    private int i;
+
+    private long l;
+
+    public byte getB() {
+        return b;
+    }
+
+    public void setB(byte b) {
+        this.b = b;
+    }
+
+    public short getS() {
+        return s;
+    }
+
+    public void setS(short s) {
+        this.s = s;
+    }
+
+    public int getI() {
+        return i;
+    }
+
+    public void setI(int i) {
+        this.i = i;
+    }
+
+    public long getL() {
+        return l;
+    }
+
+    public void setL(long l) {
+        this.l = l;
     }
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
similarity index 55%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
index b3b27e6..8db18d7 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestService.java
@@ -14,27 +14,29 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.util.Map;
 
 /**
- * {@link DubboServiceLoader} Test
+ * An interface for REST service
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
+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-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
index b3b27e6..3e318d2 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/RestServiceTest.java
@@ -14,27 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link RestService} Test
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class RestServiceTest {
 
     @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void test() throws IOException {
+        Compiler compiler = new Compiler();
+        compiler.compile(User.class, RestService.class,
+                StandardRestService.class,
+                SpringRestService.class);
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestService.java
new file mode 100644
index 0000000..c684cb3
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/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.tools;
+
+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.5
+ */
+@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-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
index b3b27e6..d240da1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/SpringRestServiceTest.java
@@ -14,27 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link SpringRestService} Test
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class SpringRestServiceTest {
 
     @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void test() throws IOException {
+        Compiler compiler = new Compiler();
+        compiler.compile(User.class, RestService.class, SpringRestService.class);
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestService.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestService.java
new file mode 100644
index 0000000..064f28c
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/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.tools;
+
+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"})
+@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-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
similarity index 59%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
index b3b27e6..8eab99e 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/StandardRestServiceTest.java
@@ -14,27 +14,22 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
 import org.junit.jupiter.api.Test;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.IOException;
 
 /**
- * {@link DubboServiceLoader} Test
+ * The test case for {@link StandardRestService}
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+public class StandardRestServiceTest {
 
     @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    public void test() throws IOException {
+        Compiler compiler = new Compiler();
+        compiler.compile(User.class, RestService.class, StandardRestService.class);
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java
new file mode 100644
index 0000000..58a6004
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestProcessor.java
@@ -0,0 +1,46 @@
+/*
+ * 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.tools;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.Processor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.TypeElement;
+import java.util.Set;
+
+/**
+ * {@link Processor} for test
+ *
+ * @since 2.7.5
+ */
+@SupportedAnnotationTypes("*")
+@SupportedSourceVersion(SourceVersion.RELEASE_8)
+public class TestProcessor extends AbstractProcessor {
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        return false;
+    }
+
+    public ProcessingEnvironment getProcessingEnvironment() {
+        return super.processingEnv;
+    }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
similarity index 51%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
index b3b27e6..d397b3f 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestService.java
@@ -14,27 +14,41 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
+import org.apache.dubbo.metadata.annotation.processing.model.Model;
 
-import java.util.List;
-
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import java.util.concurrent.TimeUnit;
 
 /**
- * {@link DubboServiceLoader} Test
+ * Test Service
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
-
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
-    }
+@Path("/echo")
+public interface TestService {
+
+    @GET
+    <T> String echo(@PathParam("message") @DefaultValue("mercyblitz") String message);
+
+    @POST
+    Model model(@PathParam("model") Model model);
+
+    // Test primitive
+    @PUT
+    String testPrimitive(boolean z, int i);
+
+    // Test enumeration
+    @PUT
+    Model testEnum(TimeUnit timeUnit);
+
+    // Test Array
+    @GET
+    String testArray(String[] strArray, int[] intArray, Model[] modelArray);
 }
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
similarity index 50%
copy from dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
copy to dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
index b3b27e6..aeb4530 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/DubboServiceLoaderTest.java
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/TestServiceImpl.java
@@ -14,27 +14,38 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.dubbo.common.utils;
+package org.apache.dubbo.metadata.tools;
 
-import org.junit.jupiter.api.Test;
 
-import java.util.List;
+import org.apache.dubbo.config.annotation.Service;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import java.io.Serializable;
 
 /**
- * {@link DubboServiceLoader} Test
+ * {@link TestService} Implementation
  *
  * @since 2.7.5
  */
-public class DubboServiceLoaderTest {
+@com.alibaba.dubbo.config.annotation.Service(
+        interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+        interfaceClass = TestService.class,
+        version = "3.0.0",
+        group = "test"
+)
+@Service(
+        interfaceName = "org.apache.dubbo.metadata.tools.TestService",
+        interfaceClass = TestService.class,
+        version = "3.0.0",
+        group = "test"
+)
+public class TestServiceImpl extends GenericTestService implements TestService, AutoCloseable, Serializable {
 
-    @Test
-    public void testLoad() {
-        List<CharSequence> charSequences = loadServices(CharSequence.class);
-        assertEquals(DefaultCharSequence.class, charSequences.get(0).getClass());
-        assertEquals(String.class, charSequences.get(1).getClass());
-        assertEquals(StringBuilder.class, charSequences.get(2).getClass());
+    @Override
+    public String echo(String message) {
+        return "[ECHO] " + message;
+    }
+
+    @Override
+    public void close() throws Exception {
     }
 }
diff --git a/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/User.java b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/User.java
new file mode 100644
index 0000000..e79f7c4
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-processor/src/test/java/org/apache/dubbo/metadata/tools/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.tools;
+
+import java.io.Serializable;
+
+/**
+ * User Entity
+ *
+ * @since 2.7.5
+ */
+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/pom.xml b/dubbo-metadata/pom.xml
index fefa364..17ceada 100644
--- a/dubbo-metadata/pom.xml
+++ b/dubbo-metadata/pom.xml
@@ -35,6 +35,7 @@
         <module>dubbo-metadata-report-consul</module>
         <module>dubbo-metadata-report-etcd</module>
         <module>dubbo-metadata-report-nacos</module>
+        <module>dubbo-metadata-processor</module>
     </modules>
 
 </project>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
index 4f8363d..7132c32 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java
@@ -21,7 +21,7 @@ import org.apache.dubbo.common.URLBuilder;
 import org.apache.dubbo.common.extension.SPI;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.DubboServiceLoader;
+import org.apache.dubbo.common.utils.PrioritizedServiceLoader;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.MetadataService;
 import org.apache.dubbo.metadata.ServiceNameMapping;
@@ -77,7 +77,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
 import static org.apache.dubbo.common.function.ThrowableAction.execute;
 import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
 import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
-import static org.apache.dubbo.common.utils.DubboServiceLoader.loadServices;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.loadServices;
 import static org.apache.dubbo.common.utils.StringUtils.isBlank;
 import static org.apache.dubbo.metadata.MetadataService.toURLs;
 import static org.apache.dubbo.registry.client.ServiceDiscoveryFactory.getExtension;
@@ -190,10 +190,10 @@ public class ServiceDiscoveryRegistry extends FailbackRegistry {
 
     /**
      * Initialize {@link SubscribedURLsSynthesizer} instances that are
-     * {@link DubboServiceLoader#loadServices(Class, ClassLoader) loaded} by {@link DubboServiceLoader}
+     * {@link PrioritizedServiceLoader#loadServices(Class, ClassLoader) loaded} by {@link PrioritizedServiceLoader}
      *
      * @return non-null {@link List}
-     * @see DubboServiceLoader#loadServices(Class, ClassLoader)
+     * @see PrioritizedServiceLoader#loadServices(Class, ClassLoader)
      */
     private List<SubscribedURLsSynthesizer> initSubscribedURLsSynthesizers() {
         return loadServices(SubscribedURLsSynthesizer.class, this.getClass().getClassLoader());
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
index 68abcdb..e5d613c 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/CustomizableServiceInstanceListener.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.registry.client.event.ServiceInstancePreRegisteredEvent;
 
 import java.util.ServiceLoader;
 
-import static org.apache.dubbo.common.utils.DubboServiceLoader.load;
+import static org.apache.dubbo.common.utils.PrioritizedServiceLoader.load;
 
 
... 1 lines suppressed ...