You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/11/01 07:20:09 UTC

[incubator-dubbo] branch dev-metadata updated (91f1ce8 -> b727c87)

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

liujun pushed a change to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git.


    from 91f1ce8  Merge pull request #2721, Refactor , add switch to simplify registry url and control metadata flow.
     new d423f55  Add xml schema and spring bean support for ConfigCenterConfig
     new d20a6aa  Change ZooKeeper's data structure as a config center
     new a45bfd4  Move UT in config-api to bootstrap temporarily, to solve the unreasonable dependency problem between modules.
     new 80f9091  Changes for demo
     new 65450f5  Merge url part from cvictory and fix configuration override problems
     new b727c87  Merge url part from cvictory and fix configuration override problems

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../apache/dubbo/config/AbstractConfigTest.java    | 515 +++++++++++++++++++++
 .../dubbo/config/AbstractInterfaceConfigTest.java  | 407 ++++++++++++++++
 .../dubbo/config/AbstractMethodConfigTest.java     | 119 +++++
 .../dubbo/config/AbstractReferenceConfigTest.java  | 157 +++++++
 .../dubbo/config/AbstractServiceConfigTest.java    | 181 ++++++++
 .../apache/dubbo/config/ApplicationConfigTest.java |   9 +-
 .../apache/dubbo/config/ArgumentConfigTest.java    |   6 +-
 .../apache/dubbo/config/ConsumerConfigTest.java    |  34 +-
 .../apache/dubbo/config/GenericServiceTest.java    | 314 +++++++++++++
 .../org/apache/dubbo/config/MethodConfigTest.java  |  25 +-
 .../org/apache/dubbo/config/ModuleConfigTest.java  |   9 +-
 .../org/apache/dubbo/config/MonitorConfigTest.java | 107 +++++
 .../apache/dubbo/config/ProtocolConfigTest.java    |  68 ++-
 .../apache/dubbo/config/ProviderConfigTest.java    |  40 +-
 .../apache/dubbo/config/ReferenceConfigTest.java   |  63 ++-
 .../apache/dubbo/config/RegistryConfigTest.java    |  19 +-
 .../org/apache/dubbo/config/ServiceConfigTest.java | 205 ++++++++
 .../java/org/apache/dubbo/config}/api/Box.java     |  44 +-
 .../org/apache/dubbo/config/api/DemoException.java |  75 +--
 .../org/apache/dubbo/config}/api/DemoService.java  |  63 +--
 .../java/org/apache/dubbo/config/api/Greeting.java |   7 +-
 .../java/org/apache/dubbo/config/api/User.java     | 117 ++---
 .../apache/dubbo/config/cache/CacheService.java    |   8 +-
 .../dubbo/config/cache/CacheServiceImpl.java       |  68 ++-
 .../org/apache/dubbo/config/cache/CacheTest.java   | 118 +++++
 .../config/consumer}/DemoActionByAnnotation.java   |  66 +--
 .../dubbo/config/consumer}/DemoActionBySetter.java |  70 +--
 .../dubbo/config/consumer}/DemoInterceptor.java    |  60 +--
 .../DelegateProviderMetaDataInvokerTest.java       |  59 +++
 .../apache/dubbo/config/mock/GreetingLocal1.java   |   4 +-
 .../apache/dubbo/config/mock/GreetingLocal2.java   |   9 +-
 .../apache/dubbo/config/mock/GreetingLocal3.java   |  15 +-
 .../apache/dubbo/config/mock/GreetingMock1.java    |   5 +-
 .../apache/dubbo/config/mock/GreetingMock2.java    |  12 +-
 .../org/apache/dubbo/config/mock/MockCluster.java  |  12 +-
 .../org/apache/dubbo/config/mock/MockCodec.java    |  19 +-
 .../apache/dubbo/config/mock/MockDispatcher.java   |  16 +-
 .../apache/dubbo/config/mock/MockExchanger.java    |  84 ++--
 .../dubbo/config/mock/MockExporterListener.java    |  70 ++-
 .../org/apache/dubbo/config/mock/MockFilter.java   |  17 +-
 .../dubbo/config/mock/MockInvokerListener.java     |  69 ++-
 .../apache/dubbo/config/mock/MockLoadBalance.java  |  68 ++-
 .../org/apache/dubbo/config/mock/MockProtocol.java |  86 ++++
 .../apache/dubbo/config/mock/MockProtocol2.java    |  92 ++--
 .../apache/dubbo/config/mock/MockProxyFactory.java |  22 +-
 .../apache/dubbo/config/mock}/MockRegistry.java    |  69 ++-
 .../dubbo/config/mock/MockRegistryFactory.java     |  15 +-
 .../dubbo/config/mock/MockRegistryFactory2.java    |   9 +-
 .../dubbo/config/mock/MockStatusChecker.java       |  11 +-
 .../dubbo/config/mock/MockTelnetHandler.java       |  12 +-
 .../apache/dubbo/config/mock/MockThreadPool.java   |  13 +-
 .../apache/dubbo/config/mock/MockTransporter.java  |  81 ++--
 .../apache/dubbo/config/mock/TestProxyFactory.java |  20 +-
 .../config/provider}/impl/DemoServiceImpl.java     |  94 ++--
 .../config/url/ExporterSideConfigUrlTest.java      |  98 ++++
 .../dubbo/config/url/InvokerSideConfigUrlTest.java | 227 +++++++++
 .../dubbo/config/url/RpcConfigGetSetProxy.java     | 166 +++++++
 .../org/apache/dubbo/config/url/UrlTestBase.java   | 211 +++++++++
 .../dubbo/config/utils/MockReferenceConfig.java    | 107 +++--
 .../config/utils/ReferenceConfigCacheTest.java     | 114 +++++
 .../config/validation/ValidationParameter.java     | 106 +++++
 .../dubbo/config/validation/ValidationService.java |  70 +++
 .../config/validation/ValidationServiceImpl.java   |  26 +-
 .../dubbo/config/validation/ValidationTest.java    | 301 ++++++++++++
 .../org.apache.dubbo.common.status.StatusChecker   |   2 +-
 .../org.apache.dubbo.common.threadpool.ThreadPool  |   2 +-
 .../org.apache.dubbo.registry.RegistryFactory      |   2 +
 .../services/org.apache.dubbo.remoting.Codec       |   2 +-
 .../services/org.apache.dubbo.remoting.Dispatcher  |   2 +-
 .../services/org.apache.dubbo.remoting.Transporter |   2 +-
 .../org.apache.dubbo.remoting.exchange.Exchanger   |   2 +-
 .../org.apache.dubbo.remoting.telnet.TelnetHandler |   2 +-
 .../services/org.apache.dubbo.rpc.ExporterListener |   2 +-
 .../META-INF/services/org.apache.dubbo.rpc.Filter  |   1 +
 .../services/org.apache.dubbo.rpc.InvokerListener  |   1 +
 .../services/org.apache.dubbo.rpc.Protocol         |   2 +
 .../services/org.apache.dubbo.rpc.ProxyFactory     |   2 +
 .../services/org.apache.dubbo.rpc.cluster.Cluster  |   1 +
 .../org.apache.dubbo.rpc.cluster.LoadBalance       |   1 +
 .../src/main}/test/resources/log4j.xml             |  55 ++-
 .../org/apache/dubbo/rpc/cluster/RouterChain.java  |  15 +-
 .../java/org/apache/dubbo/common/Constants.java    |   4 +
 .../common/config/AbstractPrefixConfiguration.java |   7 +-
 .../org/apache/dubbo/config/AbstractConfig.java    |  10 +-
 .../apache/dubbo/config/ConfigCenterConfig.java    |  33 +-
 .../org/apache/dubbo/config/ReferenceConfig.java   |   2 +-
 .../apache/dubbo/config/RegistryDataConfig.java    |  13 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |   2 +-
 .../dubbo/config/context/ConfigurationWrapper.java |  53 +++
 .../apache/dubbo/config/context/Environment.java   |  51 +-
 .../apache/dubbo/config/utils/ConfigConverter.java |   1 +
 .../dubbo/config/spring/ConfigCenterBean.java      |  20 +-
 .../apache/dubbo/config/spring/ReferenceBean.java  |   2 +-
 .../apache/dubbo/config/spring/ServiceBean.java    |   4 +-
 .../spring/schema/DubboNamespaceHandler.java       |   4 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |   6 +
 .../src/main/resources/META-INF/dubbo.xsd          |   6 +
 .../META-INF/spring/dubbo-demo-consumer.xml        |  15 +-
 .../META-INF/spring/dubbo-demo-provider.xml        |   7 +-
 .../support/apollo/ApolloDynamicConfiguration.java |   7 +
 .../archaius/ArchaiusDynamicConfiguration.java     |   2 +-
 .../sources/ZooKeeperConfigurationSource.java      |  29 +-
 .../definition/ServiceDefinitionBuilder.java       |   2 +-
 .../metadata/definition/TypeDefinitionBuilder.java |   2 +-
 .../definition/builder/ArrayTypeBuilder.java       |   2 +-
 .../definition/builder/CollectionTypeBuilder.java  |   4 +-
 .../definition/builder/DefaultTypeBuilder.java     |   2 +-
 .../definition/builder/EnumTypeBuilder.java        |   2 +-
 .../definition/builder/MapTypeBuilder.java         |   6 +-
 .../metadata/definition/builder/TypeBuilder.java   |   2 +-
 .../definition/model/FullServiceDefinition.java    |   6 +-
 .../definition/model/MethodDefinition.java         |   2 +-
 .../definition/model/ServiceDefinition.java        |   2 +-
 .../metadata/definition/model/TypeDefinition.java  |   2 +-
 .../dubbo/metadata/definition/util/ClassUtils.java |  11 +-
 .../definition/util/JaketConfigurationUtils.java   |   2 +-
 .../dubbo/metadata/definition/MetadataTest.java    |   4 +-
 .../dubbo/metadata/definition/MetadataUtils.java   |   2 +-
 .../definition/common/ClassExtendsMap.java         |   3 +-
 .../metadata/definition/common/OuterClass.java     |   2 +-
 .../common/ResultWithRawCollections.java           |   3 +-
 .../metadata/definition/common/TestService.java    |   2 +-
 .../identifier/ConsumerMetadataIdentifier.java     |   6 +-
 .../metadata/identifier/MetadataIdentifier.java    |   8 +-
 .../integration/MetadataReportService.java         |  14 +-
 .../metadata/support/AbstractMetadataReport.java   |   2 +-
 .../support/AbstractMetadataReportFactory.java     |   4 -
 .../store/test/JTestMetadataReport4Test.java       |   2 +-
 .../test/JTestMetadataReportFactory4Test.java      |   2 +-
 .../support/AbstractMetadataReportFactoryTest.java |   1 +
 .../metadata/store/redis/RedisMetadataReport.java  |   2 +-
 .../store/zookeeper/ZookeeperMetadataReport.java   |   6 +-
 .../zookeeper/ZookeeperMetadataReportFactory.java  |   2 +-
 .../zookeeper/ZookeeperMetadataReportTest.java     |   1 -
 .../java/org/apache/dubbo/registry/ZKTools.java    |  23 +-
 135 files changed, 4905 insertions(+), 988 deletions(-)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractConfigTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractInterfaceConfigTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractMethodConfigTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractReferenceConfigTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractServiceConfigTest.java
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ApplicationConfigTest.java (96%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ArgumentConfigTest.java (95%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ConsumerConfigTest.java (67%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/GenericServiceTest.java
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/MethodConfigTest.java (88%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ModuleConfigTest.java (94%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MonitorConfigTest.java
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ProtocolConfigTest.java (71%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ProviderConfigTest.java (83%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/ReferenceConfigTest.java (53%)
 copy {dubbo-compatible/src => dubbo-bootstrap/src/main}/test/java/org/apache/dubbo/config/RegistryConfigTest.java (92%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ServiceConfigTest.java
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config}/api/Box.java (92%)
 copy dubbo-common/src/main/java/org/apache/dubbo/common/json/ParseException.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoException.java (67%)
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config}/api/DemoService.java (83%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/Filter0.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Greeting.java (85%)
 copy dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/Person.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/User.java (64%)
 copy dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/support/NonSerialized.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheService.java (86%)
 copy dubbo-rpc/dubbo-rpc-rest/src/test/java/org/apache/dubbo/rpc/protol/rest/RestServiceImpl.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheServiceImpl.java (70%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheTest.java
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer}/DemoActionByAnnotation.java (88%)
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer}/DemoActionBySetter.java (88%)
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/action => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer}/DemoInterceptor.java (93%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/invoker/DelegateProviderMetaDataInvokerTest.java
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal1.java (92%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal2.java (79%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal3.java (71%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock1.java (92%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock2.java (77%)
 copy dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableCluster.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCluster.java (79%)
 copy dubbo-compatible/src/main/java/com/alibaba/dubbo/remoting/telnet/TelnetHandler.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCodec.java (64%)
 copy dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/direct/DirectDispatcher.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockDispatcher.java (78%)
 copy dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/header/HeaderExchanger.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExchanger.java (66%)
 copy dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/ExporterListenerAdapter.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExporterListener.java (76%)
 copy dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/GreetingCommand.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockFilter.java (67%)
 copy dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockInvokerListener.java (81%)
 copy dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/listener/InvokerListenerAdapter.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockLoadBalance.java (66%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol.java
 copy dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockProtocol.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol2.java (72%)
 copy dubbo-compatible/src/main/java/com/alibaba/dubbo/rpc/cluster/Cluster.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProxyFactory.java (61%)
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/registry => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock}/MockRegistry.java (53%)
 copy dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/TestRegistryFactory.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory.java (77%)
 copy dubbo-plugin/dubbo-qos/src/test/java/org/apache/dubbo/qos/command/impl/TestRegistryFactory.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory2.java (83%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockStatusChecker.java (75%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTelnetHandler.java (68%)
 copy dubbo-common/src/test/java/org/apache/dubbo/common/utils/JVMUtilTest.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockThreadPool.java (72%)
 copy dubbo-remoting/dubbo-remoting-mina/src/main/java/org/apache/dubbo/remoting/transport/mina/MinaTransporter.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTransporter.java (78%)
 copy dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableCluster.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/TestProxyFactory.java (66%)
 copy {dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/provider}/impl/DemoServiceImpl.java (65%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/RpcConfigGetSetProxy.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/UrlTestBase.java
 copy dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/support/SimpleFuture.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java (53%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationService.java
 copy dubbo-demo/dubbo-demo-consumer/src/main/java/org/apache/dubbo/demo/consumer/DemoServiceMock.java => dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java (69%)
 create mode 100644 dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationTest.java
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.status.StatusChecker (92%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.threadpool.ThreadPool (93%)
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.registry.RegistryFactory
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Codec (94%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Dispatcher (93%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Transporter (92%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.exchange.Exchanger (93%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler (92%)
 copy dubbo-common/src/test/resources/dubbo.properties => dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ExporterListener (91%)
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Filter
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.InvokerListener
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Protocol
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ProxyFactory
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.Cluster
 create mode 100644 dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.LoadBalance
 copy {dubbo-container/dubbo-container-spring/src => dubbo-bootstrap/src/main}/test/resources/log4j.xml (93%)
 create mode 100644 dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java
 copy dubbo-demo/dubbo-demo-consumer/src/main/java/org/apache/dubbo/demo/consumer/DemoServiceMock.java => dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java (66%)


[incubator-dubbo] 06/06: Merge url part from cvictory and fix configuration override problems

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit b727c87e5bed3da67064103bf0841a7f5c17b89e
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 15:19:14 2018 +0800

    Merge url part from cvictory and fix configuration override problems
---
 .../java/org/apache/dubbo/common/Constants.java    |  4 ++++
 .../common/config/AbstractPrefixConfiguration.java |  7 ++++--
 .../org/apache/dubbo/config/AbstractConfig.java    |  6 +++---
 .../apache/dubbo/config/ConfigCenterConfig.java    | 25 +++++++++++-----------
 .../org/apache/dubbo/config/ReferenceConfig.java   |  2 +-
 .../apache/dubbo/config/RegistryDataConfig.java    | 13 +++++------
 .../org/apache/dubbo/config/ServiceConfig.java     |  2 +-
 .../apache/dubbo/config/context/Environment.java   | 25 ++++++++++++++++------
 .../apache/dubbo/config/utils/ConfigConverter.java |  1 +
 .../apache/dubbo/config/spring/ReferenceBean.java  |  2 +-
 .../apache/dubbo/config/spring/ServiceBean.java    |  4 ++--
 .../META-INF/spring/dubbo-demo-consumer.xml        |  9 +++++---
 .../META-INF/spring/dubbo-demo-provider.xml        |  8 +++----
 .../archaius/ArchaiusDynamicConfiguration.java     |  2 +-
 .../sources/ZooKeeperConfigurationSource.java      | 19 +++++++++++-----
 .../definition/ServiceDefinitionBuilder.java       |  2 +-
 .../metadata/definition/TypeDefinitionBuilder.java |  2 +-
 .../definition/builder/ArrayTypeBuilder.java       |  2 +-
 .../definition/builder/CollectionTypeBuilder.java  |  4 ++--
 .../definition/builder/DefaultTypeBuilder.java     |  2 +-
 .../definition/builder/EnumTypeBuilder.java        |  2 +-
 .../definition/builder/MapTypeBuilder.java         |  6 +++---
 .../metadata/definition/builder/TypeBuilder.java   |  2 +-
 .../definition/model/FullServiceDefinition.java    |  6 +++---
 .../definition/model/MethodDefinition.java         |  2 +-
 .../definition/model/ServiceDefinition.java        |  2 +-
 .../metadata/definition/model/TypeDefinition.java  |  2 +-
 .../dubbo/metadata/definition/util/ClassUtils.java | 11 ++++------
 .../definition/util/JaketConfigurationUtils.java   |  2 +-
 .../dubbo/metadata/definition/MetadataTest.java    |  4 ++--
 .../dubbo/metadata/definition/MetadataUtils.java   |  2 +-
 .../definition/common/ClassExtendsMap.java         |  3 ++-
 .../metadata/definition/common/OuterClass.java     |  2 +-
 .../common/ResultWithRawCollections.java           |  3 ++-
 .../metadata/definition/common/TestService.java    |  2 +-
 .../identifier/ConsumerMetadataIdentifier.java     |  6 ++++--
 .../metadata/identifier/MetadataIdentifier.java    |  8 +++----
 .../integration/MetadataReportService.java         | 14 ++----------
 .../metadata/support/AbstractMetadataReport.java   |  2 +-
 .../support/AbstractMetadataReportFactory.java     |  4 ----
 .../store/test/JTestMetadataReport4Test.java       |  2 +-
 .../test/JTestMetadataReportFactory4Test.java      |  2 +-
 .../support/AbstractMetadataReportFactoryTest.java |  1 +
 .../metadata/store/redis/RedisMetadataReport.java  |  2 +-
 .../store/zookeeper/ZookeeperMetadataReport.java   |  6 ++----
 .../zookeeper/ZookeeperMetadataReportFactory.java  |  2 +-
 .../zookeeper/ZookeeperMetadataReportTest.java     |  1 -
 .../java/org/apache/dubbo/registry/ZKTools.java    | 10 +++++----
 48 files changed, 134 insertions(+), 118 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index 91e54b2..df67944 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@ -64,6 +64,9 @@ public class Constants {
     public static final String CONFIG_CLUSTER_KEY = "config.cluster";
     public static final String CONFIG_NAMESPACE_KEY = "config.namespace";
     public static final String CONFIG_CHECK_KEY = "config.check";
+    public static final String CONFIG_DATAID_KEY = "config.dataid";
+    public static final String CONFIG_PRIORITY_KEY = "config.priority";
+    public static final String CONFIG_TIMEOUT_KEY = "config.timeout";
 
     public static final String DEFAULT_CATEGORY = PROVIDERS_CATEGORY;
 
@@ -460,6 +463,7 @@ public class Constants {
     public static final String EXTRA_PROVIDER_URL_PARAM_KEYS_KEY = "extraProviderUrlParamKeys";
     /**
      * After simplify the registry, should add some paramter individually for consumer.
+     *
      * @since 2.7.0
      */
     public static final String EXTRA_CONSUMER_URL_PARAM_KEYS_KEY = "extraConsumerUrlParamKeys";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/AbstractPrefixConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/AbstractPrefixConfiguration.java
index eebff14..8f53aa5 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/AbstractPrefixConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/AbstractPrefixConfiguration.java
@@ -27,13 +27,16 @@ public abstract class AbstractPrefixConfiguration extends AbstractConfiguration
 
     public AbstractPrefixConfiguration(String prefix, String id) {
         super();
-        this.prefix = prefix;
+        if (StringUtils.isNotEmpty(prefix) && !prefix.endsWith(".")) {
+            this.prefix = prefix + ".";
+        } else {
+            this.prefix = prefix;
+        }
         this.id = id;
     }
 
     @Override
     public Object getProperty(String key, Object defaultValue) {
-
         Object value = null;
         if (StringUtils.isNotEmpty(prefix) && StringUtils.isNotEmpty(id)) {
             value = getInternalProperty(prefix + id + "." + key);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 69e266f..68717cb 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -526,9 +526,9 @@ public abstract class AbstractConfig implements Serializable {
         try {
             Configuration configuration = ConfigConverter.toConfiguration(this);
             CompositeConfiguration compositeConfiguration = Environment.getInstance().getStartupCompositeConf(getPrefix(), getId());
-            int index = 1;
-            if (Environment.getInstance().isConfigCenterFirst()) {
-                index = 2;
+            int index = 2;
+            if (!Environment.getInstance().isConfigCenterFirst()) {
+                index = 1;
             }
             compositeConfiguration.addConfiguration(index, configuration);
             // loop methods, get override value and set the new value back to method
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index 0e1497c..e24363a 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -43,9 +43,9 @@ public class ConfigCenterConfig extends AbstractConfig {
     private String appnamespace;
     private String username;
     private String password;
-    private long timeout = 3000;
-    private boolean priority;
-    private boolean check;
+    private Long timeout = 3000L;
+    private Boolean priority = true;
+    private Boolean check = true;
 
     private String dataid = "dubbo.properties";
 
@@ -96,7 +96,7 @@ public class ConfigCenterConfig extends AbstractConfig {
                         k -> map.put(k, properties.getProperty(k))
                 );
                 Environment.getInstance().setConfigCenterFirst(priority);
-                Environment.getInstance().updateExternalConfiguration(map);
+                Environment.getInstance().updateExternalConfigurationMap(map);
             }
         } catch (IOException e) {
             throw e;
@@ -158,20 +158,20 @@ public class ConfigCenterConfig extends AbstractConfig {
     }
 
     @Parameter(key = Constants.CONFIG_CHECK_KEY)
-    public boolean isCheck() {
+    public Boolean isCheck() {
         return check;
     }
 
-    public void setCheck(boolean check) {
+    public void setCheck(Boolean check) {
         this.check = check;
     }
 
-    @Parameter(key = "config.priority")
-    public boolean isPriority() {
+    @Parameter(key = Constants.CONFIG_PRIORITY_KEY)
+    public Boolean isPriority() {
         return priority;
     }
 
-    public void setPriority(boolean priority) {
+    public void setPriority(Boolean priority) {
         this.priority = priority;
     }
 
@@ -191,15 +191,16 @@ public class ConfigCenterConfig extends AbstractConfig {
         this.password = password;
     }
 
-    @Parameter(key = "config.timeout")
-    public long getTimeout() {
+    @Parameter(key = Constants.CONFIG_TIMEOUT_KEY)
+    public Long getTimeout() {
         return timeout;
     }
 
-    public void setTimeout(long timeout) {
+    public void setTimeout(Long timeout) {
         this.timeout = timeout;
     }
 
+    @Parameter(key = Constants.CONFIG_DATAID_KEY)
     public String getDataid() {
         return dataid;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 8b6e879..696840c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -408,7 +408,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
          * ServiceData Store
          */
         MetadataReportService metadataReportService = null;
-        if ((metadataReportService = getMetadataReportService()) != null){
+        if ((metadataReportService = getMetadataReportService()) != null) {
             URL consumerURL = new URL(Constants.CONSUMER_PROTOCOL, map.remove(Constants.REGISTER_IP_KEY), 0, map.get(Constants.INTERFACE_KEY), map);
             metadataReportService.publishConsumer(consumerURL);
         }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryDataConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryDataConfig.java
index 6f5b790..3ccaab5 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryDataConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryDataConfig.java
@@ -18,11 +18,8 @@ package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 
-import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 /**
@@ -36,17 +33,17 @@ public class RegistryDataConfig extends AbstractConfig {
     private boolean simpleConsumerUrl;
     private String extraConsumerUrlParamKeys;
 
-    public Map<String, String> transferMap(){
+    public Map<String, String> transferMap() {
         Map<String, String> map = new HashMap<String, String>(4);
-        if(simpleProviderUrl){
+        if (simpleProviderUrl) {
             map.put(Constants.SIMPLE_PROVIDER_URL_KEY, Boolean.TRUE.toString());
-            if (StringUtils.isNotEmpty(extraProviderUrlParamKeys)){
+            if (StringUtils.isNotEmpty(extraProviderUrlParamKeys)) {
                 map.put(Constants.EXTRA_PROVIDER_URL_PARAM_KEYS_KEY, extraProviderUrlParamKeys.trim());
             }
         }
-        if(simpleConsumerUrl){
+        if (simpleConsumerUrl) {
             map.put(Constants.SIMPLE_CONSUMER_URL_KEY, Boolean.TRUE.toString());
-            if (StringUtils.isNotEmpty(extraConsumerUrlParamKeys)){
+            if (StringUtils.isNotEmpty(extraConsumerUrlParamKeys)) {
                 map.put(Constants.EXTRA_CONSUMER_URL_PARAM_KEYS_KEY, extraConsumerUrlParamKeys.trim());
             }
         }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index ecc4f51..4c20230 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -534,7 +534,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
                  * ServiceData Store
                  */
                 MetadataReportService metadataReportService = null;
-                if ((metadataReportService = getMetadataReportService()) != null){
+                if ((metadataReportService = getMetadataReportService()) != null) {
                     metadataReportService.publishProvider(url);
                 }
             }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
index db9daaa..1785c6a 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
@@ -28,6 +28,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.governance.DynamicConfiguration;
 import org.apache.dubbo.governance.DynamicConfigurationFactory;
 
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -40,14 +41,15 @@ public class Environment {
     private volatile Map<String, PropertiesConfiguration> propertiesConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, SystemConfiguration> systemConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, EnvironmentConfiguration> environmentConfsHolder = new ConcurrentHashMap<>();
+    private volatile Map<String, InmemoryConfiguration> externalConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, CompositeConfiguration> startupCompositeConfsHolder = new ConcurrentHashMap<>();
     private volatile Map<String, CompositeConfiguration> runtimeCompositeConfsHolder = new ConcurrentHashMap<>();
 
-    private volatile InmemoryConfiguration externalConfiguration = new InmemoryConfiguration();
-
     private volatile DynamicConfiguration dynamicConfiguration;
 
-    private volatile boolean isConfigCenterFirst;
+    private volatile boolean isConfigCenterFirst = true;
+
+    private Map<String, String> externalConfigurationMap = new HashMap<>();
 
     public static Environment getInstance() {
         return INSTANCE;
@@ -61,19 +63,27 @@ public class Environment {
         return systemConfsHolder.computeIfAbsent(toKey(prefix, id), k -> new SystemConfiguration(prefix, id));
     }
 
+    public InmemoryConfiguration getExternalConfiguration(String prefix, String id) {
+        return externalConfsHolder.computeIfAbsent(toKey(prefix, id), k -> {
+            InmemoryConfiguration configuration = new InmemoryConfiguration(prefix, id);
+            configuration.addProperties(externalConfigurationMap);
+            return configuration;
+        });
+    }
+
     public EnvironmentConfiguration getEnvironmentConf(String prefix, String id) {
         return environmentConfsHolder.computeIfAbsent(toKey(prefix, id), k -> new EnvironmentConfiguration(prefix, id));
     }
 
-    public void updateExternalConfiguration(Map<String, String> externalMap) {
-        this.externalConfiguration.addProperties(externalMap);
+    public void updateExternalConfigurationMap(Map<String, String> externalMap) {
+        this.externalConfigurationMap.putAll(externalMap);
     }
 
     public CompositeConfiguration getStartupCompositeConf(String prefix, String id) {
         return startupCompositeConfsHolder.computeIfAbsent(toKey(prefix, id), k -> {
             CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
             compositeConfiguration.addConfiguration(this.getSystemConf(prefix, id));
-            compositeConfiguration.addConfiguration(this.externalConfiguration);
+            compositeConfiguration.addConfiguration(this.getExternalConfiguration(prefix, id));
             compositeConfiguration.addConfiguration(this.getPropertiesConf(prefix, id));
             return compositeConfiguration;
         });
@@ -82,7 +92,8 @@ public class Environment {
     /**
      * FIXME This method will recreate Configuration for each RPC, how much latency affect will this action has on performance?
      *
-     * @param url
+     * @param url, the url metadata.
+     * @param method, the method name the RPC is trying to invoke.
      * @return
      */
     public CompositeConfiguration getRuntimeCompositeConf(URL url, String method) {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigConverter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigConverter.java
index bca4233..df5b8cb 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigConverter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigConverter.java
@@ -31,6 +31,7 @@ public class ConfigConverter {
      * @return
      */
     public static Configuration toConfiguration(AbstractConfig config) {
+        // FIXME does not need to pass prefix and id to Configuration? because keys generated in getMetadata() did not count prefix in.
         InmemoryConfiguration configuration = new InmemoryConfiguration(config.getPrefix(), config.getId());
         configuration.addProperties(config.getMetaData());
         return configuration;
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index 2b0436e..07b7b2f 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -153,7 +153,7 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
             if (metadataReportConfigMap != null && metadataReportConfigMap.size() == 1) {
                 // first elements
                 super.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());
-            } else if(metadataReportConfigMap != null && metadataReportConfigMap.size() > 1){
+            } else if (metadataReportConfigMap != null && metadataReportConfigMap.size() > 1) {
                 throw new IllegalStateException("Multiple MetadataReport configs: " + metadataReportConfigMap);
             }
         }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index e6974ae..b644d62 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -17,13 +17,13 @@
 package org.apache.dubbo.config.spring;
 
 import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ModuleConfig;
 import org.apache.dubbo.config.MonitorConfig;
 import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.annotation.Service;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.springframework.aop.support.AopUtils;
@@ -216,7 +216,7 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
             if (metadataReportConfigMap != null && metadataReportConfigMap.size() == 1) {
                 // 第一个元素
                 super.setMetadataReportConfig(metadataReportConfigMap.values().iterator().next());
-            } else if(metadataReportConfigMap != null && metadataReportConfigMap.size() > 1){
+            } else if (metadataReportConfigMap != null && metadataReportConfigMap.size() > 1) {
                 throw new IllegalStateException("Multiple MetadataReport configs: " + metadataReportConfigMap);
             }
         }
diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
index cfc8f0f..df40d32 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
@@ -21,11 +21,14 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
 
+    <dubbo:application name="demo-consumer"/>
+
     <!-- use multicast registry center to discover service -->
-    <dubbo:registry address="zookeeper://127.0.0.1:2181" default="true"/>
-    <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
+    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181" default="true"/>
+    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181"/>
 
-    <!--<dubbo:servicestore address="zookeeper://127.0.0.1:2181"/>-->
+    <dubbo:configcenter type="zookeeper" address="127.0.0.1:2181" namespace="dubboregistrygroup1"
+                        dataid="dubbo.properties"/>
 
     <!-- generate proxy for the remote service, then demoService can be used in the same way as the
     local regular interface -->
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
index 0c4c6dc..3d2e2ed 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -25,10 +25,10 @@
     <dubbo:application name="demo-provider"/>
     <!--<dubbo:provider tag="tag3"/>-->
 
-    <!-- use multicast registry center to export service -->
-    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181" simple="false">
-    </dubbo:registry>
-    <!--<dubbo:configcenter type="zookeeper" address="127.0.0.1:2181" namespace="dubboregistrygroup1" dataid="dubbo.properties"/>-->
+    <!--<dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181" simple="false">
+    </dubbo:registry>-->
+    <dubbo:configcenter type="zookeeper" address="127.0.0.1:2181" namespace="dubboregistrygroup1"
+                        dataid="dubbo.properties"/>
 
     <!-- use dubbo protocol to export service on port 20880 -->
     <dubbo:protocol name="dubbo" port="-1"/>
diff --git a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/ArchaiusDynamicConfiguration.java b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/ArchaiusDynamicConfiguration.java
index 430a6ec..922387d 100644
--- a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/ArchaiusDynamicConfiguration.java
+++ b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/ArchaiusDynamicConfiguration.java
@@ -51,7 +51,7 @@ public class ArchaiusDynamicConfiguration extends AbstractDynamicConfiguration<R
         System.setProperty(ZooKeeperConfigurationSource.ARCHAIUS_CONFIG_CHECK_KEY, url.getParameter(Constants.CONFIG_CHECK_KEY, "false"));
 
         try {
-            ZooKeeperConfigurationSource zkConfigSource = new ZooKeeperConfigurationSource();
+            ZooKeeperConfigurationSource zkConfigSource = new ZooKeeperConfigurationSource(url);
             zkConfigSource.start();
             /*if (!zkConfigSource.isConnected()) {
                 // we can check the status of config center here, and decide to fail or continue if we cannot reach the config server.
diff --git a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
index 7cdf108..ec48c2d 100644
--- a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
+++ b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
@@ -27,6 +27,8 @@ import org.apache.curator.framework.recipes.cache.TreeCache;
 import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
 import org.apache.curator.framework.recipes.cache.TreeCacheListener;
 import org.apache.curator.retry.ExponentialBackoffRetry;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -64,8 +66,11 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
 
     private List<WatchedUpdateListener> listeners = new CopyOnWriteArrayList<WatchedUpdateListener>();
 
-    public ZooKeeperConfigurationSource() {
+    private URL url;
+
+    public ZooKeeperConfigurationSource(URL url) {
         this(System.getProperty(ARCHAIUS_SOURCE_ADDRESS_KEY), 60 * 1000, 10000, System.getProperty(ARCHAIUS_CONFIG_ROOT_PATH_KEY, DEFAULT_CONFIG_ROOT_PATH));
+        this.url = url;
     }
 
     public ZooKeeperConfigurationSource(int sessionTimeout, int connectTimeout, String configRootPath) {
@@ -143,7 +148,7 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
                     return;
                 }
 
-                // TODO?
+                // TODO We limit the notification of config changes to a specific path level, for example /dubbo/config/service/configurators, other config changes not in this level will not get notified, say /dubbo/config/dubbo.properties
                 if (data.getPath().split("/").length == 5) {
                     byte[] value = data.getData();
                     String stringValue = new String(value, charset);
@@ -205,10 +210,14 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
 
         Map<String, ChildData> dataMap = treeCache.getCurrentChildren(configRootPath);
         if (dataMap != null && dataMap.size() > 0) {
-            dataMap.forEach((childPath, v) -> {
+            dataMap.forEach((childPath, childData) -> {
                 String fullChildPath = configRootPath + "/" + childPath;
-                treeCache.getCurrentChildren(fullChildPath).forEach((subChildPath, childData) -> {
-                    all.put(pathToKey(fullChildPath + "/" + subChildPath), new String(childData.getData(), charset));
+                // special treatment for /dubbo/config/dubbo.properties, it's the only config item need to store in cache in this level.
+                if (childPath.equals(url.getParameter(Constants.CONFIG_DATAID_KEY))) {
+                    all.put(pathToKey(fullChildPath), new String(childData.getData(), charset));
+                }
+                treeCache.getCurrentChildren(fullChildPath).forEach((subChildPath, subChildData) -> {
+                    all.put(pathToKey(fullChildPath + "/" + subChildPath), new String(subChildData.getData(), charset));
                 });
             });
         }
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
index 8d2dff1..e24fe24 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/ServiceDefinitionBuilder.java
@@ -29,7 +29,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public final class ServiceDefinitionBuilder {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
index 6158273..797d9f8 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/TypeDefinitionBuilder.java
@@ -31,7 +31,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class TypeDefinitionBuilder {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
index 473bc1e..ce53c70 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/ArrayTypeBuilder.java
@@ -23,7 +23,7 @@ import java.lang.reflect.Type;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class ArrayTypeBuilder implements TypeBuilder {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
index df145f1..0f0efde 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/CollectionTypeBuilder.java
@@ -26,7 +26,7 @@ import java.util.Collection;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class CollectionTypeBuilder implements TypeBuilder {
 
@@ -55,7 +55,7 @@ public class CollectionTypeBuilder implements TypeBuilder {
         if (actualTypeArgs == null || actualTypeArgs.length != 1) {
             throw new IllegalArgumentException(MessageFormat.format(
                     "[ServiceDefinitionBuilder] Collection type [{0}] with unexpected amount of arguments [{1}]." + actualTypeArgs,
-                    new Object[] { type, actualTypeArgs }));
+                    new Object[]{type, actualTypeArgs}));
         }
 
         Type actualType = actualTypeArgs[0];
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
index 9ea8ac6..567b4b3 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/DefaultTypeBuilder.java
@@ -57,7 +57,7 @@ public final class DefaultTypeBuilder {
             Class<?> fieldClass = field.getType();
             Type fieldType = field.getGenericType();
 
-            TypeDefinition fieldTd = TypeDefinitionBuilder.build(fieldType,fieldClass, typeCache);
+            TypeDefinition fieldTd = TypeDefinitionBuilder.build(fieldType, fieldClass, typeCache);
             td.getProperties().put(fieldName, fieldTd);
         }
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
index 9aa07d7..cca8c9c 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/EnumTypeBuilder.java
@@ -23,7 +23,7 @@ import java.lang.reflect.Type;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class EnumTypeBuilder implements TypeBuilder {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
index 5aed982..131d971 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/MapTypeBuilder.java
@@ -25,7 +25,7 @@ import java.text.MessageFormat;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class MapTypeBuilder implements TypeBuilder {
 
@@ -53,8 +53,8 @@ public class MapTypeBuilder implements TypeBuilder {
         Type[] actualTypeArgs = parameterizedType.getActualTypeArguments();
         if (actualTypeArgs == null || actualTypeArgs.length != 2) {
             throw new IllegalArgumentException(MessageFormat.format(
-                    "[ServiceDefinitionBuilder] Map type [{0}] with unexpected amount of arguments [{1}]." + actualTypeArgs, new Object[] {
-                            type, actualTypeArgs }));
+                    "[ServiceDefinitionBuilder] Map type [{0}] with unexpected amount of arguments [{1}]." + actualTypeArgs, new Object[]{
+                            type, actualTypeArgs}));
         }
 
         for (Type actualType : actualTypeArgs) {
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
index b0fbd85..ef79a3f 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/builder/TypeBuilder.java
@@ -22,7 +22,7 @@ import java.lang.reflect.Type;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public interface TypeBuilder {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
index 263d34c..bbec7b5 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/FullServiceDefinition.java
@@ -19,11 +19,11 @@ package org.apache.dubbo.metadata.definition.model;
 import java.util.Map;
 
 /**
- *  2018/10/25
+ * 2018/10/25
  */
-public class FullServiceDefinition extends ServiceDefinition{
+public class FullServiceDefinition extends ServiceDefinition {
 
-    private Map<String,String> parameters;
+    private Map<String, String> parameters;
 
     public Map<String, String> getParameters() {
         return parameters;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
index 45da103..fe9e054 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
@@ -21,7 +21,7 @@ import java.util.Arrays;
 import java.util.List;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class MethodDefinition {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
index 3202a30..af60f43 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/ServiceDefinition.java
@@ -20,7 +20,7 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class ServiceDefinition {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
index 4a7e3ac..8d1c582 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/model/TypeDefinition.java
@@ -24,7 +24,7 @@ import java.util.List;
 import java.util.Map;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class TypeDefinition {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
index c313fa7..54fc655 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/ClassUtils.java
@@ -26,15 +26,14 @@ import java.util.ArrayList;
 import java.util.List;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public final class ClassUtils {
 
     /**
      * Get the code source file or class path of the Class passed in.
      *
-     * @param clazz
-     *            Class to find.
+     * @param clazz Class to find.
      * @return Jar file name or class path.
      */
     public static String getCodeSource(Class<?> clazz) {
@@ -60,8 +59,7 @@ public final class ClassUtils {
     /**
      * Get all non-static fields of the Class passed in or its super classes.
      *
-     * @param clazz
-     *            Class to parse.
+     * @param clazz Class to parse.
      * @return field list
      */
     public static List<Field> getNonStaticFields(final Class<?> clazz) {
@@ -90,8 +88,7 @@ public final class ClassUtils {
     /**
      * Get all public, non-static methods of the Class passed in.
      *
-     * @param clazz
-     *            Class to parse.
+     * @param clazz Class to parse.
      * @return methods list
      */
     public static List<Method> getPublicNonStaticMethods(final Class<?> clazz) {
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
index f1066a9..3a7dda1 100755
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/main/java/org/apache/dubbo/metadata/definition/util/JaketConfigurationUtils.java
@@ -20,7 +20,7 @@ import java.io.InputStream;
 import java.util.Properties;
 
 /**
- *  2015/1/27.
+ * 2015/1/27.
  */
 public class JaketConfigurationUtils {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
index 20e33e1..7ae9c97 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataTest.java
@@ -29,8 +29,8 @@ import org.junit.Test;
 
 /**
  * TypeDefinitionBuilder
- *
- *  16/9/22.
+ * <p>
+ * 16/9/22.
  */
 public class MetadataTest {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
index 8d16f77..14ae62f 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/MetadataUtils.java
@@ -27,7 +27,7 @@ import java.util.List;
 
 /**
  * generate metadata
- *
+ * <p>
  * 2017-4-17 14:33:24
  */
 public class MetadataUtils {
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
index cfe413d..eacd124 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ClassExtendsMap.java
@@ -23,7 +23,8 @@ public class ClassExtendsMap extends HashMap<String, Object> {
     private static final long serialVersionUID = 5108356684263812575L;
     private ClassExtendsMap resultMap;
 
-    public ClassExtendsMap() {}
+    public ClassExtendsMap() {
+    }
 
     public ClassExtendsMap getResultMap() {
         return resultMap;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
index 3ee2b4f..8f3f9df 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/OuterClass.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.metadata.definition.common;
 
 /**
- *  16/9/22.
+ * 16/9/22.
  */
 public class OuterClass {
 
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
index 7ed8e55..e17b16b 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/ResultWithRawCollections.java
@@ -28,7 +28,8 @@ public class ResultWithRawCollections {
     private Map map;
     private List list;
 
-    public ResultWithRawCollections() {}
+    public ResultWithRawCollections() {
+    }
 
     public ResultWithRawCollections(Map map, List list) {
         this.map = map;
diff --git a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
index 37a3c94..bbf29a3 100644
--- a/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
+++ b/dubbo-metadata-report/dubbo-metadata-definition/src/test/java/org/apache/dubbo/metadata/definition/common/TestService.java
@@ -17,7 +17,7 @@
 package org.apache.dubbo.metadata.definition.common;
 
 /**
- *  16/9/22.
+ * 16/9/22.
  */
 public interface TestService {
     /**
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/ConsumerMetadataIdentifier.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/ConsumerMetadataIdentifier.java
index f9c40f2..f4a17ce 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/ConsumerMetadataIdentifier.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/ConsumerMetadataIdentifier.java
@@ -17,9 +17,11 @@ public class ConsumerMetadataIdentifier extends MetadataIdentifier {
 
     private String application;
 
-    protected String getPathSegment(){
+    protected String getPathSegment() {
         return Constants.PATH_SEPARATOR + application;
-    };
+    }
+
+    ;
 
     public String getApplication() {
         return application;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java
index 23a055d..f3c1cbc 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/identifier/MetadataIdentifier.java
@@ -3,8 +3,6 @@ package org.apache.dubbo.metadata.identifier;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 
-import java.io.File;
-
 /**
  * @author cvictory ON 2018/10/25
  */
@@ -47,9 +45,11 @@ public class MetadataIdentifier {
         return URL.encode(serviceInterface);
     }
 
-    protected String getPathSegment(){
+    protected String getPathSegment() {
         return "";
-    };
+    }
+
+    ;
 
     public String getServiceInterface() {
         return serviceInterface;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java
index fa96538..89f075b 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/integration/MetadataReportService.java
@@ -16,14 +16,11 @@
  */
 package org.apache.dubbo.metadata.integration;
 
-import org.apache.commons.lang3.time.DateUtils;
 import org.apache.dubbo.common.Constants;
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.common.utils.NamedThreadFactory;
 import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
@@ -33,13 +30,6 @@ import org.apache.dubbo.metadata.store.MetadataReport;
 import org.apache.dubbo.metadata.store.MetadataReportFactory;
 import org.apache.dubbo.rpc.RpcException;
 
-import java.util.Calendar;
-import java.util.Date;
-import java.util.Random;
-import java.util.Set;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
 import java.util.function.Supplier;
 
 /**
@@ -85,7 +75,7 @@ public class MetadataReportService {
     public void publishProvider(URL providerUrl) throws RpcException {
         //first add into the list
         // remove the individul param
-        providerUrl = providerUrl.removeParameters(Constants.PID_KEY,Constants.TIMESTAMP_KEY,Constants.BIND_IP_KEY,Constants.BIND_PORT_KEY,Constants.TIMESTAMP_KEY);
+        providerUrl = providerUrl.removeParameters(Constants.PID_KEY, Constants.TIMESTAMP_KEY, Constants.BIND_IP_KEY, Constants.BIND_PORT_KEY, Constants.TIMESTAMP_KEY);
         try {
             String interfaceName = providerUrl.getParameter(Constants.INTERFACE_KEY);
             if (StringUtils.isNotEmpty(interfaceName)) {
@@ -103,7 +93,7 @@ public class MetadataReportService {
     }
 
     public void publishConsumer(URL consumerURL) throws RpcException {
-        consumerURL = consumerURL.removeParameters(Constants.PID_KEY,Constants.TIMESTAMP_KEY,Constants.BIND_IP_KEY,Constants.BIND_PORT_KEY,Constants.TIMESTAMP_KEY);
+        consumerURL = consumerURL.removeParameters(Constants.PID_KEY, Constants.TIMESTAMP_KEY, Constants.BIND_IP_KEY, Constants.BIND_PORT_KEY, Constants.TIMESTAMP_KEY);
         metadataReport.storeConsumerMetadata(new ConsumerMetadataIdentifier(consumerURL.getServiceInterface(),
                 consumerURL.getParameter(Constants.VERSION_KEY), consumerURL.getParameter(Constants.GROUP_KEY),
                 consumerURL.getParameter(Constants.APPLICATION_KEY)), consumerURL.toParameterString());
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
index aa1528d..eb9fb61 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReport.java
@@ -100,7 +100,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
         loadProperties();
         metadataReportRetry = new MetadataReportRetry(reportURL.getParameter(Constants.RETRY_TIMES_KEY, 60 * 60), reportURL.getParameter(Constants.RETRY_PERIOD_KEY, 3000));
         // cycle report the data switch
-        if(reportURL.getParameter(Constants.CYCLE_REPORT_KEY, true)){
+        if (reportURL.getParameter(Constants.CYCLE_REPORT_KEY, true)) {
             scheduler.scheduleAtFixedRate(new Runnable() {
                 @Override
                 public void run() {
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java
index c97d745..392350c 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/main/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactory.java
@@ -18,13 +18,9 @@ package org.apache.dubbo.metadata.support;
 
 import org.apache.dubbo.common.Constants;
 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.store.MetadataReport;
 import org.apache.dubbo.metadata.store.MetadataReportFactory;
 
-import java.util.Collection;
-import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java
index b15abe2..e3964af 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReport4Test.java
@@ -22,8 +22,8 @@ import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java
index 9d77abb..23437b8 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/store/test/JTestMetadataReportFactory4Test.java
@@ -17,9 +17,9 @@
 package org.apache.dubbo.metadata.store.test;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 import org.apache.dubbo.metadata.store.MetadataReport;
 import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
 /**
  * ZookeeperRegistryFactory.
diff --git a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java
index beb7594..6a808c1 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-api/src/test/java/org/apache/dubbo/metadata/support/AbstractMetadataReportFactoryTest.java
@@ -1,6 +1,7 @@
 package org.apache.dubbo.metadata.support;
 
 import com.alibaba.fastjson.JSON;
+
 import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.utils.NetUtils;
 import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java b/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
index 135020b..d6a6607 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-redis/src/main/java/org/apache/dubbo/metadata/store/redis/RedisMetadataReport.java
@@ -22,8 +22,8 @@ import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
-import org.apache.dubbo.rpc.RpcException;
 import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.rpc.RpcException;
 import redis.clients.jedis.Jedis;
 import redis.clients.jedis.JedisPool;
 import redis.clients.jedis.JedisPoolConfig;
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
index 22b926c..901601f 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReport.java
@@ -24,12 +24,10 @@ import org.apache.dubbo.common.utils.CollectionUtils;
 import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
+import org.apache.dubbo.metadata.support.AbstractMetadataReport;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
 import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
-import org.apache.dubbo.rpc.RpcException;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
 
-import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -92,7 +90,7 @@ public class ZookeeperMetadataReport extends AbstractMetadataReport {
         zkClient.create(filePath, false);
     }
 
-    String getCategory(MetadataIdentifier metadataIdentifier){
+    String getCategory(MetadataIdentifier metadataIdentifier) {
         return toRootDir() + metadataIdentifier.getFilePathKey();
     }
 
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
index 6389822..4e8902c 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
@@ -17,9 +17,9 @@
 package org.apache.dubbo.metadata.store.zookeeper;
 
 import org.apache.dubbo.common.URL;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 import org.apache.dubbo.metadata.store.MetadataReport;
 import org.apache.dubbo.metadata.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
 
 /**
  * ZookeeperRegistryFactory.
diff --git a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
index b0227e6..93b9c08 100644
--- a/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
+++ b/dubbo-metadata-report/dubbo-metadata-report-zookeeper/src/test/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportTest.java
@@ -10,7 +10,6 @@ import org.apache.dubbo.metadata.identifier.ConsumerMetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
 import org.apache.dubbo.metadata.identifier.ProviderMetadataIdentifier;
 import org.apache.dubbo.remoting.zookeeper.curator.CuratorZookeeperTransporter;
-import org.apache.dubbo.rpc.RpcException;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
index e113b93..480c3a8 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
@@ -52,14 +52,16 @@ public class ZKTools {
     }
 
     public static void testStartupConfig() {
-        String str = "dubbo.registry.address=\"zookeeper://127.0.0.1:2181\"\n" +
-                "dubbo.registry.group=\"dubboregistrygroup1\"\n" +
-                "dubbo.servicestore.address=\"zookeeper://127.0.0.1:2181\"\n" +
+        String str = "dubbo.registry.address=zookeeper://127.0.0.1:2181\n" +
+                "dubbo.registry.group=dubboregistrygroup1\n" +
+                "dubbo.servicestore.address=zookeeper://127.0.0.1:2181\n" +
                 "dubbo.protocol.port=20990\n" +
                 "dubbo.service.org.apache.dubbo.demo.DemoService.timeout=9999\n";
 
+        System.out.println(str);
+
         try {
-            String path = "/dubboregistrygroup1/dubbo.properties";
+            String path = "/dubboregistrygroup1/config/dubbo.properties";
             if (client.checkExists().forPath(path) == null) {
                 client.create().creatingParentsIfNeeded().forPath(path);
             }


[incubator-dubbo] 04/06: Changes for demo

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit 80f909151177e03c5a9413f4e82a18829ad31bbd
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 10:53:10 2018 +0800

    Changes for demo
---
 .../src/main/resources/META-INF/spring/dubbo-demo-consumer.xml   | 8 --------
 .../src/main/resources/META-INF/spring/dubbo-demo-provider.xml   | 9 +++------
 2 files changed, 3 insertions(+), 14 deletions(-)

diff --git a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
index 0216a13..1c0fa61 100644
--- a/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
+++ b/dubbo-demo/dubbo-demo-consumer/src/main/resources/META-INF/spring/dubbo-demo-consumer.xml
@@ -21,14 +21,6 @@
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
 
-    <!-- consumer's application name, used for tracing dependency relationship (not a matching criterion),
-    don't set it same as provider -->
-    <dubbo:application name="demo-consumer">
-        <dubbo:parameter key="config.type" value="zookeeper"/>
-        <dubbo:parameter key="config.address" value="127.0.0.1:2181"/>
-        <dubbo:parameter key="config.check" value="true"/>
-    </dubbo:application>
-
     <!-- use multicast registry center to discover service -->
     <dubbo:registry address="zookeeper://127.0.0.1:2181" default="true"/>
     <dubbo:registry address="zookeeper://127.0.0.1:2181"/>
diff --git a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
index 4e4a744..0c4c6dc 100644
--- a/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
+++ b/dubbo-demo/dubbo-demo-provider/src/main/resources/META-INF/spring/dubbo-demo-provider.xml
@@ -26,12 +26,9 @@
     <!--<dubbo:provider tag="tag3"/>-->
 
     <!-- use multicast registry center to export service -->
-    <!--<dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181" simple="false">
-        <dubbo:parameter key="config.check" value="false"/>
-    </dubbo:registry>-->
-    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181"/>
-
-    <dubbo:servicestore address="zookeeper://127.0.0.1:2181"/>
+    <dubbo:registry group="dubboregistrygroup1" address="zookeeper://127.0.0.1:2181" simple="false">
+    </dubbo:registry>
+    <!--<dubbo:configcenter type="zookeeper" address="127.0.0.1:2181" namespace="dubboregistrygroup1" dataid="dubbo.properties"/>-->
 
     <!-- use dubbo protocol to export service on port 20880 -->
     <dubbo:protocol name="dubbo" port="-1"/>


[incubator-dubbo] 03/06: Move UT in config-api to bootstrap temporarily, to solve the unreasonable dependency problem between modules.

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit a45bfd4f3a92af11f8a13aee6439d5a32ae5c5fc
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 10:50:32 2018 +0800

    Move UT in config-api to bootstrap temporarily, to solve the unreasonable dependency problem between modules.
---
 .../apache/dubbo/config/AbstractConfigTest.java    | 515 +++++++++++++++++++++
 .../dubbo/config/AbstractInterfaceConfigTest.java  | 407 ++++++++++++++++
 .../dubbo/config/AbstractMethodConfigTest.java     | 119 +++++
 .../dubbo/config/AbstractReferenceConfigTest.java  | 157 +++++++
 .../dubbo/config/AbstractServiceConfigTest.java    | 181 ++++++++
 .../apache/dubbo/config/ApplicationConfigTest.java | 177 +++++++
 .../apache/dubbo/config/ArgumentConfigTest.java    |  63 +++
 .../apache/dubbo/config/ConsumerConfigTest.java    |  81 ++++
 .../apache/dubbo/config/GenericServiceTest.java    | 314 +++++++++++++
 .../org/apache/dubbo/config/MethodConfigTest.java  | 182 ++++++++
 .../org/apache/dubbo/config/ModuleConfigTest.java  | 110 +++++
 .../org/apache/dubbo/config/MonitorConfigTest.java | 107 +++++
 .../apache/dubbo/config/ProtocolConfigTest.java    | 217 +++++++++
 .../apache/dubbo/config/ProviderConfigTest.java    | 219 +++++++++
 .../apache/dubbo/config/ReferenceConfigTest.java   | 108 +++++
 .../apache/dubbo/config/RegistryConfigTest.java    | 178 +++++++
 .../org/apache/dubbo/config/ServiceConfigTest.java | 205 ++++++++
 .../test/java/org/apache/dubbo/config/api/Box.java |  23 +
 .../org/apache/dubbo/config/api/DemoException.java |  42 ++
 .../org/apache/dubbo/config/api/DemoService.java   |  37 ++
 .../java/org/apache/dubbo/config/api/Greeting.java |  24 +
 .../java/org/apache/dubbo/config/api/User.java     |  65 +++
 .../apache/dubbo/config/cache/CacheService.java    |  26 ++
 .../dubbo/config/cache/CacheServiceImpl.java       |  32 ++
 .../org/apache/dubbo/config/cache/CacheTest.java   | 118 +++++
 .../config/consumer/DemoActionByAnnotation.java    |  34 ++
 .../dubbo/config/consumer/DemoActionBySetter.java  |  36 ++
 .../dubbo/config/consumer/DemoInterceptor.java     |  31 ++
 .../DelegateProviderMetaDataInvokerTest.java       |  59 +++
 .../apache/dubbo/config/mock/GreetingLocal1.java   |  21 +
 .../apache/dubbo/config/mock/GreetingLocal2.java   |  26 ++
 .../apache/dubbo/config/mock/GreetingLocal3.java   |  32 ++
 .../apache/dubbo/config/mock/GreetingMock1.java    |  20 +
 .../apache/dubbo/config/mock/GreetingMock2.java    |  29 ++
 .../org/apache/dubbo/config/mock/MockCluster.java  |  29 ++
 .../org/apache/dubbo/config/mock/MockCodec.java    |  37 ++
 .../apache/dubbo/config/mock/MockDispatcher.java   |  29 ++
 .../apache/dubbo/config/mock/MockExchanger.java    |  37 ++
 .../dubbo/config/mock/MockExporterListener.java    |  34 ++
 .../org/apache/dubbo/config/mock/MockFilter.java   |  30 ++
 .../dubbo/config/mock/MockInvokerListener.java     |  33 ++
 .../apache/dubbo/config/mock/MockLoadBalance.java  |  32 ++
 .../org/apache/dubbo/config/mock/MockProtocol.java |  86 ++++
 .../apache/dubbo/config/mock/MockProtocol2.java    |  48 ++
 .../apache/dubbo/config/mock/MockProxyFactory.java |  39 ++
 .../org/apache/dubbo/config/mock/MockRegistry.java | 108 +++++
 .../dubbo/config/mock/MockRegistryFactory.java     |  37 ++
 .../dubbo/config/mock/MockRegistryFactory2.java    |  31 ++
 .../dubbo/config/mock/MockStatusChecker.java       |  28 ++
 .../dubbo/config/mock/MockTelnetHandler.java       |  29 ++
 .../apache/dubbo/config/mock/MockThreadPool.java   |  30 ++
 .../apache/dubbo/config/mock/MockTransporter.java  |  41 ++
 .../apache/dubbo/config/mock/TestProxyFactory.java |  33 ++
 .../config/provider/impl/DemoServiceImpl.java      |  51 ++
 .../config/url/ExporterSideConfigUrlTest.java      |  98 ++++
 .../dubbo/config/url/InvokerSideConfigUrlTest.java | 227 +++++++++
 .../dubbo/config/url/RpcConfigGetSetProxy.java     | 166 +++++++
 .../org/apache/dubbo/config/url/UrlTestBase.java   | 211 +++++++++
 .../dubbo/config/utils/MockReferenceConfig.java    |  53 +++
 .../config/utils/ReferenceConfigCacheTest.java     | 114 +++++
 .../config/validation/ValidationParameter.java     | 106 +++++
 .../dubbo/config/validation/ValidationService.java |  70 +++
 .../config/validation/ValidationServiceImpl.java   |  37 ++
 .../dubbo/config/validation/ValidationTest.java    | 301 ++++++++++++
 .../org.apache.dubbo.common.status.StatusChecker   |  18 +
 .../org.apache.dubbo.common.threadpool.ThreadPool  |  18 +
 .../org.apache.dubbo.registry.RegistryFactory      |   2 +
 .../services/org.apache.dubbo.remoting.Codec       |  18 +
 .../services/org.apache.dubbo.remoting.Dispatcher  |  18 +
 .../services/org.apache.dubbo.remoting.Transporter |  18 +
 .../org.apache.dubbo.remoting.exchange.Exchanger   |  18 +
 .../org.apache.dubbo.remoting.telnet.TelnetHandler |  18 +
 .../services/org.apache.dubbo.rpc.ExporterListener |  18 +
 .../META-INF/services/org.apache.dubbo.rpc.Filter  |   1 +
 .../services/org.apache.dubbo.rpc.InvokerListener  |   1 +
 .../services/org.apache.dubbo.rpc.Protocol         |   2 +
 .../services/org.apache.dubbo.rpc.ProxyFactory     |   2 +
 .../services/org.apache.dubbo.rpc.cluster.Cluster  |   1 +
 .../org.apache.dubbo.rpc.cluster.LoadBalance       |   1 +
 dubbo-bootstrap/src/main/test/resources/log4j.xml  |  28 ++
 80 files changed, 6382 insertions(+)

diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractConfigTest.java
new file mode 100644
index 0000000..a9300ec
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -0,0 +1,515 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import junit.framework.TestCase;
+import org.apache.dubbo.config.api.Greeting;
+import org.apache.dubbo.config.support.Parameter;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertThat;
+
+public class AbstractConfigTest {
+
+    //FIXME
+    /*@Test
+    public void testAppendProperties1() throws Exception {
+        try {
+            System.setProperty("dubbo.properties.i", "1");
+            System.setProperty("dubbo.properties.c", "c");
+            System.setProperty("dubbo.properties.b", "2");
+            System.setProperty("dubbo.properties.d", "3");
+            System.setProperty("dubbo.properties.f", "4");
+            System.setProperty("dubbo.properties.l", "5");
+            System.setProperty("dubbo.properties.s", "6");
+            System.setProperty("dubbo.properties.str", "dubbo");
+            System.setProperty("dubbo.properties.bool", "true");
+            PropertiesConfig config = new PropertiesConfig();
+            AbstractConfig.appendProperties(config);
+            TestCase.assertEquals(1, config.getI());
+            TestCase.assertEquals('c', config.getC());
+            TestCase.assertEquals((byte) 0x02, config.getB());
+            TestCase.assertEquals(3d, config.getD());
+            TestCase.assertEquals(4f, config.getF());
+            TestCase.assertEquals(5L, config.getL());
+            TestCase.assertEquals(6, config.getS());
+            TestCase.assertEquals("dubbo", config.getStr());
+            TestCase.assertTrue(config.isBool());
+        } finally {
+            System.clearProperty("dubbo.properties.i");
+            System.clearProperty("dubbo.properties.c");
+            System.clearProperty("dubbo.properties.b");
+            System.clearProperty("dubbo.properties.d");
+            System.clearProperty("dubbo.properties.f");
+            System.clearProperty("dubbo.properties.l");
+            System.clearProperty("dubbo.properties.s");
+            System.clearProperty("dubbo.properties.str");
+            System.clearProperty("dubbo.properties.bool");
+        }
+    }
+
+    @Test
+    public void testAppendProperties2() throws Exception {
+        try {
+            System.setProperty("dubbo.properties.two.i", "2");
+            PropertiesConfig config = new PropertiesConfig("two");
+            AbstractConfig.appendProperties(config);
+            TestCase.assertEquals(2, config.getI());
+        } finally {
+            System.clearProperty("dubbo.properties.two.i");
+        }
+    }
+
+    @Test
+    public void testAppendProperties3() throws Exception {
+        try {
+            Properties p = new Properties();
+            p.put("dubbo.properties.str", "dubbo");
+            ConfigUtils.setProperties(p);
+            PropertiesConfig config = new PropertiesConfig();
+            AbstractConfig.appendProperties(config);
+            TestCase.assertEquals("dubbo", config.getStr());
+        } finally {
+            System.clearProperty(Constants.DUBBO_PROPERTIES_KEY);
+            ConfigUtils.setProperties(null);
+        }
+    }*/
+
+    @Test
+    public void testAppendParameters1() throws Exception {
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("default.num", "one");
+        parameters.put("num", "ONE");
+        AbstractConfig.appendParameters(parameters, new ParameterConfig(1, "hello/world", 30, "password"), "prefix");
+        TestCase.assertEquals("one", parameters.get("prefix.key.1"));
+        TestCase.assertEquals("two", parameters.get("prefix.key.2"));
+        TestCase.assertEquals("ONE,one,1", parameters.get("prefix.num"));
+        TestCase.assertEquals("hello%2Fworld", parameters.get("prefix.naming"));
+        TestCase.assertEquals("30", parameters.get("prefix.age"));
+        TestCase.assertFalse(parameters.containsKey("prefix.key-2"));
+        TestCase.assertFalse(parameters.containsKey("prefix.secret"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testAppendParameters2() throws Exception {
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractConfig.appendParameters(parameters, new ParameterConfig());
+    }
+
+    @Test
+    public void testAppendParameters3() throws Exception {
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractConfig.appendParameters(parameters, null);
+        TestCase.assertTrue(parameters.isEmpty());
+    }
+
+    @Test
+    public void testAppendParameters4() throws Exception {
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractConfig.appendParameters(parameters, new ParameterConfig(1, "hello/world", 30, "password"));
+        TestCase.assertEquals("one", parameters.get("key.1"));
+        TestCase.assertEquals("two", parameters.get("key.2"));
+        TestCase.assertEquals("1", parameters.get("num"));
+        TestCase.assertEquals("hello%2Fworld", parameters.get("naming"));
+        TestCase.assertEquals("30", parameters.get("age"));
+    }
+
+    @Test
+    public void testAppendAttributes1() throws Exception {
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01), "prefix");
+        TestCase.assertEquals('l', parameters.get("prefix.let"));
+        TestCase.assertEquals(true, parameters.get("prefix.activate"));
+        TestCase.assertFalse(parameters.containsKey("prefix.flag"));
+    }
+
+    @Test
+    public void testAppendAttributes2() throws Exception {
+        Map<String, Object> parameters = new HashMap<String, Object>();
+        AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01));
+        TestCase.assertEquals('l', parameters.get("let"));
+        TestCase.assertEquals(true, parameters.get("activate"));
+        TestCase.assertFalse(parameters.containsKey("flag"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkExtension() throws Exception {
+        AbstractConfig.checkExtension(Greeting.class, "hello", "world");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkMultiExtension1() throws Exception {
+        AbstractConfig.checkMultiExtension(Greeting.class, "hello", "default,world");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkMultiExtension2() throws Exception {
+        AbstractConfig.checkMultiExtension(Greeting.class, "hello", "default,-world");
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkLength() throws Exception {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i <= 200; i++) {
+            builder.append("a");
+        }
+        AbstractConfig.checkLength("hello", builder.toString());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkPathLength() throws Exception {
+        StringBuilder builder = new StringBuilder();
+        for (int i = 0; i <= 200; i++) {
+            builder.append("a");
+        }
+        AbstractConfig.checkPathLength("hello", builder.toString());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkName() throws Exception {
+        AbstractConfig.checkName("hello", "world%");
+    }
+
+    @Test
+    public void checkNameHasSymbol() throws Exception {
+        try {
+            AbstractConfig.checkNameHasSymbol("hello", ":*,/-0123abcdABCD");
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+    }
+
+    @Test
+    public void checkKey() throws Exception {
+        try {
+            AbstractConfig.checkKey("hello", "*,-0123abcdABCD");
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+    }
+
+    @Test
+    public void checkMultiName() throws Exception {
+        try {
+            AbstractConfig.checkMultiName("hello", ",-._0123abcdABCD");
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+    }
+
+    @Test
+    public void checkPathName() throws Exception {
+        try {
+            AbstractConfig.checkPathName("hello", "/-$._0123abcdABCD");
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+    }
+
+    @Test
+    public void checkMethodName() throws Exception {
+        try {
+            AbstractConfig.checkMethodName("hello", "abcdABCD0123abcd");
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+
+        try {
+            AbstractConfig.checkMethodName("hello", "0a");
+            TestCase.fail("the value should be illegal.");
+        } catch (Exception e) {
+            // ignore
+        }
+    }
+
+    @Test
+    public void checkParameterName() throws Exception {
+        Map<String, String> parameters = Collections.singletonMap("hello", ":*,/-._0123abcdABCD");
+        try {
+            AbstractConfig.checkParameterName(parameters);
+        } catch (Exception e) {
+            TestCase.fail("the value should be legal.");
+        }
+    }
+
+    @Test
+    @Config(interfaceClass = Greeting.class, filter = {"f1, f2"}, listener = {"l1, l2"},
+            parameters = {"k1", "v1", "k2", "v2"})
+    public void appendAnnotation() throws Exception {
+        Config config = getClass().getMethod("appendAnnotation").getAnnotation(Config.class);
+        AnnotationConfig annotationConfig = new AnnotationConfig();
+        annotationConfig.appendAnnotation(Config.class, config);
+        TestCase.assertSame(Greeting.class, annotationConfig.getInterface());
+        TestCase.assertEquals("f1, f2", annotationConfig.getFilter());
+        TestCase.assertEquals("l1, l2", annotationConfig.getListener());
+        TestCase.assertEquals(2, annotationConfig.getParameters().size());
+        TestCase.assertEquals("v1", annotationConfig.getParameters().get("k1"));
+        TestCase.assertEquals("v2", annotationConfig.getParameters().get("k2"));
+        assertThat(annotationConfig.toString(), Matchers.containsString("filter=\"f1, f2\" "));
+        assertThat(annotationConfig.toString(), Matchers.containsString("listener=\"l1, l2\" "));
+    }
+
+    private static class PropertiesConfig extends AbstractConfig {
+        private char c;
+        private boolean bool;
+        private byte b;
+        private int i;
+        private long l;
+        private float f;
+        private double d;
+        private short s;
+        private String str;
+
+        PropertiesConfig() {
+        }
+
+        PropertiesConfig(String id) {
+            this.id = id;
+        }
+
+        public char getC() {
+            return c;
+        }
+
+        public void setC(char c) {
+            this.c = c;
+        }
+
+        public boolean isBool() {
+            return bool;
+        }
+
+        public void setBool(boolean bool) {
+            this.bool = bool;
+        }
+
+        public byte getB() {
+            return b;
+        }
+
+        public void setB(byte b) {
+            this.b = b;
+        }
+
+        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;
+        }
+
+        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 short getS() {
+            return s;
+        }
+
+        public void setS(short s) {
+            this.s = s;
+        }
+    }
+
+    private static class ParameterConfig {
+        private int number;
+        private String name;
+        private int age;
+        private String secret;
+
+        ParameterConfig() {
+        }
+
+        ParameterConfig(int number, String name, int age, String secret) {
+            this.number = number;
+            this.name = name;
+            this.age = age;
+            this.secret = secret;
+        }
+
+        @Parameter(key = "num", append = true)
+        public int getNumber() {
+            return number;
+        }
+
+        public void setNumber(int number) {
+            this.number = number;
+        }
+
+        @Parameter(key = "naming", append = true, escaped = true, required = true)
+        public String getName() {
+            return name;
+        }
+
+        public void setName(String name) {
+            this.name = name;
+        }
+
+        public int getAge() {
+            return age;
+        }
+
+        public void setAge(int age) {
+            this.age = age;
+        }
+
+        @Parameter(excluded = true)
+        public String getSecret() {
+            return secret;
+        }
+
+        public void setSecret(String secret) {
+            this.secret = secret;
+        }
+
+        public Map getParameters() {
+            Map<String, String> map = new HashMap<String, String>();
+            map.put("key.1", "one");
+            map.put("key-2", "two");
+            return map;
+        }
+    }
+
+    private static class AttributeConfig {
+        private char letter;
+        private boolean activate;
+        private byte flag;
+
+        public AttributeConfig(char letter, boolean activate, byte flag) {
+            this.letter = letter;
+            this.activate = activate;
+            this.flag = flag;
+        }
+
+        @Parameter(attribute = true, key = "let")
+        public char getLetter() {
+            return letter;
+        }
+
+        public void setLetter(char letter) {
+            this.letter = letter;
+        }
+
+        @Parameter(attribute = true)
+        public boolean isActivate() {
+            return activate;
+        }
+
+        public void setActivate(boolean activate) {
+            this.activate = activate;
+        }
+
+        public byte getFlag() {
+            return flag;
+        }
+
+        public void setFlag(byte flag) {
+            this.flag = flag;
+        }
+    }
+
+    @Retention(RetentionPolicy.RUNTIME)
+    @Target({ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
+    public @interface Config {
+        Class<?> interfaceClass() default void.class;
+
+        String interfaceName() default "";
+
+        String[] filter() default {};
+
+        String[] listener() default {};
+
+        String[] parameters() default {};
+    }
+
+    private static class AnnotationConfig extends AbstractConfig {
+        private Class interfaceClass;
+        private String filter;
+        private String listener;
+        private Map<String, String> parameters;
+
+        public Class getInterface() {
+            return interfaceClass;
+        }
+
+        public void setInterface(Class interfaceName) {
+            this.interfaceClass = interfaceName;
+        }
+
+        public String getFilter() {
+            return filter;
+        }
+
+        public void setFilter(String filter) {
+            this.filter = filter;
+        }
+
+        public String getListener() {
+            return listener;
+        }
+
+        public void setListener(String listener) {
+            this.listener = listener;
+        }
+
+        public Map<String, String> getParameters() {
+            return parameters;
+        }
+
+        public void setParameters(Map<String, String> parameters) {
+            this.parameters = parameters;
+        }
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractInterfaceConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractInterfaceConfigTest.java
new file mode 100644
index 0000000..a99a910
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractInterfaceConfigTest.java
@@ -0,0 +1,407 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import junit.framework.TestCase;
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.config.api.Greeting;
+import org.apache.dubbo.config.mock.GreetingLocal1;
+import org.apache.dubbo.config.mock.GreetingLocal2;
+import org.apache.dubbo.config.mock.GreetingLocal3;
+import org.apache.dubbo.config.mock.GreetingMock1;
+import org.apache.dubbo.config.mock.GreetingMock2;
+import org.apache.dubbo.monitor.MonitorService;
+import org.apache.dubbo.registry.RegistryService;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+
+public class AbstractInterfaceConfigTest {
+    @ClassRule
+    public static TemporaryFolder tempDir = new TemporaryFolder();
+    private static File dubboProperties;
+
+    @BeforeClass
+    public static void setUp() throws Exception {
+        dubboProperties = tempDir.newFile(Constants.DUBBO_PROPERTIES_KEY);
+        System.setProperty(Constants.DUBBO_PROPERTIES_KEY, dubboProperties.getAbsolutePath());
+    }
+
+    @AfterClass
+    public static void tearDown() throws Exception {
+        System.clearProperty(Constants.DUBBO_PROPERTIES_KEY);
+    }
+
+    @Test
+    public void testCheckRegistry1() throws Exception {
+        System.setProperty("dubbo.registry.address", "addr1|addr2");
+        try {
+            InterfaceConfig interfaceConfig = new InterfaceConfig();
+            interfaceConfig.checkRegistry();
+            TestCase.assertEquals(2, interfaceConfig.getRegistries().size());
+        } finally {
+            System.clearProperty("dubbo.registry.address");
+        }
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testCheckRegistry2() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkRegistry();
+    }
+
+    @Test
+    public void checkApplication1() throws Exception {
+        try {
+            ConfigUtils.setProperties(null);
+            System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
+            System.clearProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
+
+            writeDubboProperties(Constants.SHUTDOWN_WAIT_KEY, "100");
+            System.setProperty("dubbo.application.name", "demo");
+            InterfaceConfig interfaceConfig = new InterfaceConfig();
+            interfaceConfig.checkApplication();
+            ApplicationConfig appConfig = interfaceConfig.getApplication();
+            TestCase.assertEquals("demo", appConfig.getName());
+            TestCase.assertEquals("100", System.getProperty(Constants.SHUTDOWN_WAIT_KEY));
+
+            System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
+            ConfigUtils.setProperties(null);
+            writeDubboProperties(Constants.SHUTDOWN_WAIT_SECONDS_KEY, "1000");
+            System.setProperty("dubbo.application.name", "demo");
+            interfaceConfig = new InterfaceConfig();
+            interfaceConfig.checkApplication();
+            TestCase.assertEquals("1000", System.getProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY));
+        } finally {
+            ConfigUtils.setProperties(null);
+            System.clearProperty("dubbo.application.name");
+            System.clearProperty(Constants.SHUTDOWN_WAIT_KEY);
+            System.clearProperty(Constants.SHUTDOWN_WAIT_SECONDS_KEY);
+        }
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkApplication2() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkApplication();
+    }
+
+    @Test
+    public void testLoadRegistries() throws Exception {
+        System.setProperty("dubbo.registry.address", "addr1");
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        List<URL> urls = interfaceConfig.loadRegistries(true);
+        TestCase.assertEquals(1, urls.size());
+        URL url = urls.get(0);
+        TestCase.assertEquals("registry", url.getProtocol());
+        TestCase.assertEquals("addr1:9090", url.getAddress());
+        TestCase.assertEquals(RegistryService.class.getName(), url.getPath());
+        TestCase.assertTrue(url.getParameters().containsKey("timestamp"));
+        TestCase.assertTrue(url.getParameters().containsKey("pid"));
+        TestCase.assertTrue(url.getParameters().containsKey("registry"));
+        TestCase.assertTrue(url.getParameters().containsKey("dubbo"));
+    }
+
+    @Test
+    public void testLoadMonitor() throws Exception {
+        System.setProperty("dubbo.monitor.address", "monitor-addr:12080");
+        System.setProperty("dubbo.monitor.protocol", "monitor");
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        URL url = interfaceConfig.loadMonitor(new URL("dubbo", "addr1", 9090));
+        TestCase.assertEquals("monitor-addr:12080", url.getAddress());
+        TestCase.assertEquals(MonitorService.class.getName(), url.getParameter("interface"));
+        TestCase.assertNotNull(url.getParameter("dubbo"));
+        TestCase.assertNotNull(url.getParameter("pid"));
+        TestCase.assertNotNull(url.getParameter("timestamp"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkInterfaceAndMethods1() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkInterfaceAndMethods(null, null);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkInterfaceAndMethods2() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkInterfaceAndMethods(AbstractInterfaceConfigTest.class, null);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkInterfaceAndMethod3() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkInterfaceAndMethod4() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setName("nihao");
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
+    }
+
+    @Test
+    public void checkInterfaceAndMethod5() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setName("hello");
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock1() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setLocal(GreetingLocal1.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock2() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setLocal(GreetingLocal2.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test
+    public void checkStubAndMock3() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setLocal(GreetingLocal3.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock4() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setStub(GreetingLocal1.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock5() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setStub(GreetingLocal2.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test
+    public void checkStubAndMock6() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setStub(GreetingLocal3.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock7() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setMock("return {a, b}");
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock8() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setMock(GreetingMock1.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void checkStubAndMock9() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setMock(GreetingMock2.class.getName());
+        interfaceConfig.checkStubAndMock(Greeting.class);
+    }
+
+    @Test
+    public void testLocal() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setLocal((Boolean) null);
+        TestCase.assertNull(interfaceConfig.getLocal());
+        interfaceConfig.setLocal(true);
+        TestCase.assertEquals("true", interfaceConfig.getLocal());
+        interfaceConfig.setLocal("GreetingMock");
+        TestCase.assertEquals("GreetingMock", interfaceConfig.getLocal());
+    }
+
+    @Test
+    public void testStub() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setStub((Boolean) null);
+        TestCase.assertNull(interfaceConfig.getStub());
+        interfaceConfig.setStub(true);
+        TestCase.assertEquals("true", interfaceConfig.getStub());
+        interfaceConfig.setStub("GreetingMock");
+        TestCase.assertEquals("GreetingMock", interfaceConfig.getStub());
+    }
+
+    @Test
+    public void testCluster() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setCluster("mockcluster");
+        TestCase.assertEquals("mockcluster", interfaceConfig.getCluster());
+    }
+
+    @Test
+    public void testProxy() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setProxy("mockproxyfactory");
+        TestCase.assertEquals("mockproxyfactory", interfaceConfig.getProxy());
+    }
+
+    @Test
+    public void testConnections() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setConnections(1);
+        TestCase.assertEquals(1, interfaceConfig.getConnections().intValue());
+    }
+
+    @Test
+    public void testFilter() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setFilter("mockfilter");
+        TestCase.assertEquals("mockfilter", interfaceConfig.getFilter());
+    }
+
+    @Test
+    public void testListener() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setListener("mockinvokerlistener");
+        TestCase.assertEquals("mockinvokerlistener", interfaceConfig.getListener());
+    }
+
+    @Test
+    public void testLayer() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setLayer("layer");
+        TestCase.assertEquals("layer", interfaceConfig.getLayer());
+    }
+
+    @Test
+    public void testApplication() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        ApplicationConfig applicationConfig = new ApplicationConfig();
+        interfaceConfig.setApplication(applicationConfig);
+        TestCase.assertSame(applicationConfig, interfaceConfig.getApplication());
+    }
+
+    @Test
+    public void testModule() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        ModuleConfig moduleConfig = new ModuleConfig();
+        interfaceConfig.setModule(moduleConfig);
+        TestCase.assertSame(moduleConfig, interfaceConfig.getModule());
+    }
+
+    @Test
+    public void testRegistry() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        RegistryConfig registryConfig = new RegistryConfig();
+        interfaceConfig.setRegistry(registryConfig);
+        TestCase.assertSame(registryConfig, interfaceConfig.getRegistry());
+    }
+
+    @Test
+    public void testRegistries() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        RegistryConfig registryConfig = new RegistryConfig();
+        interfaceConfig.setRegistries(Collections.singletonList(registryConfig));
+        TestCase.assertEquals(1, interfaceConfig.getRegistries().size());
+        TestCase.assertSame(registryConfig, interfaceConfig.getRegistries().get(0));
+    }
+
+    @Test
+    public void testMonitor() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setMonitor("monitor-addr");
+        TestCase.assertEquals("monitor-addr", interfaceConfig.getMonitor().getAddress());
+        MonitorConfig monitorConfig = new MonitorConfig();
+        interfaceConfig.setMonitor(monitorConfig);
+        TestCase.assertSame(monitorConfig, interfaceConfig.getMonitor());
+    }
+
+    @Test
+    public void testOwner() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setOwner("owner");
+        TestCase.assertEquals("owner", interfaceConfig.getOwner());
+    }
+
+    @Test
+    public void testCallbacks() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setCallbacks(2);
+        TestCase.assertEquals(2, interfaceConfig.getCallbacks().intValue());
+    }
+
+    @Test
+    public void testOnconnect() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setOnconnect("onConnect");
+        TestCase.assertEquals("onConnect", interfaceConfig.getOnconnect());
+    }
+
+    @Test
+    public void testOndisconnect() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setOndisconnect("onDisconnect");
+        TestCase.assertEquals("onDisconnect", interfaceConfig.getOndisconnect());
+    }
+
+    @Test
+    public void testScope() throws Exception {
+        InterfaceConfig interfaceConfig = new InterfaceConfig();
+        interfaceConfig.setScope("scope");
+        TestCase.assertEquals("scope", interfaceConfig.getScope());
+    }
+
+    private void writeDubboProperties(String key, String value) {
+        OutputStream os = null;
+        try {
+            os = new BufferedOutputStream(new FileOutputStream(dubboProperties));
+            Properties properties = new Properties();
+            properties.put(key, value);
+            properties.store(os, "");
+            os.close();
+        } catch (IOException e) {
+            if (os != null) {
+                try {
+                    os.close();
+                } catch (IOException ioe) {
+                    // ignore
+                }
+            }
+        }
+    }
+
+    private static class InterfaceConfig extends AbstractInterfaceConfig {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractMethodConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractMethodConfigTest.java
new file mode 100644
index 0000000..41549e3
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractMethodConfigTest.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.isEmptyOrNullString;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+
+public class AbstractMethodConfigTest {
+    @Test
+    public void testTimeout() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setTimeout(10);
+        assertThat(methodConfig.getTimeout(), equalTo(10));
+    }
+
+    @Test
+    public void testRetries() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setRetries(3);
+        assertThat(methodConfig.getRetries(), equalTo(3));
+    }
+
+    @Test
+    public void testLoadbalance() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setLoadbalance("mockloadbalance");
+        assertThat(methodConfig.getLoadbalance(), equalTo("mockloadbalance"));
+    }
+
+    @Test
+    public void testAsync() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setAsync(true);
+        assertThat(methodConfig.isAsync(), is(true));
+    }
+
+    @Test
+    public void testActives() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setActives(10);
+        assertThat(methodConfig.getActives(), equalTo(10));
+    }
+
+    @Test
+    public void testSent() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setSent(true);
+        assertThat(methodConfig.getSent(), is(true));
+    }
+
+    @Test
+    public void testMock() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setMock((Boolean) null);
+        assertThat(methodConfig.getMock(), isEmptyOrNullString());
+        methodConfig.setMock(true);
+        assertThat(methodConfig.getMock(), equalTo("true"));
+        methodConfig.setMock("return null");
+        assertThat(methodConfig.getMock(), equalTo("return null"));
+        methodConfig.setMock("mock");
+        assertThat(methodConfig.getMock(), equalTo("mock"));
+    }
+
+    @Test
+    public void testMerger() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setMerger("merger");
+        assertThat(methodConfig.getMerger(), equalTo("merger"));
+    }
+
+    @Test
+    public void testCache() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setCache("cache");
+        assertThat(methodConfig.getCache(), equalTo("cache"));
+    }
+
+    @Test
+    public void testValidation() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        methodConfig.setValidation("validation");
+        assertThat(methodConfig.getValidation(), equalTo("validation"));
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        MethodConfig methodConfig = new MethodConfig();
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("key", "value");
+        methodConfig.setParameters(parameters);
+        assertThat(methodConfig.getParameters(), sameInstance(parameters));
+    }
+
+    private static class MethodConfig extends AbstractMethodConfig {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractReferenceConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractReferenceConfigTest.java
new file mode 100644
index 0000000..a53217c
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractReferenceConfigTest.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.config;
+
+import org.apache.dubbo.common.Constants;
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.hasValue;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class AbstractReferenceConfigTest {
+
+    @Test
+    public void testCheck() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setCheck(true);
+        assertThat(referenceConfig.isCheck(), is(true));
+    }
+
+    @Test
+    public void testInit() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setInit(true);
+        assertThat(referenceConfig.isInit(), is(true));
+    }
+
+    @Test
+    public void testGeneric() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setGeneric(true);
+        assertThat(referenceConfig.isGeneric(), is(true));
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        // FIXME: not sure why AbstractReferenceConfig has both isGeneric and getGeneric
+        assertThat(parameters, hasKey("generic"));
+    }
+
+    @Test
+    public void testInjvm() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setInit(true);
+        assertThat(referenceConfig.isInit(), is(true));
+    }
+
+    @Test
+    public void testFilter() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setFilter("mockfilter");
+        assertThat(referenceConfig.getFilter(), equalTo("mockfilter"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put(Constants.REFERENCE_FILTER_KEY, "prefilter");
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        assertThat(parameters, hasValue("prefilter,mockfilter"));
+    }
+
+    @Test
+    public void testListener() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setListener("mockinvokerlistener");
+        assertThat(referenceConfig.getListener(), equalTo("mockinvokerlistener"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put(Constants.INVOKER_LISTENER_KEY, "prelistener");
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        assertThat(parameters, hasValue("prelistener,mockinvokerlistener"));
+    }
+
+    @Test
+    public void testLazy() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setLazy(true);
+        assertThat(referenceConfig.getLazy(), is(true));
+    }
+
+    @Test
+    public void testOnconnect() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setOnconnect("onConnect");
+        assertThat(referenceConfig.getOnconnect(), equalTo("onConnect"));
+        assertThat(referenceConfig.getStubevent(), is(true));
+    }
+
+    @Test
+    public void testOndisconnect() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setOndisconnect("onDisconnect");
+        assertThat(referenceConfig.getOndisconnect(), equalTo("onDisconnect"));
+        assertThat(referenceConfig.getStubevent(), is(true));
+    }
+
+    @Test
+    public void testStubevent() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setOnconnect("onConnect");
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        assertThat(parameters, hasKey(Constants.STUB_EVENT_KEY));
+    }
+
+    @Test
+    public void testReconnect() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setReconnect("reconnect");
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        assertThat(referenceConfig.getReconnect(), equalTo("reconnect"));
+        assertThat(parameters, hasKey(Constants.RECONNECT_KEY));
+    }
+
+    @Test
+    public void testSticky() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setSticky(true);
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractInterfaceConfig.appendParameters(parameters, referenceConfig);
+        assertThat(referenceConfig.getSticky(), is(true));
+        assertThat(parameters, hasKey(Constants.CLUSTER_STICKY_KEY));
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setVersion("version");
+        assertThat(referenceConfig.getVersion(), equalTo("version"));
+    }
+
+    @Test
+    public void testGroup() throws Exception {
+        ReferenceConfig referenceConfig = new ReferenceConfig();
+        referenceConfig.setGroup("group");
+        assertThat(referenceConfig.getGroup(), equalTo("group"));
+    }
+
+    private static class ReferenceConfig extends AbstractReferenceConfig {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractServiceConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractServiceConfigTest.java
new file mode 100644
index 0000000..3f79541
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/AbstractServiceConfigTest.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.nullValue;
+import static org.junit.Assert.assertThat;
+
+public class AbstractServiceConfigTest {
+    @Test
+    public void testVersion() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setVersion("version");
+        assertThat(serviceConfig.getVersion(), equalTo("version"));
+    }
+
+    @Test
+    public void testGroup() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setGroup("group");
+        assertThat(serviceConfig.getGroup(), equalTo("group"));
+    }
+
+    @Test
+    public void testDelay() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setDelay(1000);
+        assertThat(serviceConfig.getDelay(), equalTo(1000));
+    }
+
+    @Test
+    public void testExport() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setExport(true);
+        assertThat(serviceConfig.getExport(), is(true));
+    }
+
+    @Test
+    public void testWeight() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setWeight(500);
+        assertThat(serviceConfig.getWeight(), equalTo(500));
+    }
+
+    @Test
+    public void testDocument() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setDocument("http://dubbo.io");
+        assertThat(serviceConfig.getDocument(), equalTo("http://dubbo.io"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractServiceConfig.appendParameters(parameters, serviceConfig);
+        assertThat(parameters, hasEntry("document", "http%3A%2F%2Fdubbo.io"));
+    }
+
+    @Test
+    public void testToken() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setToken("token");
+        assertThat(serviceConfig.getToken(), equalTo("token"));
+        serviceConfig.setToken((Boolean) null);
+        assertThat(serviceConfig.getToken(), nullValue());
+        serviceConfig.setToken(true);
+        assertThat(serviceConfig.getToken(), is("true"));
+    }
+
+    @Test
+    public void testDeprecated() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setDeprecated(true);
+        assertThat(serviceConfig.isDeprecated(), is(true));
+    }
+
+    @Test
+    public void testDynamic() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setDynamic(true);
+        assertThat(serviceConfig.isDynamic(), is(true));
+    }
+
+    @Test
+    public void testProtocol() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        assertThat(serviceConfig.getProtocol(), nullValue());
+        serviceConfig.setProtocol(new ProtocolConfig());
+        assertThat(serviceConfig.getProtocol(), notNullValue());
+        serviceConfig.setProtocols(Collections.singletonList(new ProtocolConfig()));
+        assertThat(serviceConfig.getProtocols(), hasSize(1));
+    }
+
+    @Test
+    public void testAccesslog() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setAccesslog("access.log");
+        assertThat(serviceConfig.getAccesslog(), equalTo("access.log"));
+        serviceConfig.setAccesslog((Boolean) null);
+        assertThat(serviceConfig.getAccesslog(), nullValue());
+        serviceConfig.setAccesslog(true);
+        assertThat(serviceConfig.getAccesslog(), equalTo("true"));
+    }
+
+    @Test
+    public void testExecutes() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setExecutes(10);
+        assertThat(serviceConfig.getExecutes(), equalTo(10));
+    }
+
+    @Test
+    public void testFilter() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setFilter("mockfilter");
+        assertThat(serviceConfig.getFilter(), equalTo("mockfilter"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put(Constants.SERVICE_FILTER_KEY, "prefilter");
+        AbstractServiceConfig.appendParameters(parameters, serviceConfig);
+        assertThat(parameters, hasEntry(Constants.SERVICE_FILTER_KEY, "prefilter,mockfilter"));
+    }
+
+    @Test
+    public void testListener() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setListener("mockexporterlistener");
+        assertThat(serviceConfig.getListener(), equalTo("mockexporterlistener"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put(Constants.EXPORTER_LISTENER_KEY, "prelistener");
+        AbstractServiceConfig.appendParameters(parameters, serviceConfig);
+        assertThat(parameters, hasEntry(Constants.EXPORTER_LISTENER_KEY, "prelistener,mockexporterlistener"));
+    }
+
+    @Test
+    public void testRegister() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setRegister(true);
+        assertThat(serviceConfig.isRegister(), is(true));
+    }
+
+    @Test
+    public void testWarmup() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setWarmup(100);
+        assertThat(serviceConfig.getWarmup(), equalTo(100));
+    }
+
+    @Test
+    public void testSerialization() throws Exception {
+        ServiceConfig serviceConfig = new ServiceConfig();
+        serviceConfig.setSerialization("serialization");
+        assertThat(serviceConfig.getSerialization(), equalTo("serialization"));
+    }
+
+
+    private static class ServiceConfig extends AbstractServiceConfig {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ApplicationConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ApplicationConfigTest.java
new file mode 100644
index 0000000..1cc5a22
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ApplicationConfigTest.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
+import static org.junit.Assert.assertThat;
+
+public class ApplicationConfigTest {
+    @Test
+    public void testName() throws Exception {
+        ApplicationConfig application = new ApplicationConfig();
+        application.setName("app");
+        assertThat(application.getName(), equalTo("app"));
+        application = new ApplicationConfig("app2");
+        assertThat(application.getName(), equalTo("app2"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry(Constants.APPLICATION_KEY, "app2"));
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setVersion("1.0.0");
+        assertThat(application.getVersion(), equalTo("1.0.0"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry("application.version", "1.0.0"));
+    }
+
+    @Test
+    public void testOwner() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setOwner("owner");
+        assertThat(application.getOwner(), equalTo("owner"));
+    }
+
+    @Test
+    public void testOrganization() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setOrganization("org");
+        assertThat(application.getOrganization(), equalTo("org"));
+    }
+
+    @Test
+    public void testArchitecture() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setArchitecture("arch");
+        assertThat(application.getArchitecture(), equalTo("arch"));
+    }
+
+    @Test
+    public void testEnvironment1() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setEnvironment("develop");
+        assertThat(application.getEnvironment(), equalTo("develop"));
+        application.setEnvironment("test");
+        assertThat(application.getEnvironment(), equalTo("test"));
+        application.setEnvironment("product");
+        assertThat(application.getEnvironment(), equalTo("product"));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testEnvironment2() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setEnvironment("illegal-env");
+    }
+
+    @Test
+    public void testRegistry() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        RegistryConfig registry = new RegistryConfig();
+        application.setRegistry(registry);
+        assertThat(application.getRegistry(), sameInstance(registry));
+        application.setRegistries(Collections.singletonList(registry));
+        assertThat(application.getRegistries(), contains(registry));
+        assertThat(application.getRegistries(), hasSize(1));
+    }
+
+    @Test
+    public void testMonitor() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setMonitor(new MonitorConfig("monitor-addr"));
+        assertThat(application.getMonitor().getAddress(), equalTo("monitor-addr"));
+        application.setMonitor("monitor-addr");
+        assertThat(application.getMonitor().getAddress(), equalTo("monitor-addr"));
+    }
+
+    @Test
+    public void testLogger() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setLogger("log4j");
+        assertThat(application.getLogger(), equalTo("log4j"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setDefault(true);
+        assertThat(application.isDefault(), is(true));
+    }
+
+    @Test
+    public void testDumpDirectory() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setDumpDirectory("/dump");
+        assertThat(application.getDumpDirectory(), equalTo("/dump"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry(Constants.DUMP_DIRECTORY, "/dump"));
+    }
+
+    @Test
+    public void testQosEnable() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setQosEnable(true);
+        assertThat(application.getQosEnable(), is(true));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry(Constants.QOS_ENABLE, "true"));
+    }
+
+    @Test
+    public void testQosPort() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setQosPort(8080);
+        assertThat(application.getQosPort(), equalTo(8080));
+    }
+
+    @Test
+    public void testQosAcceptForeignIp() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setQosAcceptForeignIp(true);
+        assertThat(application.getQosAcceptForeignIp(), is(true));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry(Constants.ACCEPT_FOREIGN_IP, "true"));
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        ApplicationConfig application = new ApplicationConfig("app");
+        application.setQosAcceptForeignIp(true);
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("k1", "v1");
+        ApplicationConfig.appendParameters(parameters, application);
+        assertThat(parameters, hasEntry("k1", "v1"));
+        assertThat(parameters, hasEntry(Constants.ACCEPT_FOREIGN_IP, "true"));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ArgumentConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ArgumentConfigTest.java
new file mode 100644
index 0000000..26051f9
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ArgumentConfigTest.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.config;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ArgumentConfigTest {
+    @Test
+    public void testIndex() throws Exception {
+        ArgumentConfig argument = new ArgumentConfig();
+        argument.setIndex(1);
+        assertThat(argument.getIndex(), is(1));
+    }
+
+    @Test
+    public void testType() throws Exception {
+        ArgumentConfig argument = new ArgumentConfig();
+        argument.setType("int");
+        assertThat(argument.getType(), equalTo("int"));
+    }
+
+    @Test
+    public void testCallback() throws Exception {
+        ArgumentConfig argument = new ArgumentConfig();
+        argument.setCallback(true);
+        assertThat(argument.isCallback(), is(true));
+    }
+
+    @Test
+    public void testArguments() throws Exception {
+        ArgumentConfig argument = new ArgumentConfig();
+        argument.setIndex(1);
+        argument.setType("int");
+        argument.setCallback(true);
+        Map<String, String> parameters = new HashMap<String, String>();
+        AbstractServiceConfig.appendParameters(parameters, argument);
+        assertThat(parameters, hasEntry("callback", "true"));
+        assertThat(parameters.size(), is(1));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ConsumerConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
new file mode 100644
index 0000000..b9a1a9a
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ConsumerConfigTest {
+    @Test
+    public void testTimeout() throws Exception {
+        try {
+            System.clearProperty("sun.rmi.transport.tcp.responseTimeout");
+            ConsumerConfig consumer = new ConsumerConfig();
+            consumer.setTimeout(10);
+            assertThat(consumer.getTimeout(), is(10));
+            assertThat(System.getProperty("sun.rmi.transport.tcp.responseTimeout"), equalTo("10"));
+        } finally {
+            System.clearProperty("sun.rmi.transport.tcp.responseTimeout");
+        }
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setDefault(true);
+        assertThat(consumer.isDefault(), is(true));
+    }
+
+    @Test
+    public void testClient() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setClient("client");
+        assertThat(consumer.getClient(), equalTo("client"));
+    }
+
+    @Test
+    public void testThreadpool() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setThreadpool("fixed");
+        assertThat(consumer.getThreadpool(), equalTo("fixed"));
+    }
+
+    @Test
+    public void testCorethreads() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setCorethreads(10);
+        assertThat(consumer.getCorethreads(), equalTo(10));
+    }
+
+    @Test
+    public void testThreads() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setThreads(20);
+        assertThat(consumer.getThreads(), equalTo(20));
+    }
+
+    @Test
+    public void testQueues() throws Exception {
+        ConsumerConfig consumer = new ConsumerConfig();
+        consumer.setQueues(5);
+        assertThat(consumer.getQueues(), equalTo(5));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/GenericServiceTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/GenericServiceTest.java
new file mode 100644
index 0000000..eed9b1e
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/GenericServiceTest.java
@@ -0,0 +1,314 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.beanutil.JavaBeanAccessor;
+import org.apache.dubbo.common.beanutil.JavaBeanDescriptor;
+import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.serialize.Serialization;
+import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.config.api.DemoException;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.api.User;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.apache.dubbo.rpc.service.GenericException;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * GenericServiceTest
+ */
+public class GenericServiceTest {
+
+    @Test
+    public void testGenericServiceException() {
+        ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
+        service.setApplication(new ApplicationConfig("generic-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29581));
+        service.setInterface(DemoService.class.getName());
+        service.setRef(new GenericService() {
+
+            public Object $invoke(String method, String[] parameterTypes, Object[] args)
+                    throws GenericException {
+                if ("sayName".equals(method)) {
+                    return "Generic " + args[0];
+                }
+                if ("throwDemoException".equals(method)) {
+                    throw new GenericException(DemoException.class.getName(), "Generic");
+                }
+                if ("getUsers".equals(method)) {
+                    return args[0];
+                }
+                return null;
+            }
+        });
+        service.export();
+        try {
+            ReferenceConfig<DemoService> reference = new ReferenceConfig<DemoService>();
+            reference.setApplication(new ApplicationConfig("generic-consumer"));
+            reference.setInterface(DemoService.class);
+            reference.setUrl("dubbo://127.0.0.1:29581?generic=true&timeout=3000");
+            DemoService demoService = reference.get();
+            try {
+                // say name
+                Assert.assertEquals("Generic Haha", demoService.sayName("Haha"));
+                // get users
+                List<User> users = new ArrayList<User>();
+                users.add(new User("Aaa"));
+                users = demoService.getUsers(users);
+                Assert.assertEquals("Aaa", users.get(0).getName());
+                // throw demo exception
+                try {
+                    demoService.throwDemoException();
+                    Assert.fail();
+                } catch (DemoException e) {
+                    Assert.assertEquals("Generic", e.getMessage());
+                }
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Test
+    public void testGenericReferenceException() {
+        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
+        service.setApplication(new ApplicationConfig("generic-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29581));
+        service.setInterface(DemoService.class.getName());
+        service.setRef(new DemoServiceImpl());
+        service.export();
+        try {
+            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
+            reference.setApplication(new ApplicationConfig("generic-consumer"));
+            reference.setInterface(DemoService.class);
+            reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
+            reference.setGeneric(true);
+            GenericService genericService = reference.get();
+            try {
+                List<Map<String, Object>> users = new ArrayList<Map<String, Object>>();
+                Map<String, Object> user = new HashMap<String, Object>();
+                user.put("class", "org.apache.dubbo.config.api.User");
+                user.put("name", "actual.provider");
+                users.add(user);
+                users = (List<Map<String, Object>>) genericService.$invoke("getUsers", new String[]{List.class.getName()}, new Object[]{users});
+                Assert.assertEquals(1, users.size());
+                Assert.assertEquals("actual.provider", users.get(0).get("name"));
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testGenericSerializationJava() throws Exception {
+        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
+        service.setApplication(new ApplicationConfig("generic-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29581));
+        service.setInterface(DemoService.class.getName());
+        DemoServiceImpl ref = new DemoServiceImpl();
+        service.setRef(ref);
+        service.export();
+        try {
+            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
+            reference.setApplication(new ApplicationConfig("generic-consumer"));
+            reference.setInterface(DemoService.class);
+            reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
+            reference.setGeneric(Constants.GENERIC_SERIALIZATION_NATIVE_JAVA);
+            GenericService genericService = reference.get();
+            try {
+                String name = "kimi";
+                ByteArrayOutputStream bos = new ByteArrayOutputStream(512);
+                ExtensionLoader.getExtensionLoader(Serialization.class)
+                        .getExtension("nativejava").serialize(null, bos).writeObject(name);
+                byte[] arg = bos.toByteArray();
+                Object obj = genericService.$invoke("sayName", new String[]{String.class.getName()}, new Object[]{arg});
+                Assert.assertTrue(obj instanceof byte[]);
+                byte[] result = (byte[]) obj;
+                Assert.assertEquals(ref.sayName(name), ExtensionLoader.getExtensionLoader(Serialization.class)
+                        .getExtension("nativejava").deserialize(null, new ByteArrayInputStream(result)).readObject().toString());
+
+                // getUsers
+                List<User> users = new ArrayList<User>();
+                User user = new User();
+                user.setName(name);
+                users.add(user);
+                bos = new ByteArrayOutputStream(512);
+                ExtensionLoader.getExtensionLoader(Serialization.class)
+                        .getExtension("nativejava").serialize(null, bos).writeObject(users);
+                obj = genericService.$invoke("getUsers",
+                        new String[]{List.class.getName()},
+                        new Object[]{bos.toByteArray()});
+                Assert.assertTrue(obj instanceof byte[]);
+                result = (byte[]) obj;
+                Assert.assertEquals(users,
+                        ExtensionLoader.getExtensionLoader(Serialization.class)
+                                .getExtension("nativejava")
+                                .deserialize(null, new ByteArrayInputStream(result))
+                                .readObject());
+
+                // echo(int)
+                bos = new ByteArrayOutputStream(512);
+                ExtensionLoader.getExtensionLoader(Serialization.class).getExtension("nativejava")
+                        .serialize(null, bos).writeObject(Integer.MAX_VALUE);
+                obj = genericService.$invoke("echo", new String[]{int.class.getName()}, new Object[]{bos.toByteArray()});
+                Assert.assertTrue(obj instanceof byte[]);
+                Assert.assertEquals(Integer.MAX_VALUE,
+                        ExtensionLoader.getExtensionLoader(Serialization.class)
+                                .getExtension("nativejava")
+                                .deserialize(null, new ByteArrayInputStream((byte[]) obj))
+                                .readObject());
+
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testGenericInvokeWithBeanSerialization() throws Exception {
+        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
+        service.setApplication(new ApplicationConfig("bean-provider"));
+        service.setInterface(DemoService.class);
+        service.setRegistry(new RegistryConfig("N/A"));
+        DemoServiceImpl impl = new DemoServiceImpl();
+        service.setRef(impl);
+        service.setProtocol(new ProtocolConfig("dubbo", 29581));
+        service.export();
+        ReferenceConfig<GenericService> reference = null;
+        try {
+            reference = new ReferenceConfig<GenericService>();
+            reference.setApplication(new ApplicationConfig("bean-consumer"));
+            reference.setInterface(DemoService.class);
+            reference.setUrl("dubbo://127.0.0.1:29581?scope=remote&timeout=3000");
+            reference.setGeneric(Constants.GENERIC_SERIALIZATION_BEAN);
+            GenericService genericService = reference.get();
+            User user = new User();
+            user.setName("zhangsan");
+            List<User> users = new ArrayList<User>();
+            users.add(user);
+            Object result = genericService.$invoke("getUsers", new String[]{ReflectUtils.getName(List.class)}, new Object[]{JavaBeanSerializeUtil.serialize(users, JavaBeanAccessor.METHOD)});
+            Assert.assertTrue(result instanceof JavaBeanDescriptor);
+            JavaBeanDescriptor descriptor = (JavaBeanDescriptor) result;
+            Assert.assertTrue(descriptor.isCollectionType());
+            Assert.assertEquals(1, descriptor.propertySize());
+            descriptor = (JavaBeanDescriptor) descriptor.getProperty(0);
+            Assert.assertTrue(descriptor.isBeanType());
+            Assert.assertEquals(user.getName(), ((JavaBeanDescriptor) descriptor.getProperty("name")).getPrimitiveProperty());
+        } finally {
+            if (reference != null) {
+                reference.destroy();
+            }
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testGenericImplementationWithBeanSerialization() throws Exception {
+        final AtomicReference reference = new AtomicReference();
+        ServiceConfig<GenericService> service = new ServiceConfig<GenericService>();
+        service.setApplication(new ApplicationConfig("bean-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29581));
+        service.setInterface(DemoService.class.getName());
+        service.setRef(new GenericService() {
+
+            public Object $invoke(String method, String[] parameterTypes, Object[] args) throws GenericException {
+                if ("getUsers".equals(method)) {
+                    GenericParameter arg = new GenericParameter();
+                    arg.method = method;
+                    arg.parameterTypes = parameterTypes;
+                    arg.arguments = args;
+                    reference.set(arg);
+                    return args[0];
+                }
+                if ("sayName".equals(method)) {
+                    return null;
+                }
+                return args;
+            }
+        });
+        service.export();
+        ReferenceConfig<DemoService> ref = null;
+        try {
+            ref = new ReferenceConfig<DemoService>();
+            ref.setApplication(new ApplicationConfig("bean-consumer"));
+            ref.setInterface(DemoService.class);
+            ref.setUrl("dubbo://127.0.0.1:29581?scope=remote&generic=bean&timeout=3000");
+            DemoService demoService = ref.get();
+            User user = new User();
+            user.setName("zhangsan");
+            List<User> users = new ArrayList<User>();
+            users.add(user);
+            List<User> result = demoService.getUsers(users);
+            Assert.assertEquals(users.size(), result.size());
+            Assert.assertEquals(user.getName(), result.get(0).getName());
+
+            GenericParameter gp = (GenericParameter) reference.get();
+            Assert.assertEquals("getUsers", gp.method);
+            Assert.assertEquals(1, gp.parameterTypes.length);
+            Assert.assertEquals(ReflectUtils.getName(List.class), gp.parameterTypes[0]);
+            Assert.assertEquals(1, gp.arguments.length);
+            Assert.assertTrue(gp.arguments[0] instanceof JavaBeanDescriptor);
+            JavaBeanDescriptor descriptor = (JavaBeanDescriptor) gp.arguments[0];
+            Assert.assertTrue(descriptor.isCollectionType());
+            Assert.assertEquals(ArrayList.class.getName(), descriptor.getClassName());
+            Assert.assertEquals(1, descriptor.propertySize());
+            descriptor = (JavaBeanDescriptor) descriptor.getProperty(0);
+            Assert.assertTrue(descriptor.isBeanType());
+            Assert.assertEquals(User.class.getName(), descriptor.getClassName());
+            Assert.assertEquals(user.getName(), ((JavaBeanDescriptor) descriptor.getProperty("name")).getPrimitiveProperty());
+            Assert.assertNull(demoService.sayName("zhangsan"));
+        } finally {
+            if (ref != null) {
+                ref.destroy();
+            }
+            service.unexport();
+        }
+    }
+
+    protected static class GenericParameter {
+
+        String method;
+
+        String[] parameterTypes;
+
+        Object[] arguments;
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MethodConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MethodConfigTest.java
new file mode 100644
index 0000000..8f7e860
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MethodConfigTest.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+public class MethodConfigTest {
+    @Test
+    public void testName() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setName("hello");
+        assertThat(method.getName(), equalTo("hello"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters, not(hasKey("name")));
+    }
+
+    @Test
+    public void testStat() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setStat(10);
+        assertThat(method.getStat(), equalTo(10));
+    }
+
+    @Test
+    public void testRetry() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setRetry(true);
+        assertThat(method.isRetry(), is(true));
+    }
+
+    @Test
+    public void testReliable() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setReliable(true);
+        assertThat(method.isReliable(), is(true));
+    }
+
+    @Test
+    public void testExecutes() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setExecutes(10);
+        assertThat(method.getExecutes(), equalTo(10));
+    }
+
+    @Test
+    public void testDeprecated() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setDeprecated(true);
+        assertThat(method.getDeprecated(), is(true));
+    }
+
+    @Test
+    public void testArguments() throws Exception {
+        MethodConfig method = new MethodConfig();
+        ArgumentConfig argument = new ArgumentConfig();
+        method.setArguments(Collections.singletonList(argument));
+        assertThat(method.getArguments(), contains(argument));
+        assertThat(method.getArguments(), Matchers.<ArgumentConfig>hasSize(1));
+    }
+
+    @Test
+    public void testSticky() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setSticky(true);
+        assertThat(method.getSticky(), is(true));
+    }
+
+    @Test
+    public void testOnreturn() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOnreturn("on-return-object");
+        assertThat(method.getOnreturn(), equalTo((Object) "on-return-object"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_INSTANCE_KEY, (Object) "on-return-object"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testOnreturnMethod() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOnreturnMethod("on-return-method");
+        assertThat(method.getOnreturnMethod(), equalTo("on-return-method"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_RETURN_METHOD_KEY, (Object) "on-return-method"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testOnthrow() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOnthrow("on-throw-object");
+        assertThat(method.getOnthrow(), equalTo((Object) "on-throw-object"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_THROW_INSTANCE_KEY, (Object) "on-throw-object"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testOnthrowMethod() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOnthrowMethod("on-throw-method");
+        assertThat(method.getOnthrowMethod(), equalTo("on-throw-method"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_THROW_METHOD_KEY, (Object) "on-throw-method"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testOninvoke() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOninvoke("on-invoke-object");
+        assertThat(method.getOninvoke(), equalTo((Object) "on-invoke-object"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testOninvokeMethod() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setOninvokeMethod("on-invoke-method");
+        assertThat(method.getOninvokeMethod(), equalTo("on-invoke-method"));
+        Map<String, Object> attribute = new HashMap<String, Object>();
+        MethodConfig.appendAttributes(attribute, method);
+        assertThat(attribute, hasEntry((Object) Constants.ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MethodConfig.appendParameters(parameters, method);
+        assertThat(parameters.size(), is(0));
+    }
+
+    @Test
+    public void testReturn() throws Exception {
+        MethodConfig method = new MethodConfig();
+        method.setReturn(true);
+        assertThat(method.isReturn(), is(true));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ModuleConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ModuleConfigTest.java
new file mode 100644
index 0000000..c535e99
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ModuleConfigTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+
+public class ModuleConfigTest {
+    @Test(expected = IllegalStateException.class)
+    public void testName1() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        Map<String, String> parameters = new HashMap<String, String>();
+        ModuleConfig.appendParameters(parameters, module);
+    }
+
+    @Test
+    public void testName2() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setName("module-name");
+        assertThat(module.getName(), equalTo("module-name"));
+        assertThat(module.getId(), equalTo("module-name"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ModuleConfig.appendParameters(parameters, module);
+        assertThat(parameters, hasEntry("module", "module-name"));
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setName("module-name");
+        module.setVersion("1.0.0");
+        assertThat(module.getVersion(), equalTo("1.0.0"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        ModuleConfig.appendParameters(parameters, module);
+        assertThat(parameters, hasEntry("module.version", "1.0.0"));
+    }
+
+    @Test
+    public void testOwner() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setOwner("owner");
+        assertThat(module.getOwner(), equalTo("owner"));
+    }
+
+    @Test
+    public void testOrganization() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setOrganization("org");
+        assertThat(module.getOrganization(), equalTo("org"));
+    }
+
+    @Test
+    public void testRegistry() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        RegistryConfig registry = new RegistryConfig();
+        module.setRegistry(registry);
+        assertThat(module.getRegistry(), sameInstance(registry));
+    }
+
+    @Test
+    public void testRegistries() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        RegistryConfig registry = new RegistryConfig();
+        module.setRegistries(Collections.singletonList(registry));
+        assertThat(module.getRegistries(), Matchers.<RegistryConfig>hasSize(1));
+        assertThat(module.getRegistries(), contains(registry));
+    }
+
+    @Test
+    public void testMonitor() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setMonitor("monitor-addr1");
+        assertThat(module.getMonitor().getAddress(), equalTo("monitor-addr1"));
+        module.setMonitor(new MonitorConfig("monitor-addr2"));
+        assertThat(module.getMonitor().getAddress(), equalTo("monitor-addr2"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        ModuleConfig module = new ModuleConfig();
+        module.setDefault(true);
+        assertThat(module.isDefault(), is(true));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MonitorConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MonitorConfigTest.java
new file mode 100644
index 0000000..c666072
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/MonitorConfigTest.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.config;
+
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class MonitorConfigTest {
+    @Test
+    public void testAddress() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setAddress("monitor-addr");
+        assertThat(monitor.getAddress(), equalTo("monitor-addr"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MonitorConfig.appendParameters(parameters, monitor);
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testProtocol() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setProtocol("protocol");
+        assertThat(monitor.getProtocol(), equalTo("protocol"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MonitorConfig.appendParameters(parameters, monitor);
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testUsername() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setUsername("user");
+        assertThat(monitor.getUsername(), equalTo("user"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MonitorConfig.appendParameters(parameters, monitor);
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testPassword() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setPassword("secret");
+        assertThat(monitor.getPassword(), equalTo("secret"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        MonitorConfig.appendParameters(parameters, monitor);
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testGroup() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setGroup("group");
+        assertThat(monitor.getGroup(), equalTo("group"));
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setVersion("1.0.0");
+        assertThat(monitor.getVersion(), equalTo("1.0.0"));
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        Map<String, String> parameters = Collections.singletonMap("k1", "v1");
+        monitor.setParameters(parameters);
+        assertThat(monitor.getParameters(), hasEntry("k1", "v1"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setDefault(true);
+        assertThat(monitor.isDefault(), is(true));
+    }
+
+    @Test
+    public void testInterval() throws Exception {
+        MonitorConfig monitor = new MonitorConfig();
+        monitor.setInterval("100");
+        assertThat(monitor.getInterval(), equalTo("100"));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProtocolConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProtocolConfigTest.java
new file mode 100644
index 0000000..04c5a43
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProtocolConfigTest.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.config.mock.MockProtocol2;
+import org.apache.dubbo.rpc.Protocol;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ProtocolConfigTest {
+
+    @Test
+    public void testDestroy() throws Exception {
+        Protocol protocol = Mockito.mock(Protocol.class);
+        MockProtocol2.delegate = protocol;
+        ProtocolConfig protocolConfig = new ProtocolConfig();
+        protocolConfig.setName("mockprotocol2");
+        protocolConfig.destroy();
+        Mockito.verify(protocol).destroy();
+    }
+
+    @Test
+    public void testName() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setName("name");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProtocolConfig.appendParameters(parameters, protocol);
+        assertThat(protocol.getName(), equalTo("name"));
+        assertThat(protocol.getId(), equalTo("name"));
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testHost() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setHost("host");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProtocolConfig.appendParameters(parameters, protocol);
+        assertThat(protocol.getHost(), equalTo("host"));
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testPort() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setPort(8080);
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProtocolConfig.appendParameters(parameters, protocol);
+        assertThat(protocol.getPort(), equalTo(8080));
+        assertThat(parameters.isEmpty(), is(true));
+    }
+
+    @Test
+    public void testPath() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setContextpath("context-path");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProtocolConfig.appendParameters(parameters, protocol);
+        assertThat(protocol.getPath(), equalTo("context-path"));
+        assertThat(protocol.getContextpath(), equalTo("context-path"));
+        assertThat(parameters.isEmpty(), is(true));
+        protocol.setPath("path");
+        assertThat(protocol.getPath(), equalTo("path"));
+        assertThat(protocol.getContextpath(), equalTo("path"));
+    }
+
+    @Test
+    public void testCorethreads() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setCorethreads(10);
+        assertThat(protocol.getCorethreads(), is(10));
+    }
+
+    @Test
+    public void testThreads() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setThreads(10);
+        assertThat(protocol.getThreads(), is(10));
+    }
+
+    @Test
+    public void testIothreads() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setIothreads(10);
+        assertThat(protocol.getIothreads(), is(10));
+    }
+
+    @Test
+    public void testQueues() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setQueues(10);
+        assertThat(protocol.getQueues(), is(10));
+    }
+
+    @Test
+    public void testAccepts() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setAccepts(10);
+        assertThat(protocol.getAccepts(), is(10));
+    }
+
+    @Test
+    public void testCodec() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setName("dubbo");
+        protocol.setCodec("mockcodec");
+        assertThat(protocol.getCodec(), equalTo("mockcodec"));
+    }
+
+    @Test
+    public void testAccesslog() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setAccesslog("access.log");
+        assertThat(protocol.getAccesslog(), equalTo("access.log"));
+    }
+
+    @Test
+    public void testTelnet() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setTelnet("mocktelnethandler");
+        assertThat(protocol.getTelnet(), equalTo("mocktelnethandler"));
+    }
+
+    @Test
+    public void testRegister() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setRegister(true);
+        assertThat(protocol.isRegister(), is(true));
+    }
+
+    @Test
+    public void testTransporter() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setTransporter("mocktransporter");
+        assertThat(protocol.getTransporter(), equalTo("mocktransporter"));
+    }
+
+    @Test
+    public void testExchanger() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setExchanger("mockexchanger");
+        assertThat(protocol.getExchanger(), equalTo("mockexchanger"));
+    }
+
+    @Test
+    public void testDispatcher() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setDispatcher("mockdispatcher");
+        assertThat(protocol.getDispatcher(), equalTo("mockdispatcher"));
+    }
+
+    @Test
+    public void testNetworker() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setNetworker("networker");
+        assertThat(protocol.getNetworker(), equalTo("networker"));
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setParameters(Collections.singletonMap("k1", "v1"));
+        assertThat(protocol.getParameters(), hasEntry("k1", "v1"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setDefault(true);
+        assertThat(protocol.isDefault(), is(true));
+    }
+
+    @Test
+    public void testKeepAlive() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setKeepAlive(true);
+        assertThat(protocol.getKeepAlive(), is(true));
+    }
+
+    @Test
+    public void testOptimizer() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setOptimizer("optimizer");
+        assertThat(protocol.getOptimizer(), equalTo("optimizer"));
+    }
+
+    @Test
+    public void testExtension() throws Exception {
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setExtension("extension");
+        assertThat(protocol.getExtension(), equalTo("extension"));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProviderConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProviderConfigTest.java
new file mode 100644
index 0000000..18c630a
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ProviderConfigTest.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.junit.Test;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+public class ProviderConfigTest {
+    @Test
+    public void testProtocol() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setProtocol("protocol");
+        assertThat(provider.getProtocol().getName(), equalTo("protocol"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setDefault(true);
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.isDefault(), is(true));
+        assertThat(parameters, not(hasKey("default")));
+    }
+
+    @Test
+    public void testHost() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setHost("demo-host");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.getHost(), equalTo("demo-host"));
+        assertThat(parameters, not(hasKey("host")));
+    }
+
+    @Test
+    public void testPort() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setPort(8080);
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.getPort(), is(8080));
+        assertThat(parameters, not(hasKey("port")));
+    }
+
+    @Test
+    public void testPath() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setPath("/path");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.getPath(), equalTo("/path"));
+        assertThat(provider.getContextpath(), equalTo("/path"));
+        assertThat(parameters, not(hasKey("path")));
+    }
+
+    @Test
+    public void testContextPath() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setContextpath("/context-path");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.getContextpath(), equalTo("/context-path"));
+        assertThat(parameters, not(hasKey("/context-path")));
+    }
+
+    @Test
+    public void testThreadpool() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setThreadpool("mockthreadpool");
+        assertThat(provider.getThreadpool(), equalTo("mockthreadpool"));
+    }
+
+    @Test
+    public void testThreads() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setThreads(10);
+        assertThat(provider.getThreads(), is(10));
+    }
+
+    @Test
+    public void testIothreads() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setIothreads(10);
+        assertThat(provider.getIothreads(), is(10));
+    }
+
+    @Test
+    public void testQueues() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setQueues(10);
+        assertThat(provider.getQueues(), is(10));
+    }
+
+    @Test
+    public void testAccepts() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setAccepts(10);
+        assertThat(provider.getAccepts(), is(10));
+    }
+
+    @Test
+    public void testCharset() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setCharset("utf-8");
+        assertThat(provider.getCharset(), equalTo("utf-8"));
+    }
+
+    @Test
+    public void testPayload() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setPayload(10);
+        assertThat(provider.getPayload(), is(10));
+    }
+
+    @Test
+    public void testBuffer() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setBuffer(10);
+        assertThat(provider.getBuffer(), is(10));
+    }
+
+    @Test
+    public void testServer() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setServer("demo-server");
+        assertThat(provider.getServer(), equalTo("demo-server"));
+    }
+
+    @Test
+    public void testClient() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setClient("client");
+        assertThat(provider.getClient(), equalTo("client"));
+    }
+
+    @Test
+    public void testTelnet() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setTelnet("mocktelnethandler");
+        assertThat(provider.getTelnet(), equalTo("mocktelnethandler"));
+    }
+
+    @Test
+    public void testPrompt() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setPrompt("#");
+        Map<String, String> parameters = new HashMap<String, String>();
+        ProviderConfig.appendParameters(parameters, provider);
+        assertThat(provider.getPrompt(), equalTo("#"));
+        assertThat(parameters, hasEntry("prompt", "%23"));
+    }
+
+    @Test
+    public void testStatus() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setStatus("mockstatuschecker");
+        assertThat(provider.getStatus(), equalTo("mockstatuschecker"));
+    }
+
+    @Test
+    public void testTransporter() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setTransporter("mocktransporter");
+        assertThat(provider.getTransporter(), equalTo("mocktransporter"));
+    }
+
+    @Test
+    public void testExchanger() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setExchanger("mockexchanger");
+        assertThat(provider.getExchanger(), equalTo("mockexchanger"));
+    }
+
+    @Test
+    public void testDispatcher() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setDispatcher("mockdispatcher");
+        assertThat(provider.getDispatcher(), equalTo("mockdispatcher"));
+    }
+
+    @Test
+    public void testNetworker() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setNetworker("networker");
+        assertThat(provider.getNetworker(), equalTo("networker"));
+    }
+
+    @Test
+    public void testWait() throws Exception {
+        ProviderConfig provider = new ProviderConfig();
+        provider.setWait(10);
+        assertThat(provider.getWait(), equalTo(10));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
new file mode 100644
index 0000000..0b1840f
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ReferenceConfigTest.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.config;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReferenceConfigTest {
+
+    @Test
+    public void testInjvm() throws Exception {
+        ApplicationConfig application = new ApplicationConfig();
+        application.setName("test-protocol-random-port");
+
+        RegistryConfig registry = new RegistryConfig();
+        registry.setAddress("multicast://224.5.6.7:1234");
+
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setName("dubbo");
+
+        ServiceConfig<DemoService> demoService;
+        demoService = new ServiceConfig<DemoService>();
+        demoService.setInterface(DemoService.class);
+        demoService.setRef(new DemoServiceImpl());
+        demoService.setApplication(application);
+        demoService.setRegistry(registry);
+        demoService.setProtocol(protocol);
+
+        ReferenceConfig<DemoService> rc = new ReferenceConfig<DemoService>();
+        rc.setApplication(application);
+        rc.setRegistry(registry);
+        rc.setInterface(DemoService.class.getName());
+        rc.setInjvm(false);
+
+        try {
+            demoService.export();
+            rc.get();
+            Assert.assertTrue(!Constants.LOCAL_PROTOCOL.equalsIgnoreCase(
+                    rc.getInvoker().getUrl().getProtocol()));
+        } finally {
+            demoService.unexport();
+        }
+    }
+
+    /**
+     * unit test for dubbo-1765
+     */
+    @Test
+    public void testReferenceRetry() {
+        ApplicationConfig application = new ApplicationConfig();
+        application.setName("test-reference-retry");
+        RegistryConfig registry = new RegistryConfig();
+        registry.setAddress("multicast://224.5.6.7:1234");
+        ProtocolConfig protocol = new ProtocolConfig();
+        protocol.setName("dubbo");
+
+        ReferenceConfig<DemoService> rc = new ReferenceConfig<DemoService>();
+        rc.setApplication(application);
+        rc.setRegistry(registry);
+        rc.setInterface(DemoService.class.getName());
+
+        boolean success = false;
+        DemoService demoService = null;
+        try {
+            demoService = rc.get();
+            success = true;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Assert.assertFalse(success);
+        Assert.assertNull(demoService);
+
+        ServiceConfig<DemoService> sc = new ServiceConfig<DemoService>();
+        sc.setInterface(DemoService.class);
+        sc.setRef(new DemoServiceImpl());
+        sc.setApplication(application);
+        sc.setRegistry(registry);
+        sc.setProtocol(protocol);
+
+        try {
+            sc.export();
+            demoService = rc.get();
+            success = true;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        Assert.assertTrue(success);
+        Assert.assertNotNull(demoService);
+
+    }
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/RegistryConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/RegistryConfigTest.java
new file mode 100644
index 0000000..75c99b1
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/RegistryConfigTest.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.junit.Test;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+
+public class RegistryConfigTest {
+    @Test
+    public void testProtocol() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setProtocol("protocol");
+        assertThat(registry.getProtocol(), equalTo(registry.getProtocol()));
+    }
+
+    @Test
+    public void testAddress() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setAddress("localhost");
+        assertThat(registry.getAddress(), equalTo("localhost"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        RegistryConfig.appendParameters(parameters, registry);
+        assertThat(parameters, not(hasKey("address")));
+    }
+
+    @Test
+    public void testUsername() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setUsername("username");
+        assertThat(registry.getUsername(), equalTo("username"));
+    }
+
+    @Test
+    public void testPassword() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setPassword("password");
+        assertThat(registry.getPassword(), equalTo("password"));
+    }
+
+    @Test
+    public void testWait() throws Exception {
+        try {
+            RegistryConfig registry = new RegistryConfig();
+            registry.setWait(10);
+            assertThat(registry.getWait(), is(10));
+            assertThat(System.getProperty(Constants.SHUTDOWN_WAIT_KEY), equalTo("10"));
+        } finally {
+            System.clearProperty(Constants.SHUTDOWN_TIMEOUT_KEY);
+        }
+    }
+
+    @Test
+    public void testCheck() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setCheck(true);
+        assertThat(registry.isCheck(), is(true));
+    }
+
+    @Test
+    public void testFile() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setFile("file");
+        assertThat(registry.getFile(), equalTo("file"));
+    }
+
+    @Test
+    public void testTransporter() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setTransporter("transporter");
+        assertThat(registry.getTransporter(), equalTo("transporter"));
+    }
+
+    @Test
+    public void testClient() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setClient("client");
+        assertThat(registry.getClient(), equalTo("client"));
+    }
+
+    @Test
+    public void testTimeout() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setTimeout(10);
+        assertThat(registry.getTimeout(), is(10));
+    }
+
+    @Test
+    public void testSession() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setSession(10);
+        assertThat(registry.getSession(), is(10));
+    }
+
+    @Test
+    public void testDynamic() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setDynamic(true);
+        assertThat(registry.isDynamic(), is(true));
+    }
+
+    @Test
+    public void testRegister() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setRegister(true);
+        assertThat(registry.isRegister(), is(true));
+    }
+
+    @Test
+    public void testSubscribe() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setSubscribe(true);
+        assertThat(registry.isSubscribe(), is(true));
+    }
+
+    @Test
+    public void testCluster() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setCluster("cluster");
+        assertThat(registry.getCluster(), equalTo("cluster"));
+    }
+
+    @Test
+    public void testGroup() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setGroup("group");
+        assertThat(registry.getGroup(), equalTo("group"));
+    }
+
+    @Test
+    public void testVersion() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setVersion("1.0.0");
+        assertThat(registry.getVersion(), equalTo("1.0.0"));
+    }
+
+    @Test
+    public void testParameters() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setParameters(Collections.singletonMap("k1", "v1"));
+        assertThat(registry.getParameters(), hasEntry("k1", "v1"));
+        Map<String, String> parameters = new HashMap<String, String>();
+        RegistryConfig.appendParameters(parameters, registry);
+        assertThat(parameters, hasEntry("k1", "v1"));
+    }
+
+    @Test
+    public void testDefault() throws Exception {
+        RegistryConfig registry = new RegistryConfig();
+        registry.setDefault(true);
+        assertThat(registry.isDefault(), is(true));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ServiceConfigTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ServiceConfigTest.java
new file mode 100644
index 0000000..b0a4aef
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/ServiceConfigTest.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.api.Greeting;
+import org.apache.dubbo.config.mock.MockProtocol2;
+import org.apache.dubbo.config.mock.MockRegistryFactory2;
+import org.apache.dubbo.config.mock.TestProxyFactory;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import java.util.Collections;
+
+import static org.apache.dubbo.common.Constants.GENERIC_SERIALIZATION_BEAN;
+import static org.apache.dubbo.common.Constants.GENERIC_SERIALIZATION_DEFAULT;
+import static org.apache.dubbo.common.Constants.GENERIC_SERIALIZATION_NATIVE_JAVA;
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.Matchers.hasEntry;
+import static org.hamcrest.Matchers.hasKey;
+import static org.hamcrest.Matchers.hasSize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.withSettings;
+
+public class ServiceConfigTest {
+    private Protocol protocolDelegate = Mockito.mock(Protocol.class);
+    private Registry registryDelegate = Mockito.mock(Registry.class);
+    private Exporter exporter = Mockito.mock(Exporter.class);
+    private ServiceConfig<DemoServiceImpl> service = new ServiceConfig<DemoServiceImpl>();
+    private ServiceConfig<DemoServiceImpl> service2 = new ServiceConfig<DemoServiceImpl>();
+
+
+    @Before
+    public void setUp() throws Exception {
+        MockProtocol2.delegate = protocolDelegate;
+        MockRegistryFactory2.registry = registryDelegate;
+        Mockito.when(protocolDelegate.export(Mockito.any(Invoker.class))).thenReturn(exporter);
+
+        ApplicationConfig app = new ApplicationConfig("app");
+
+        ProtocolConfig protocolConfig = new ProtocolConfig();
+        protocolConfig.setName("mockprotocol2");
+
+        ProviderConfig provider = new ProviderConfig();
+        provider.setExport(true);
+        provider.setProtocol(protocolConfig);
+
+        RegistryConfig registry = new RegistryConfig();
+        registry.setProtocol("mockprotocol2");
+
+        ArgumentConfig argument = new ArgumentConfig();
+        argument.setIndex(0);
+        argument.setCallback(false);
+
+        MethodConfig method = new MethodConfig();
+        method.setName("echo");
+        method.setArguments(Collections.singletonList(argument));
+
+        service.setProvider(provider);
+        service.setApplication(app);
+        service.setRegistry(registry);
+        service.setInterface(DemoService.class);
+        service.setRef(new DemoServiceImpl());
+        service.setMethods(Collections.singletonList(method));
+
+        service2.setProvider(provider);
+        service2.setApplication(app);
+        service2.setRegistry(registry);
+        service2.setInterface(DemoService.class);
+        service2.setRef(new DemoServiceImpl());
+        service2.setMethods(Collections.singletonList(method));
+        service2.setProxy("testproxyfactory");
+    }
+
+    @Test
+    public void testExport() throws Exception {
+        service.export();
+
+        assertThat(service.getExportedUrls(), hasSize(1));
+        URL url = service.toUrl();
+        assertThat(url.getProtocol(), equalTo("mockprotocol2"));
+        assertThat(url.getPath(), equalTo(DemoService.class.getName()));
+        assertThat(url.getParameters(), hasEntry(Constants.ANYHOST_KEY, "true"));
+        assertThat(url.getParameters(), hasEntry(Constants.APPLICATION_KEY, "app"));
+        assertThat(url.getParameters(), hasKey(Constants.BIND_IP_KEY));
+        assertThat(url.getParameters(), hasKey(Constants.BIND_PORT_KEY));
+        assertThat(url.getParameters(), hasEntry(Constants.DEFAULT_KEY + "." + Constants.EXPORT_KEY, "true"));
+        assertThat(url.getParameters(), hasEntry(Constants.EXPORT_KEY, "true"));
+        assertThat(url.getParameters(), hasEntry("echo.0.callback", "false"));
+        assertThat(url.getParameters(), hasEntry(Constants.GENERIC_KEY, "false"));
+        assertThat(url.getParameters(), hasEntry(Constants.INTERFACE_KEY, DemoService.class.getName()));
+        assertThat(url.getParameters(), hasKey(Constants.METHODS_KEY));
+        assertThat(url.getParameters().get(Constants.METHODS_KEY), containsString("echo"));
+        assertThat(url.getParameters(), hasEntry(Constants.SIDE_KEY, Constants.PROVIDER));
+        Mockito.verify(protocolDelegate).export(Mockito.any(Invoker.class));
+    }
+
+    @Test
+    public void testProxy() throws Exception {
+        service2.export();
+
+        assertThat(service2.getExportedUrls(), hasSize(1));
+        assertEquals(2, TestProxyFactory.count); // local injvm and registry protocol, so expected is 2
+    }
+
+    @Test
+    @Ignore("cannot pass in travis")
+    public void testUnexport() throws Exception {
+        System.setProperty(Constants.SHUTDOWN_WAIT_KEY, "0");
+        try {
+            service.export();
+            service.unexport();
+            Thread.sleep(1000);
+            Mockito.verify(exporter, Mockito.atLeastOnce()).unexport();
+        } finally {
+            System.clearProperty(Constants.SHUTDOWN_TIMEOUT_KEY);
+        }
+    }
+
+    @Test
+    public void testInterfaceClass() throws Exception {
+        ServiceConfig<Greeting> service = new ServiceConfig<Greeting>();
+        service.setInterface(Greeting.class.getName());
+        service.setRef(Mockito.mock(Greeting.class));
+        assertThat(service.getInterfaceClass() == Greeting.class, is(true));
+        service = new ServiceConfig<Greeting>();
+        service.setRef(Mockito.mock(Greeting.class, withSettings().extraInterfaces(GenericService.class)));
+        assertThat(service.getInterfaceClass() == GenericService.class, is(true));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testInterface1() throws Exception {
+        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
+        service.setInterface(DemoServiceImpl.class);
+    }
+
+    @Test
+    public void testInterface2() throws Exception {
+        ServiceConfig<DemoService> service = new ServiceConfig<DemoService>();
+        service.setInterface(DemoService.class);
+        assertThat(service.getInterface(), equalTo(DemoService.class.getName()));
+    }
+
+    @Test
+    public void testProvider() throws Exception {
+        ServiceConfig service = new ServiceConfig();
+        ProviderConfig provider = new ProviderConfig();
+        service.setProvider(provider);
+        assertThat(service.getProvider(), is(provider));
+    }
+
+    @Test
+    public void testGeneric1() throws Exception {
+        ServiceConfig service = new ServiceConfig();
+        service.setGeneric(GENERIC_SERIALIZATION_DEFAULT);
+        assertThat(service.getGeneric(), equalTo(GENERIC_SERIALIZATION_DEFAULT));
+        service.setGeneric(GENERIC_SERIALIZATION_NATIVE_JAVA);
+        assertThat(service.getGeneric(), equalTo(GENERIC_SERIALIZATION_NATIVE_JAVA));
+        service.setGeneric(GENERIC_SERIALIZATION_BEAN);
+        assertThat(service.getGeneric(), equalTo(GENERIC_SERIALIZATION_BEAN));
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testGeneric2() throws Exception {
+        ServiceConfig service = new ServiceConfig();
+        service.setGeneric("illegal");
+    }
+
+    @Test
+    public void testUniqueServiceName() throws Exception {
+        ServiceConfig<Greeting> service = new ServiceConfig<Greeting>();
+        service.setGroup("dubbo");
+        service.setInterface(Greeting.class);
+        service.setVersion("1.0.0");
+        assertThat(service.getUniqueServiceName(), equalTo("dubbo/" + Greeting.class.getName() + ":1.0.0"));
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Box.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Box.java
new file mode 100644
index 0000000..e63f924
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Box.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.api;
+
+public interface Box {
+
+    String getName();
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoException.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoException.java
new file mode 100644
index 0000000..2f32c3f
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoException.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.config.api;
+
+/**
+ * DemoException
+ */
+public class DemoException extends Exception {
+
+    private static final long serialVersionUID = -8213943026163641747L;
+
+    public DemoException() {
+        super();
+    }
+
+    public DemoException(String message, Throwable cause) {
+        super(message, cause);
+    }
+
+    public DemoException(String message) {
+        super(message);
+    }
+
+    public DemoException(Throwable cause) {
+        super(cause);
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoService.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoService.java
new file mode 100644
index 0000000..c5bc722
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/DemoService.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.api;
+
+import java.util.List;
+
+
+/**
+ * DemoService
+ */
+public interface DemoService {
+
+    String sayName(String name);
+
+    Box getBox();
+
+    void throwDemoException() throws DemoException;
+
+    List<User> getUsers(List<User> users);
+
+    int echo(int i);
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Greeting.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Greeting.java
new file mode 100644
index 0000000..c2afa98
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/Greeting.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.api;
+
+import org.apache.dubbo.common.extension.SPI;
+
+@SPI
+public interface Greeting {
+    String hello();
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/User.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/User.java
new file mode 100644
index 0000000..5e55cbb
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/api/User.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.config.api;
+
+import java.io.Serializable;
+
+/**
+ * User
+ */
+public class User implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String name;
+
+    public User() {
+    }
+
+    public User(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public int hashCode() {
+        return name == null ? -1 : name.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof User)) {
+            return false;
+        }
+        User other = (User) obj;
+        if (this == other) {
+            return true;
+        }
+        if (name != null && other.name != null) {
+            return name.equals(other.name);
+        }
+        return false;
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheService.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheService.java
new file mode 100644
index 0000000..7696b24
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheService.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.cache;
+
+/**
+ * ValidationService
+ */
+public interface CacheService {
+
+    String findCache(String id);
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheServiceImpl.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheServiceImpl.java
new file mode 100644
index 0000000..14e9ee7
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheServiceImpl.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.cache;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * ValidationServiceImpl
+ */
+public class CacheServiceImpl implements CacheService {
+
+    private final AtomicInteger i = new AtomicInteger();
+
+    public String findCache(String id) {
+        return "request: " + id + ", response: " + i.getAndIncrement();
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheTest.java
new file mode 100644
index 0000000..6c79b8e
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/cache/CacheTest.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.cache;
+
+import junit.framework.TestCase;
+import org.apache.dubbo.cache.Cache;
+import org.apache.dubbo.cache.CacheFactory;
+import org.apache.dubbo.cache.support.threadlocal.ThreadLocalCache;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.RpcInvocation;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * CacheTest
+ */
+public class CacheTest extends TestCase {
+
+    private void testCache(String type) throws Exception {
+        ServiceConfig<CacheService> service = new ServiceConfig<CacheService>();
+        service.setApplication(new ApplicationConfig("cache-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("injvm"));
+        service.setInterface(CacheService.class.getName());
+        service.setRef(new CacheServiceImpl());
+        service.export();
+        try {
+            ReferenceConfig<CacheService> reference = new ReferenceConfig<CacheService>();
+            reference.setApplication(new ApplicationConfig("cache-consumer"));
+            reference.setInterface(CacheService.class);
+            reference.setUrl("injvm://127.0.0.1?scope=remote&cache=true");
+
+            MethodConfig method = new MethodConfig();
+            method.setName("findCache");
+            method.setCache(type);
+            reference.setMethods(Arrays.asList(method));
+
+            CacheService cacheService = reference.get();
+            try {
+                // verify cache, same result is returned for multiple invocations (in fact, the return value increases
+                // on every invocation on the server side)
+                String fix = null;
+                for (int i = 0; i < 3; i++) {
+                    String result = cacheService.findCache("0");
+                    assertTrue(fix == null || fix.equals(result));
+                    fix = result;
+                    Thread.sleep(100);
+                }
+
+                if ("lru".equals(type)) {
+                    // default cache.size is 1000 for LRU, should have cache expired if invoke more than 1001 times
+                    for (int n = 0; n < 1001; n++) {
+                        String pre = null;
+                        for (int i = 0; i < 10; i++) {
+                            String result = cacheService.findCache(String.valueOf(n));
+                            assertTrue(pre == null || pre.equals(result));
+                            pre = result;
+                        }
+                    }
+
+                    // verify if the first cache item is expired in LRU cache
+                    String result = cacheService.findCache("0");
+                    assertFalse(fix == null || fix.equals(result));
+                }
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testCache() throws Exception {
+        testCache("lru");
+        testCache("threadlocal");
+    }
+
+    @Test
+    public void testCacheProvider() throws Exception {
+        CacheFactory cacheFactory = ExtensionLoader.getExtensionLoader(CacheFactory.class).getAdaptiveExtension();
+
+        Map<String, String> parameters = new HashMap<String, String>();
+        parameters.put("findCache.cache", "threadlocal");
+        URL url = new URL("dubbo", "127.0.0.1", 29582, "org.apache.dubbo.config.cache.CacheService", parameters);
+
+        Invocation invocation = new RpcInvocation("findCache", new Class[]{String.class}, new String[]{"0"}, null, null);
+
+        Cache cache = cacheFactory.getCache(url, invocation);
+        assertTrue(cache instanceof ThreadLocalCache);
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionByAnnotation.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionByAnnotation.java
new file mode 100644
index 0000000..8fd477a
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionByAnnotation.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.consumer;
+
+import org.apache.dubbo.config.api.DemoService;
+import org.springframework.beans.factory.annotation.Autowired;
+
+/**
+ * DemoAction
+ */
+public class DemoActionByAnnotation {
+
+    @Autowired
+    private DemoService demoService;
+
+    public DemoService getDemoService() {
+        return demoService;
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionBySetter.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionBySetter.java
new file mode 100644
index 0000000..0606e26
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoActionBySetter.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.consumer;
+
+import org.apache.dubbo.config.api.DemoService;
+
+/**
+ * DemoAction
+ */
+public class DemoActionBySetter {
+
+    private DemoService demoService;
+
+    public DemoService getDemoService() {
+        return demoService;
+    }
+
+    public void setDemoService(DemoService demoService) {
+        this.demoService = demoService;
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoInterceptor.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoInterceptor.java
new file mode 100644
index 0000000..46d7e9a
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/consumer/DemoInterceptor.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.consumer;
+
+import org.aopalliance.intercept.MethodInterceptor;
+import org.aopalliance.intercept.MethodInvocation;
+
+/**
+ * DemoInterceptor
+ */
+public class DemoInterceptor implements MethodInterceptor {
+
+    public Object invoke(MethodInvocation invocation) throws Throwable {
+        return "aop:" + invocation.proceed();
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/invoker/DelegateProviderMetaDataInvokerTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/invoker/DelegateProviderMetaDataInvokerTest.java
new file mode 100644
index 0000000..7630842
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/invoker/DelegateProviderMetaDataInvokerTest.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.config.invoker;
+
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.api.Greeting;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import static org.hamcrest.Matchers.sameInstance;
+import static org.junit.Assert.assertThat;
+
+public class DelegateProviderMetaDataInvokerTest {
+    private ServiceConfig service;
+    private Invoker<Greeting> invoker;
+
+    @Before
+    public void setUp() throws Exception {
+        service = Mockito.mock(ServiceConfig.class);
+        invoker = Mockito.mock(Invoker.class);
+    }
+
+    @Test
+    public void testDelegate() throws Exception {
+        DelegateProviderMetaDataInvoker<Greeting> delegate =
+                new DelegateProviderMetaDataInvoker<Greeting>(invoker, service);
+        delegate.getInterface();
+        Mockito.verify(invoker).getInterface();
+        delegate.getUrl();
+        Mockito.verify(invoker).getUrl();
+        delegate.isAvailable();
+        Mockito.verify(invoker).isAvailable();
+        Invocation invocation = Mockito.mock(Invocation.class);
+        delegate.invoke(invocation);
+        Mockito.verify(invoker).invoke(invocation);
+        delegate.destroy();
+        Mockito.verify(invoker).destroy();
+        assertThat(delegate.getMetadata(), sameInstance(service));
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal1.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal1.java
new file mode 100644
index 0000000..f3d5ee5
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal1.java
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+public class GreetingLocal1 {
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal2.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal2.java
new file mode 100644
index 0000000..8cae406
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal2.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.config.api.Greeting;
+
+public class GreetingLocal2 implements Greeting {
+    @Override
+    public String hello() {
+        return "local";
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal3.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal3.java
new file mode 100644
index 0000000..9b14ac6
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingLocal3.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.config.api.Greeting;
+
+public class GreetingLocal3 implements Greeting {
+    private Greeting greeting;
+
+    public GreetingLocal3(Greeting greeting) {
+        this.greeting = greeting;
+    }
+
+    @Override
+    public String hello() {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock1.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock1.java
new file mode 100644
index 0000000..8bfe6e6
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock1.java
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+public class GreetingMock1 {
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock2.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock2.java
new file mode 100644
index 0000000..429bff4
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/GreetingMock2.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.config.api.Greeting;
+
+public class GreetingMock2 implements Greeting {
+    private GreetingMock2() {
+    }
+
+    @Override
+    public String hello() {
+        return "mock";
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCluster.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCluster.java
new file mode 100644
index 0000000..39bf974
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCluster.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.Directory;
+
+public class MockCluster implements Cluster {
+    @Override
+    public <T> Invoker<T> join(Directory<T> directory) throws RpcException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCodec.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCodec.java
new file mode 100644
index 0000000..c1aac42
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockCodec.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.Codec;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+public class MockCodec implements Codec {
+    @Override
+    public void encode(Channel channel, OutputStream output, Object message) throws IOException {
+
+    }
+
+    @Override
+    public Object decode(Channel channel, InputStream input) throws IOException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockDispatcher.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockDispatcher.java
new file mode 100644
index 0000000..32fffca
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockDispatcher.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.ChannelHandler;
+import org.apache.dubbo.remoting.Dispatcher;
+
+public class MockDispatcher implements Dispatcher {
+    @Override
+    public ChannelHandler dispatch(ChannelHandler handler, URL url) {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExchanger.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExchanger.java
new file mode 100644
index 0000000..fccfd23
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExchanger.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.exchange.ExchangeClient;
+import org.apache.dubbo.remoting.exchange.ExchangeHandler;
+import org.apache.dubbo.remoting.exchange.ExchangeServer;
+import org.apache.dubbo.remoting.exchange.Exchanger;
+
+public class MockExchanger implements Exchanger {
+    @Override
+    public ExchangeServer bind(URL url, ExchangeHandler handler) throws RemotingException {
+        return null;
+    }
+
+    @Override
+    public ExchangeClient connect(URL url, ExchangeHandler handler) throws RemotingException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExporterListener.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExporterListener.java
new file mode 100644
index 0000000..b93f44c
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockExporterListener.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.ExporterListener;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockExporterListener implements ExporterListener {
+    @Override
+    public void exported(Exporter<?> exporter) throws RpcException {
+
+    }
+
+    @Override
+    public void unexported(Exporter<?> exporter) {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockFilter.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockFilter.java
new file mode 100644
index 0000000..d51f123
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockFilter.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockFilter implements Filter {
+    @Override
+    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockInvokerListener.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockInvokerListener.java
new file mode 100644
index 0000000..c929e54
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockInvokerListener.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.InvokerListener;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockInvokerListener implements InvokerListener {
+    @Override
+    public void referred(Invoker<?> invoker) throws RpcException {
+
+    }
+
+    @Override
+    public void destroyed(Invoker<?> invoker) {
+
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockLoadBalance.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockLoadBalance.java
new file mode 100644
index 0000000..377f328
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockLoadBalance.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import java.util.List;
+
+public class MockLoadBalance implements LoadBalance {
+    @Override
+    public <T> Invoker<T> select(List<Invoker<T>> invokers, URL url, Invocation invocation) throws RpcException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol.java
new file mode 100644
index 0000000..f4cb8ce
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.Invocation;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.Result;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockProtocol implements Protocol {
+
+    /* (non-Javadoc)
+     * @see org.apache.dubbo.rpc.Protocol#getDefaultPort()
+     */
+    @Override
+    public int getDefaultPort() {
+
+        return 0;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.dubbo.rpc.Protocol#export(org.apache.dubbo.rpc.Invoker)
+     */
+    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
+        return null;
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.dubbo.rpc.Protocol#refer(java.lang.Class, org.apache.dubbo.common.URL)
+     */
+    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
+
+        final URL u = url;
+
+        return new Invoker<T>() {
+            @Override
+            public Class<T> getInterface() {
+                return null;
+            }
+
+            public URL getUrl() {
+                return u;
+            }
+
+            @Override
+            public boolean isAvailable() {
+                return true;
+            }
+
+            public Result invoke(Invocation invocation) throws RpcException {
+                return null;
+            }
+
+            @Override
+            public void destroy() {
+
+            }
+        };
+    }
+
+    /* (non-Javadoc)
+     * @see org.apache.dubbo.rpc.Protocol#destroy()
+     */
+    @Override
+    public void destroy() {
+
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol2.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol2.java
new file mode 100644
index 0000000..91653d4
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProtocol2.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockProtocol2 implements Protocol {
+    public static Protocol delegate;
+
+    @Override
+    public int getDefaultPort() {
+        return delegate.getDefaultPort();
+    }
+
+    @Override
+    public <T> Exporter<T> export(Invoker<T> invoker) throws RpcException {
+        return delegate.export(invoker);
+    }
+
+    @Override
+    public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
+        return delegate.refer(type, url);
+    }
+
+    @Override
+    public void destroy() {
+        delegate.destroy();
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProxyFactory.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProxyFactory.java
new file mode 100644
index 0000000..49f05d8
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockProxyFactory.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.RpcException;
+
+public class MockProxyFactory implements ProxyFactory {
+    @Override
+    public <T> T getProxy(Invoker<T> invoker) throws RpcException {
+        return null;
+    }
+
+    @Override
+    public <T> T getProxy(Invoker<T> invoker, boolean generic) throws RpcException {
+        return null;
+    }
+
+    @Override
+    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistry.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistry.java
new file mode 100644
index 0000000..5632887
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistry.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.config.mock;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.NotifyListener;
+import org.apache.dubbo.registry.Registry;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * TODO Comment of MockRegistry
+ */
+public class MockRegistry implements Registry {
+
+    static URL subscribedUrl = new URL("null", "0.0.0.0", 0);
+
+    public static URL getSubscribedUrl() {
+        return subscribedUrl;
+    }
+
+    /*
+     * @see org.apache.dubbo.common.Node#getUrl()
+     */
+    public URL getUrl() {
+        return null;
+    }
+
+    /*
+     * @see org.apache.dubbo.common.Node#isAvailable()
+     */
+    @Override
+    public boolean isAvailable() {
+        return true;
+    }
+
+    /*
+     * @see org.apache.dubbo.common.Node#destroy()
+     */
+    @Override
+    public void destroy() {
+
+    }
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryService#register(org.apache.dubbo.common.URL)
+     */
+    @Override
+    public void register(URL url) {
+
+    }
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryService#unregister(org.apache.dubbo.common.URL)
+     */
+    @Override
+    public void unregister(URL url) {
+
+    }
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryService#subscribe(org.apache.dubbo.common.URL, org.apache.dubbo.registry.NotifyListener)
+     */
+    @Override
+    public void subscribe(URL url, NotifyListener listener) {
+        this.subscribedUrl = url;
+        List<URL> urls = new ArrayList<URL>();
+
+        urls.add(url.setProtocol("mockprotocol")
+                .removeParameter(Constants.CATEGORY_KEY)
+                .addParameter(Constants.METHODS_KEY, "sayHello"));
+
+        listener.notify(urls);
+    }
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryService#unsubscribe(org.apache.dubbo.common.URL, org.apache.dubbo.registry.NotifyListener)
+     */
+    @Override
+    public void unsubscribe(URL url, NotifyListener listener) {
+
+    }
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryService#lookup(org.apache.dubbo.common.URL)
+     */
+    @Override
+    public List<URL> lookup(URL url) {
+        return null;
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory.java
new file mode 100644
index 0000000..1e0e6e7
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.registry.RegistryFactory;
+
+/**
+ * TODO Comment of MockRegistryFactory
+ */
+public class MockRegistryFactory implements RegistryFactory {
+
+    /*
+     * @see org.apache.dubbo.registry.RegistryFactory#getRegistry(org.apache.dubbo.common.URL)
+     */
+    @Override
+    public Registry getRegistry(URL url) {
+
+        return new MockRegistry();
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory2.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory2.java
new file mode 100644
index 0000000..2ab3da8
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockRegistryFactory2.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.registry.Registry;
+import org.apache.dubbo.registry.RegistryFactory;
+
+public class MockRegistryFactory2 implements RegistryFactory {
+    public static Registry registry;
+
+    @Override
+    public Registry getRegistry(URL url) {
+        return registry;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockStatusChecker.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockStatusChecker.java
new file mode 100644
index 0000000..e144c7b
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockStatusChecker.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.status.Status;
+import org.apache.dubbo.common.status.StatusChecker;
+
+public class MockStatusChecker implements StatusChecker {
+    @Override
+    public Status check() {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTelnetHandler.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTelnetHandler.java
new file mode 100644
index 0000000..a08160f
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTelnetHandler.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.remoting.Channel;
+import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.telnet.TelnetHandler;
+
+public class MockTelnetHandler implements TelnetHandler {
+    @Override
+    public String telnet(Channel channel, String message) throws RemotingException {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockThreadPool.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockThreadPool.java
new file mode 100644
index 0000000..fe96689
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockThreadPool.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.threadpool.ThreadPool;
+
+import java.util.concurrent.Executor;
+
+public class MockThreadPool implements ThreadPool {
+    @Override
+    public Executor getExecutor(URL url) {
+        return null;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTransporter.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTransporter.java
new file mode 100644
index 0000000..08d005d
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/MockTransporter.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.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.remoting.ChannelHandler;
+import org.apache.dubbo.remoting.Client;
+import org.apache.dubbo.remoting.RemotingException;
+import org.apache.dubbo.remoting.Server;
+import org.apache.dubbo.remoting.Transporter;
+import org.mockito.Mockito;
+
+public class MockTransporter implements Transporter {
+    private Server server = Mockito.mock(Server.class);
+    private Client client = Mockito.mock(Client.class);
+
+    @Override
+    public Server bind(URL url, ChannelHandler handler) throws RemotingException {
+        return server;
+    }
+
+    @Override
+    public Client connect(URL url, ChannelHandler handler) throws RemotingException {
+        return client;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/TestProxyFactory.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/TestProxyFactory.java
new file mode 100644
index 0000000..fe22bd1
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/mock/TestProxyFactory.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dubbo.config.mock;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.proxy.jdk.JdkProxyFactory;
+
+public class TestProxyFactory extends JdkProxyFactory {
+    public static int count = 0;
+
+    @Override
+    public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
+        count++;
+        return super.getInvoker(proxy, type, url);
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/provider/impl/DemoServiceImpl.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/provider/impl/DemoServiceImpl.java
new file mode 100644
index 0000000..d81269e
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/provider/impl/DemoServiceImpl.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.provider.impl;
+
+import org.apache.dubbo.config.api.Box;
+import org.apache.dubbo.config.api.DemoException;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.api.User;
+
+import java.util.List;
+
+/**
+ * DemoServiceImpl
+ */
+public class DemoServiceImpl implements DemoService {
+
+    public String sayName(String name) {
+        return "say:" + name;
+    }
+
+    public Box getBox() {
+        return null;
+    }
+
+    public void throwDemoException() throws DemoException {
+        throw new DemoException("DemoServiceImpl");
+    }
+
+    public List<User> getUsers(List<User> users) {
+        return users;
+    }
+
+    public int echo(int i) {
+        return i;
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
new file mode 100644
index 0000000..e2ebd63
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.url;
+
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+public class ExporterSideConfigUrlTest extends UrlTestBase {
+
+    private static final Logger log = LoggerFactory.getLogger(ExporterSideConfigUrlTest.class);
+
+    // ======================================================
+    //   tests start
+    // ======================================================  
+    @BeforeClass
+    public static void start() {
+    }
+
+
+    @Before
+    public void setUp() {
+        initServConf();
+    }
+
+    @After()
+    public void teardown() {
+    }
+
+    @Test
+    public void exporterMethodConfigUrlTest() {
+        verifyExporterUrlGeneration(methodConfForService, methodConfForServiceTable);
+    }
+
+    @Test
+    public void exporterServiceConfigUrlTest() {
+        verifyExporterUrlGeneration(servConf, servConfTable);
+    }
+
+    @Test
+    public void exporterProviderConfigUrlTest() {
+
+        verifyExporterUrlGeneration(provConf, provConfTable);
+    }
+
+    @Test
+    public void exporterRegistryConfigUrlTest() {
+
+        //verifyExporterUrlGeneration(regConfForService, regConfForServiceTable);
+    }
+
+
+    protected <T> void verifyExporterUrlGeneration(T config, Object[][] dataTable) {
+
+        // 1. fill corresponding config with data
+        ////////////////////////////////////////////////////////////
+        fillConfigs(config, dataTable, TESTVALUE1);
+
+        // 2. export service and get url parameter string from db
+        ////////////////////////////////////////////////////////////
+        servConf.export();
+        String paramStringFromDb = getProviderParamString();
+        try {
+            paramStringFromDb = URLDecoder.decode(paramStringFromDb, "UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            // impossible
+        }
+
+
+        assertUrlStringWithLocalTable(paramStringFromDb, dataTable, config.getClass().getName(), TESTVALUE1);
+
+
+        // 4. unexport service
+        ////////////////////////////////////////////////////////////
+        servConf.unexport();
+    }
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
new file mode 100644
index 0000000..a7b5842
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/InvokerSideConfigUrlTest.java
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.url;
+
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.mock.MockRegistry;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+
+public class InvokerSideConfigUrlTest extends UrlTestBase {
+    private static final Logger log = LoggerFactory.getLogger(InvokerSideConfigUrlTest.class);
+
+    // ======================================================
+    //   invoker related data preparing
+    // ======================================================  
+    private ApplicationConfig appConfForConsumer;
+    private ApplicationConfig appConfForReference;
+    private RegistryConfig regConfForConsumer;
+    private RegistryConfig regConfForReference;
+    private MethodConfig methodConfForReference;
+    private ConsumerConfig consumerConf;
+    private ReferenceConfig<DemoService> refConf;
+
+    private Object appConfForConsumerTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+
+    private Object appConfForReferenceTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+
+    private Object regConfForConsumerTable[][] = {
+//            {"timeout", "registry.timeout", "int", 5000, 9000, "", "", "", "", ""}, 
+//            {"file", "registry.file", "string", "", "regConfForServiceTable.log", "", "", "", "", ""}, 
+//            {"wait", "registry.wait", "int", 0, 9000, "", "", "", "", ""}, 
+//            {"transport", "registry.transporter", "string", "netty", "mina", "", "", "", "", ""}, 
+            {"subscribe", "subscribe", "boolean", true, false, "", "", "", "", ""},
+            {"dynamic", "dynamic", "boolean", true, false, "", "", "", "", ""},
+    };
+
+    private Object regConfForReferenceTable[][] = {
+            {"timeout", "registry.timeout", "int", 5000, 9000, "", "", "", "", ""},
+            {"file", "registry.file", "string", "", "regConfForServiceTable.log", "", "", "", "", ""},
+            {"wait", "registry.wait", "int", 0, 9000, "", "", "", "", ""},
+            {"transport", "registry.transporter", "string", "netty", "mina", "", "", "", "", ""},
+            {"subscribe", "subscribe", "boolean", true, false, "", "", "", "", ""},
+            {"dynamic", "dynamic", "boolean", true, false, "", "", "", "", ""},
+    };
+
+    private Object methodConfForReferenceTable[][] = {
+            {"actives", "eatTiger.actives", "int", 0, 90, "", "", "", "", ""},
+            {"executes", "eatTiger.executes", "int", 0, 90, "", "", "", "", ""},
+            {"deprecated", "eatTiger.deprecated", "boolean", false, true, "", "", "", "", ""},
+            {"async", "eatTiger.async", "boolean", false, true, "", "", "", "", ""},
+            {"timeout", "eatTiger.timeout", "int", 0, 90, "", "", "", "", ""},
+    };
+
+    private Object refConfTable[][] = {
+//            {"version", "version", "string", "0.0.0", "1.2.3", "", "", "", "", ""}, 
+//            {"group", "group", "string", "", "HaominTest", "", "", "", "", ""}, 
+
+//            {"delay", "delay", "int", 0, 5, "", "", "", "", ""}, // not boolean 
+            {"timeout", "timeout", "int", 5000, 3000, "", "", "", "", ""},
+            {"retries", "retries", "int", 2, 5, "", "", "", "", ""},
+            {"connections", "connections", "boolean", 100, 20, "", "", "", "", ""},
+            {"loadbalance", "loadbalance", "string", "random", "roundrobin", "leastactive", "", "", ""},
+            {"async", "async", "boolean", false, true, "", "", "", "", ""},
+            //excluded = true
+//            {"generic", "generic", "boolean", false, true, "", "", "", "", ""},  
+            {"check", "check", "boolean", false, true, "", "", "", "", ""},
+            //{"local", "local", "string", "false", "HelloServiceLocal", "true", "", "", "", ""}, 
+            //{"local", "local", "string", "false", "true", "", "", "", "", ""}, 
+            //{"mock", "mock", "string", "false", "dubbo.test.HelloServiceMock", "true", "", "", "", ""}, 
+            {"mock", "mock", "string", "false", "false", "", "", "", "", ""},
+            {"proxy", "proxy", "boolean", "javassist", "jdk", "", "", "", "", ""},
+            {"client", "client", "string", "netty", "mina", "", "", "", "", ""},
+            {"client", "client", "string", "netty", "mina", "", "", "", "", ""},
+            {"owner", "owner", "string", "", "haomin,ludvik", "", "", "", "", ""},
+            {"actives", "actives", "int", 0, 30, "", "", "", "", ""},
+            {"cluster", "cluster", "string", "failover", "failfast", "failsafe", "failback", "forking", "", ""},
+            //excluded = true
+//            {"filter", "service.filter", "string", "default", "-generic", "", "", "", "", ""}, 
+            //excluded = true
+//            {"listener", "exporter.listener", "string", "default", "-deprecated", "", "", "", "", ""}, 
+            //{"", "", "", "", "", "", "", "", "", ""}, 
+    };
+
+    private Object consumerConfTable[][] = {
+            {"timeout", "default.timeout", "int", 5000, 8000, "", "", "", "", ""},
+            {"retries", "default.retries", "int", 2, 5, "", "", "", "", ""},
+            {"loadbalance", "default.loadbalance", "string", "random", "leastactive", "", "", "", "", ""},
+            {"async", "default.async", "boolean", false, true, "", "", "", "", ""},
+            {"connections", "default.connections", "int", 100, 5, "", "", "", "", ""},
+//            {"generic", "generic", "boolean", false, false, "", "", "", "", ""}, 
+            {"check", "check", "boolean", true, false, "", "", "", "", ""},
+            {"proxy", "proxy", "string", "javassist", "jdk", "javassist", "", "", "", ""},
+            {"owner", "owner", "string", "", "haomin", "", "", "", "", ""},
+            {"actives", "default.actives", "int", 0, 5, "", "", "", "", ""},
+            {"cluster", "default.cluster", "string", "failover", "forking", "", "", "", "", ""},
+            {"filter", "", "string", "", "", "", "", "", "", ""},
+            {"listener", "", "string", "", "", "", "", "", "", ""},
+//            {"", "", "", "", "", "", "", "", "", ""}, 
+    };
+
+    // ======================================================
+    //   test Start
+    // ====================================================== 
+
+    @BeforeClass
+    public static void start() {
+        //RegistryController.startRegistryIfAbsence(1);
+    }
+
+
+    @Before
+    public void setUp() {
+        initServConf();
+        initRefConf();
+    }
+
+    @After()
+    public void teardown() {
+        //RegistryServer.reloadCache();
+    }
+
+
+    @Test
+    public void consumerConfUrlTest() {
+        verifyInvokerUrlGeneration(consumerConf, consumerConfTable);
+    }
+
+    @Test
+    public void refConfUrlTest() {
+        verifyInvokerUrlGeneration(refConf, refConfTable);
+    }
+
+    @Ignore("parameter on register center will not be merged any longer with query parameter request from the consumer")
+    @Test
+    public void regConfForConsumerUrlTest() {
+        verifyInvokerUrlGeneration(regConfForConsumer, regConfForConsumerTable);
+    }
+
+    // ======================================================
+    //   private helper
+    // ====================================================== 
+    private void initRefConf() {
+
+        appConfForConsumer = new ApplicationConfig();
+        appConfForReference = new ApplicationConfig();
+        regConfForConsumer = new RegistryConfig();
+        regConfForReference = new RegistryConfig();
+        methodConfForReference = new MethodConfig();
+
+        refConf = new ReferenceConfig<DemoService>();
+        consumerConf = new ConsumerConfig();
+
+        methodConfForReference.setName("sayName");
+        regConfForReference.setAddress("127.0.0.1:9090");
+        regConfForReference.setProtocol("mockregistry");
+        appConfForReference.setName("ConfigTests");
+        refConf.setInterface("org.apache.dubbo.config.api.DemoService");
+
+        refConf.setApplication(appConfForReference);
+        consumerConf.setApplication(appConfForConsumer);
+
+        refConf.setRegistry(regConfForReference);
+        consumerConf.setRegistry(regConfForConsumer);
+
+        refConf.setConsumer(consumerConf);
+
+        refConf.setMethods(Arrays.asList(new MethodConfig[]{methodConfForReference}));
+
+        refConf.setScope(Constants.SCOPE_REMOTE);
+    }
+
+    private <T> void verifyInvokerUrlGeneration(T config, Object[][] dataTable) {
+        servConf.export();
+
+        fillConfigs(config, dataTable, TESTVALUE1);
+        refConf.get();
+
+        String subScribedUrlStr = getSubscribedUrlString();
+
+        System.out.println("url string=========:" + subScribedUrlStr);
+        String configName = config.getClass().getName();
+        int column = TESTVALUE1;
+
+        assertUrlStringWithLocalTable(subScribedUrlStr, dataTable, configName, column);
+
+        try {
+            refConf.destroy();
+        } catch (Exception e) {
+        }
+    }
+
+    private String getSubscribedUrlString() {
+        return MockRegistry.getSubscribedUrl().toString();
+    }
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/RpcConfigGetSetProxy.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/RpcConfigGetSetProxy.java
new file mode 100644
index 0000000..d883ec2
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/RpcConfigGetSetProxy.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.url;
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.config.AbstractConfig;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+
+public class RpcConfigGetSetProxy {
+
+    private static final String RPC_CONFIG_BASECLASS = AbstractConfig.class.getName();
+    private static final Logger log = LoggerFactory.getLogger(RpcConfigGetSetProxy.class);
+
+
+    private Object proxiee = null;
+    private Class<?> proxieeClass = null;
+    private Boolean isOk = false;
+
+    public RpcConfigGetSetProxy(Object p) {
+
+        if (p == null) {
+            return;
+        }
+
+        if (!isKindOf(p.getClass(), RPC_CONFIG_BASECLASS)) {
+            return;
+        }
+
+        proxiee = p;
+        //proxieeClass = c;
+        proxieeClass = p.getClass();
+        isOk = true;
+
+    }
+
+    public static boolean isKindOf(Class<?> c, String type) {
+
+        // get the class def for obj and type
+
+        Class<?> tClass;
+        try {
+            tClass = Class.forName(type);
+        } catch (ClassNotFoundException e) {
+            return false;
+        }
+
+        // check against type and superclasses
+        while (c != null) {
+            if (c == tClass) return true;
+            c = c.getSuperclass();
+        }
+
+        return false;
+    }
+
+    public boolean isOk() {
+        return isOk;
+    }
+
+    public Object setValue(String key, Object value) {
+
+        if (!isOk()) {
+            return null;
+        }
+
+        Method m = findSetMethod(key, value, proxieeClass);
+        return invoke(m, value);
+    }
+
+    public Object getValue(String key) {
+
+        if (!isOk()) {
+            return null;
+        }
+
+        Method m = findGetMethod(key, proxieeClass);
+        return invoke(m, null);
+    }
+
+    private Object invoke(Method m, Object value) {
+
+        if (m == null) {
+            return null;
+        }
+
+        try {
+            if (value == null) {
+                return m.invoke(proxiee, (Object[]) null);
+            } else {
+                return m.invoke(proxiee, value);
+            }
+        } catch (IllegalArgumentException e) {
+            log.error("IllegalArgumentException", e);
+            return null;
+        } catch (IllegalAccessException e) {
+            log.error("IllegalAccessException", e);
+            return null;
+        } catch (InvocationTargetException e) {
+            log.error("InvocationTargetException", e);
+            return null;
+        }
+    }
+
+    private Method findGetMethod(String key, Class<?> clazz) {
+
+        Method m = findMethod(key, null, "get", clazz);
+        if (m != null) {
+            return m;
+        }
+
+        return findMethod(key, null, "is", clazz);
+    }
+
+    private Method findSetMethod(String key, Object value, Class<?> clazz) {
+
+        return findMethod(key, value, "set", clazz);
+    }
+
+    private Method getMethod(String methodName, Object value, Class<?> clazz) {
+
+        try {
+            if (value == null) {
+                return clazz.getMethod(methodName, (Class<?>[]) null);
+            } else {
+                return clazz.getMethod(methodName, value.getClass());
+            }
+        } catch (SecurityException e) {
+            log.error("SecurityException: " + e.getMessage());
+            return null;
+        } catch (NoSuchMethodException e) {
+            log.error("NoSuchMethodException: " + e.getMessage());
+            return null;
+        }
+    }
+
+    private Method findMethod(String key, Object value, String prefix, Class<?> clazz) {
+
+        if (key.length() < 2) {
+            return null;
+        }
+
+        key = key.substring(0, 1).toUpperCase() + key.substring(1);
+        String methodName = prefix + key;
+
+        return getMethod(methodName, value, clazz);
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/UrlTestBase.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/UrlTestBase.java
new file mode 100644
index 0000000..b342685
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/url/UrlTestBase.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.url;
+
+
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+
+import java.util.Arrays;
+
+import static junit.framework.TestCase.fail;
+
+@SuppressWarnings("unused")
+public class UrlTestBase {
+
+    // ======================================================
+    //   data column definition
+    // ======================================================
+    protected static final int KEY = 0;
+    protected static final int URL_KEY = 1;
+    protected static final int TESTVALUE1 = 4;
+    private static final Logger log = LoggerFactory.getLogger(UrlTestBase.class);
+    private static final int TYPE = 2;
+    private static final int DEFAULT = 3;
+    private static final int TESTVALUE2 = 5;
+    private static final int TESTVALUE3 = 6;
+    private static final int TESTVALUE4 = 7;
+    private static final int TESTVALUE5 = 8;
+    private static final int TESTVALUE6 = 9;
+    private static final int TESTVALUE7 = 10;
+    protected ApplicationConfig appConfForProvider;
+    protected ApplicationConfig appConfForService;
+    protected RegistryConfig regConfForProvider;
+    protected RegistryConfig regConfForService;
+    protected ProviderConfig provConf;
+    protected ProtocolConfig protoConfForProvider;
+    protected ProtocolConfig protoConfForService;
+    protected MethodConfig methodConfForService;
+    protected ServiceConfig<DemoService> servConf;
+    protected Object servConfTable[][] = {
+            {"proxy", "proxy", "string", "javassist", "jdk", "javassist", "", "", "", ""},
+            {"actives", "actives", "int", 0, 90, "", "", "", "", ""},
+            {"executes", "executes", "int", 0, 90, "", "", "", "", ""},
+            {"deprecated", "deprecated", "boolean", false, true, "", "", "", "", ""},
+            {"dynamic", "dynamic", "boolean", true, false, "", "", "", "", ""},
+            {"accesslog", "accesslog", "string", "", "haominTest", "", "", "", "", ""},
+            {"document", "document", "string", "", "http://b2b-doc.alibaba-inc.com/display/RC/dubbo_devguide.htm?testquery=你好你好", "", "", "", "", ""},
+            {"weight", "weight", "int", 0, 90, "", "", "", "", ""},
+
+            //{"filter", "service.filter", "string", "", "", "", "", "", "", ""},
+            //{"listener", "listener", "string", "", "", "", "", "", "", ""},
+
+    };
+    protected Object regConfForServiceTable[][] = {
+            //            {"timeout", "registry.timeout", "int", 5000, 9000, "", "", "", "", ""},
+            //            {"file", "registry.file", "string", "", "regConfForServiceTable.log", "", "", "", "", ""},
+            //            {"wait", "registry.wait", "int", 0, 9000, "", "", "", "", ""},
+            //            {"transport", "registry.transporter", "string", "netty", "mina", "", "", "", "", ""},
+            //            {"subscribe", "subscribe", "boolean", true, false, "", "", "", "", ""},
+            {"dynamic", "dynamic", "boolean", true, false, "", "", "", "", ""},
+    };
+    protected Object provConfTable[][] = {
+            {"cluster", "default.cluster", "string", "string", "failover", "failfast", "failsafe", "", "", ""},
+            {"async", "default.async", "boolean", false, true, "", "", "", "", ""},
+            {"loadbalance", "default.loadbalance", "string", "random", "leastactive", "", "", "", "", ""},
+            {"connections", "default.connections", "int", 0, 60, "", "", "", "", ""},
+            {"retries", "default.retries", "int", 2, 60, "", "", "", "", ""},
+            {"timeout", "default.timeout", "int", 5000, 60, "", "", "", "", ""},
+            //change by fengting listener 没有缺省值
+            //{"listener", "exporter.listener", "string", "", "", "", "", "", "", ""},
+            //{"filter", "service.filter", "string", "", "", "", "", "", "", ""},
+
+    };
+    protected Object methodConfForServiceTable[][] = {
+            {"actives", "sayName.actives", "int", 0, 90, "", "", "", "", ""},
+            {"executes", "sayName.executes", "int", 0, 90, "", "", "", "", ""},
+            {"deprecated", "sayName.deprecated", "boolean", false, true, "", "", "", "", ""},
+            {"async", "sayName.async", "boolean", false, true, "", "", "", "", ""},
+            {"timeout", "sayName.timeout", "int", 0, 90, "", "", "", "", ""},
+    };
+    protected DemoService demoService = new DemoServiceImpl();
+    private Object appConfForProviderTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+    private Object appConfForServiceTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+    private Object regConfForProviderTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+    private Object protoConfForProviderTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+    private Object protoConfForServiceTable[][] = {
+            {"", "", "", "", "", "", "", "", "", ""},
+    };
+
+    // ======================================================
+    //   data table manipulation utils
+    // ====================================================== 
+    protected String genParamString(Object urlKey, Object value) {
+
+        return (String) urlKey + "=" + value.toString();
+    }
+
+    protected <T> void fillConfigs(T conf, Object[][] table, int column) {
+
+        for (Object[] row : table) {
+            fillConfig(conf, row, column);
+        }
+    }
+
+    protected <T> void fillConfig(T conf, Object[] row, int column) {
+
+        RpcConfigGetSetProxy proxy = new RpcConfigGetSetProxy(conf);
+        proxy.setValue((String) row[KEY], row[column]);
+
+    }
+
+    @SuppressWarnings("deprecation")
+    protected void initServConf() {
+
+        appConfForProvider = new ApplicationConfig();
+        appConfForService = new ApplicationConfig();
+        regConfForProvider = new RegistryConfig();
+        regConfForService = new RegistryConfig();
+        provConf = new ProviderConfig();
+        protoConfForProvider = new ProtocolConfig();
+        protoConfForService = new ProtocolConfig();
+        methodConfForService = new MethodConfig();
+        servConf = new ServiceConfig<DemoService>();
+
+        provConf.setApplication(appConfForProvider);
+        servConf.setApplication(appConfForService);
+
+        provConf.setRegistry(regConfForProvider);
+        servConf.setRegistry(regConfForService);
+
+        provConf.setProtocols(Arrays.asList(new ProtocolConfig[]{protoConfForProvider}));
+        servConf.setProtocols(Arrays.asList(new ProtocolConfig[]{protoConfForService}));
+
+        servConf.setMethods(Arrays.asList(new MethodConfig[]{methodConfForService}));
+        servConf.setProvider(provConf);
+
+        servConf.setRef(demoService);
+        servConf.setInterfaceClass(DemoService.class);
+
+        methodConfForService.setName("sayName");
+        regConfForService.setAddress("127.0.0.1:9090");
+        regConfForService.setProtocol("mockregistry");
+        appConfForService.setName("ConfigTests");
+    }
+
+    protected String getProviderParamString() {
+        return servConf.getExportedUrls().get(0).toString();
+    }
+
+    /**
+     * @param paramStringFromDb
+     * @param dataTable
+     * @param configName
+     * @param column
+     */
+    protected void assertUrlStringWithLocalTable(String paramStringFromDb,
+                                                 Object[][] dataTable, String configName, int column) {
+        final String FAILLOG_HEADER = "The following config items are not found in URLONE: ";
+
+        log.warn("Verifying service url for " + configName + "... ");
+        log.warn("Consumer url string: " + paramStringFromDb);
+
+        String failLog = FAILLOG_HEADER;
+        for (Object[] row : dataTable) {
+
+            String targetString = genParamString(row[URL_KEY], row[column]);
+
+            log.warn("Checking " + (String) row[KEY] + "for" + targetString);
+            if (paramStringFromDb.contains(targetString)) {
+                log.warn((String) row[KEY] + " --> " + targetString + " OK!");
+            } else {
+                failLog += targetString + ", ";
+            }
+        }
+
+        if (!failLog.equals(FAILLOG_HEADER)) {
+            fail(failLog);
+        }
+    }
+
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java
new file mode 100644
index 0000000..68df6cd
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.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.config.utils;
+
+import org.apache.dubbo.config.ReferenceConfig;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+public class MockReferenceConfig extends ReferenceConfig<String> {
+    static AtomicLong counter = new AtomicLong();
+
+    String value;
+    boolean destroyMethodRun = false;
+
+    public static void setCounter(long c) {
+        counter.set(c);
+    }
+
+    public boolean isGetMethodRun() {
+        return value != null;
+    }
+
+    public boolean isDestroyMethodRun() {
+        return destroyMethodRun;
+    }
+
+    @Override
+    public synchronized String get() {
+        if (value != null) return value;
+
+        value = "" + counter.getAndIncrement();
+        return value;
+    }
+
+    @Override
+    public synchronized void destroy() {
+        destroyMethodRun = true;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java
new file mode 100644
index 0000000..8216609
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.utils;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class ReferenceConfigCacheTest {
+    @Before
+    public void setUp() throws Exception {
+        MockReferenceConfig.setCounter(0);
+        ReferenceConfigCache.cacheHolder.clear();
+    }
+
+    @Test
+    public void testGetCacheSameReference() throws Exception {
+        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+        MockReferenceConfig config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        String value = cache.get(config);
+        assertTrue(config.isGetMethodRun());
+        assertEquals("0", value);
+
+        MockReferenceConfig configCopy = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        value = cache.get(configCopy);
+        assertFalse(configCopy.isGetMethodRun());
+        assertEquals("0", value);
+    }
+
+    @Test
+    public void testGetCacheDiffReference() throws Exception {
+        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+        MockReferenceConfig config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        String value = cache.get(config);
+        assertTrue(config.isGetMethodRun());
+        assertEquals("0", value);
+
+        MockReferenceConfig configCopy = buildMockReferenceConfig("XxxService", "group1", "1.0.0");
+        value = cache.get(configCopy);
+        assertTrue(configCopy.isGetMethodRun());
+        assertEquals("1", value);
+    }
+
+    @Test
+    public void testGetCacheDiffName() throws Exception {
+        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+        MockReferenceConfig config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        String value = cache.get(config);
+        assertTrue(config.isGetMethodRun());
+        assertEquals("0", value);
+
+        cache = ReferenceConfigCache.getCache("foo");
+        config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        value = cache.get(config);
+        // still init for the same ReferenceConfig if the cache is different
+        assertTrue(config.isGetMethodRun());
+        assertEquals("1", value);
+    }
+
+    @Test
+    public void testDestroy() throws Exception {
+        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+        MockReferenceConfig config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        cache.get(config);
+        MockReferenceConfig configCopy = buildMockReferenceConfig("XxxService", "group1", "1.0.0");
+        cache.get(configCopy);
+        assertEquals(2, cache.cache.size());
+        cache.destroy(config);
+        assertTrue(config.isDestroyMethodRun());
+        assertEquals(1, cache.cache.size());
+        cache.destroy(configCopy);
+        assertTrue(configCopy.isDestroyMethodRun());
+        assertEquals(0, cache.cache.size());
+    }
+
+    @Test
+    public void testDestroyAll() throws Exception {
+        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+        MockReferenceConfig config = buildMockReferenceConfig("FooService", "group1", "1.0.0");
+        cache.get(config);
+        MockReferenceConfig configCopy = buildMockReferenceConfig("XxxService", "group1", "1.0.0");
+        cache.get(configCopy);
+        assertEquals(2, cache.cache.size());
+        cache.destroyAll();
+        assertTrue(config.isDestroyMethodRun());
+        assertTrue(configCopy.isDestroyMethodRun());
+        assertEquals(0, cache.cache.size());
+    }
+
+    private MockReferenceConfig buildMockReferenceConfig(String service, String group, String version) {
+        MockReferenceConfig config = new MockReferenceConfig();
+        config.setInterface(service);
+        config.setGroup(group);
+        config.setVersion(version);
+        return config;
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationParameter.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
new file mode 100644
index 0000000..70c4d0e
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationParameter.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.validation;
+
+import javax.validation.constraints.Future;
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Past;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * ValidationParameter
+ */
+public class ValidationParameter implements Serializable {
+
+    private static final long serialVersionUID = 7158911668568000392L;
+
+    @NotNull(groups = ValidationService.Update.class)
+    private Integer id;
+
+    @NotNull
+    @Size(min = 2, max = 20)
+    private String name;
+
+    // not allow to save null, but allow to update with null which means not update the field
+    @NotNull(groups = ValidationService.Save.class)
+    @Pattern(regexp = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$")
+    private String email;
+
+    @Min(18)
+    @Max(100)
+    private int age;
+
+    @Past
+    private Date loginDate;
+
+    @Future
+    private Date expiryDate;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(Integer id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getEmail() {
+        return email;
+    }
+
+    public void setEmail(String email) {
+        this.email = email;
+    }
+
+    public int getAge() {
+        return age;
+    }
+
+    public void setAge(int age) {
+        this.age = age;
+    }
+
+    public Date getLoginDate() {
+        return loginDate;
+    }
+
+    public void setLoginDate(Date loginDate) {
+        this.loginDate = loginDate;
+    }
+
+    public Date getExpiryDate() {
+        return expiryDate;
+    }
+
+    public void setExpiryDate(Date expiryDate) {
+        this.expiryDate = expiryDate;
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationService.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationService.java
new file mode 100644
index 0000000..2efc5e0
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationService.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.validation;
+
+import org.apache.dubbo.validation.MethodValidated;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+
+
+/**
+ * ValidationService
+ * <p>
+ * Use service interface to distinguish validation scenario, for example: @NotNull(groups = ValidationService.class)
+ */
+public interface ValidationService {
+
+    /**
+     * The current logic will not verify 'groups = ValidationService.Save.class' if
+     * '@MethodValidated(ValidationService.Save.class)' is not present
+     *
+     * @param parameter
+     */
+    @MethodValidated(Save.class)
+    void save(ValidationParameter parameter);
+
+    void update(ValidationParameter parameter);
+
+    void delete(@Min(1) long id, @NotNull @Size(min = 2, max = 16) @Pattern(regexp = "^[a-zA-Z]+$") String operator);
+
+    /**
+     * Assume both id and email are needed to pass in, need to verify Save group and Update group.
+     *
+     * @param parameter
+     */
+    @MethodValidated({Save.class, Update.class})
+    void relatedQuery(ValidationParameter parameter);
+
+    /**
+     * annotation which has the same name with the method but has the first letter in capital
+     * used for distinguish validation scenario, for example: @NotNull(groups = ValidationService.Save.class)
+     * optional
+     */
+    @interface Save {
+    }
+
+    /**
+     * annotation which has the same name with the method but has the first letter in capital
+     * used for distinguish validation scenario, for example: @NotNull(groups = ValidationService.Update.class)
+     * optional
+     */
+    @interface Update {
+    }
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java
new file mode 100644
index 0000000..837e7e4
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationServiceImpl.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.validation;
+
+/**
+ * ValidationServiceImpl
+ */
+public class ValidationServiceImpl implements ValidationService {
+
+    public void save(ValidationParameter parameter) {
+    }
+
+    public void update(ValidationParameter parameter) {
+    }
+
+    public void delete(long id, String operator) {
+    }
+
+    public void relatedQuery(ValidationParameter parameter) {
+
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationTest.java b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationTest.java
new file mode 100644
index 0000000..39655ae
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/java/org/apache/dubbo/config/validation/ValidationTest.java
@@ -0,0 +1,301 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.validation;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.rpc.RpcException;
+import org.apache.dubbo.rpc.service.GenericException;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * GenericServiceTest
+ */
+public class ValidationTest {
+
+    @Test
+    public void testValidation() {
+        ServiceConfig<ValidationService> service = new ServiceConfig<ValidationService>();
+        service.setApplication(new ApplicationConfig("validation-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29582));
+        service.setInterface(ValidationService.class.getName());
+        service.setRef(new ValidationServiceImpl());
+        service.setValidation(String.valueOf(true));
+        service.export();
+        try {
+            ReferenceConfig<ValidationService> reference = new ReferenceConfig<ValidationService>();
+            reference.setApplication(new ApplicationConfig("validation-consumer"));
+            reference.setInterface(ValidationService.class);
+            reference.setUrl("dubbo://127.0.0.1:29582?scope=remote&validation=true");
+            ValidationService validationService = reference.get();
+            try {
+                // Save OK
+                ValidationParameter parameter = new ValidationParameter();
+                parameter.setName("liangfei");
+                parameter.setEmail("liangfei@liang.fei");
+                parameter.setAge(50);
+                parameter.setLoginDate(new Date(System.currentTimeMillis() - 1000000));
+                parameter.setExpiryDate(new Date(System.currentTimeMillis() + 1000000));
+                validationService.save(parameter);
+
+                try {
+                    parameter = new ValidationParameter();
+                    parameter.setName("l");
+                    parameter.setEmail("liangfei@liang.fei");
+                    parameter.setAge(50);
+                    parameter.setLoginDate(new Date(System.currentTimeMillis() - 1000000));
+                    parameter.setExpiryDate(new Date(System.currentTimeMillis() + 1000000));
+                    validationService.save(parameter);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                }
+
+                // verify save group, save error
+                try {
+                    parameter = new ValidationParameter();
+                    parameter.setName("liangfei");
+                    parameter.setAge(50);
+                    parameter.setLoginDate(new Date(System.currentTimeMillis() - 1000000));
+                    parameter.setExpiryDate(new Date(System.currentTimeMillis() + 1000000));
+                    validationService.save(parameter);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                }
+
+                // relatedQuery error, no id and email is passed, will trigger validation exception for both Save
+                // and Update
+                try {
+                    parameter = new ValidationParameter();
+                    parameter.setName("liangfei");
+                    parameter.setAge(50);
+                    parameter.setLoginDate(new Date(System.currentTimeMillis() - 1000000));
+                    parameter.setExpiryDate(new Date(System.currentTimeMillis() + 1000000));
+                    validationService.relatedQuery(parameter);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertEquals(violations.size(), 2);
+                }
+
+                // Save Error
+                try {
+                    parameter = new ValidationParameter();
+                    validationService.save(parameter);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertTrue(violations.size() == 3);
+                    Assert.assertNotNull(violations);
+                }
+
+                // Delete OK
+                validationService.delete(2, "abc");
+
+                // Delete Error
+                try {
+                    validationService.delete(2, "a");
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                    Assert.assertEquals(1, violations.size());
+                }
+
+                // Delete Error
+                try {
+                    validationService.delete(0, "abc");
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                    Assert.assertEquals(1, violations.size());
+                }
+                try {
+                    validationService.delete(2, null);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                    Assert.assertEquals(1, violations.size());
+                }
+                try {
+                    validationService.delete(0, null);
+                    Assert.fail();
+                } catch (ConstraintViolationException ve) {
+                    Set<ConstraintViolation<?>> violations = ve.getConstraintViolations();
+                    Assert.assertNotNull(violations);
+                    Assert.assertEquals(2, violations.size());
+                }
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testProviderValidation() {
+        ServiceConfig<ValidationService> service = new ServiceConfig<ValidationService>();
+        service.setApplication(new ApplicationConfig("validation-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29582));
+        service.setInterface(ValidationService.class.getName());
+        service.setRef(new ValidationServiceImpl());
+        service.setValidation(String.valueOf(true));
+        service.export();
+        try {
+            ReferenceConfig<ValidationService> reference = new ReferenceConfig<ValidationService>();
+            reference.setApplication(new ApplicationConfig("validation-consumer"));
+            reference.setInterface(ValidationService.class);
+            reference.setUrl("dubbo://127.0.0.1:29582");
+            ValidationService validationService = reference.get();
+            try {
+                // Save OK
+                ValidationParameter parameter = new ValidationParameter();
+                parameter.setName("liangfei");
+                parameter.setEmail("liangfei@liang.fei");
+                parameter.setAge(50);
+                parameter.setLoginDate(new Date(System.currentTimeMillis() - 1000000));
+                parameter.setExpiryDate(new Date(System.currentTimeMillis() + 1000000));
+                validationService.save(parameter);
+
+                // Save Error
+                try {
+                    parameter = new ValidationParameter();
+                    validationService.save(parameter);
+                    Assert.fail();
+                } catch (RpcException e) {
+                    Assert.assertTrue(e.getMessage().contains("ConstraintViolation"));
+                }
+
+                // Delete OK
+                validationService.delete(2, "abc");
+
+                // Delete Error
+                try {
+                    validationService.delete(0, "abc");
+                    Assert.fail();
+                } catch (RpcException e) {
+                    Assert.assertTrue(e.getMessage().contains("ConstraintViolation"));
+                }
+                try {
+                    validationService.delete(2, null);
+                    Assert.fail();
+                } catch (RpcException e) {
+                    Assert.assertTrue(e.getMessage().contains("ConstraintViolation"));
+                }
+                try {
+                    validationService.delete(0, null);
+                    Assert.fail();
+                } catch (RpcException e) {
+                    Assert.assertTrue(e.getMessage().contains("ConstraintViolation"));
+                }
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+    @Test
+    public void testGenericValidation() {
+        ServiceConfig<ValidationService> service = new ServiceConfig<ValidationService>();
+        service.setApplication(new ApplicationConfig("validation-provider"));
+        service.setRegistry(new RegistryConfig("N/A"));
+        service.setProtocol(new ProtocolConfig("dubbo", 29582));
+        service.setInterface(ValidationService.class.getName());
+        service.setRef(new ValidationServiceImpl());
+        service.setValidation(String.valueOf(true));
+        service.export();
+        try {
+            ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
+            reference.setApplication(new ApplicationConfig("validation-consumer"));
+            reference.setInterface(ValidationService.class.getName());
+            reference.setUrl("dubbo://127.0.0.1:29582?scope=remote&validation=true&timeout=9000000");
+            reference.setGeneric(true);
+            GenericService validationService = reference.get();
+            try {
+                // Save OK
+                Map<String, Object> parameter = new HashMap<String, Object>();
+                parameter.put("name", "liangfei");
+                parameter.put("Email", "liangfei@liang.fei");
+                parameter.put("Age", 50);
+                parameter.put("LoginDate", new Date(System.currentTimeMillis() - 1000000));
+                parameter.put("ExpiryDate", new Date(System.currentTimeMillis() + 1000000));
+                validationService.$invoke("save", new String[]{ValidationParameter.class.getName()}, new Object[]{parameter});
+
+                // Save Error
+                try {
+                    parameter = new HashMap<String, Object>();
+                    validationService.$invoke("save", new String[]{ValidationParameter.class.getName()}, new Object[]{parameter});
+                    Assert.fail();
+                } catch (GenericException e) {
+                    Assert.assertTrue(e.getMessage().contains("Failed to validate service"));
+                }
+
+                // Delete OK
+                validationService.$invoke("delete", new String[]{long.class.getName(), String.class.getName()}, new Object[]{2, "abc"});
+
+                // Delete Error
+                try {
+                    validationService.$invoke("delete", new String[]{long.class.getName(), String.class.getName()}, new Object[]{0, "abc"});
+                    Assert.fail();
+                } catch (GenericException e) {
+                    Assert.assertTrue(e.getMessage().contains("Failed to validate service"));
+                }
+                try {
+                    validationService.$invoke("delete", new String[]{long.class.getName(), String.class.getName()}, new Object[]{2, null});
+                    Assert.fail();
+                } catch (GenericException e) {
+                    Assert.assertTrue(e.getMessage().contains("Failed to validate service"));
+                }
+                try {
+                    validationService.$invoke("delete", new String[]{long.class.getName(), String.class.getName()}, new Object[]{0, null});
+                    Assert.fail();
+                } catch (GenericException e) {
+                    Assert.assertTrue(e.getMessage().contains("Failed to validate service"));
+                }
+            } catch (GenericException e) {
+                Assert.assertTrue(e.getMessage().contains("Failed to validate service"));
+            } finally {
+                reference.destroy();
+            }
+        } finally {
+            service.unexport();
+        }
+    }
+
+}
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.status.StatusChecker b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.status.StatusChecker
new file mode 100644
index 0000000..d7d3b44
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.status.StatusChecker
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockstatuschecker=org.apache.dubbo.config.mock.MockStatusChecker
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.threadpool.ThreadPool b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.threadpool.ThreadPool
new file mode 100644
index 0000000..f4f5d34
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.common.threadpool.ThreadPool
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockthreadpool=org.apache.dubbo.config.mock.MockThreadPool
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.registry.RegistryFactory b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.registry.RegistryFactory
new file mode 100644
index 0000000..7b8cf68
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.registry.RegistryFactory
@@ -0,0 +1,2 @@
+mockregistry=org.apache.dubbo.config.mock.MockRegistryFactory
+mockprotocol2=org.apache.dubbo.config.mock.MockRegistryFactory2
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Codec b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Codec
new file mode 100644
index 0000000..94f7668
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Codec
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockcodec=org.apache.dubbo.config.mock.MockCodec
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Dispatcher b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Dispatcher
new file mode 100644
index 0000000..febb4f8
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Dispatcher
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockdispatcher=org.apache.dubbo.config.mock.MockDispatcher
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Transporter b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Transporter
new file mode 100644
index 0000000..ef9ec51
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.Transporter
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mocktransporter=org.apache.dubbo.config.mock.MockTransporter
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.exchange.Exchanger b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.exchange.Exchanger
new file mode 100644
index 0000000..f8d3c3b
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.exchange.Exchanger
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockexchanger=org.apache.dubbo.config.mock.MockExchanger
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler
new file mode 100644
index 0000000..76dfd94
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.remoting.telnet.TelnetHandler
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+mocktelnethandler=org.apache.dubbo.config.mock.MockTelnetHandler
+
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ExporterListener b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ExporterListener
new file mode 100644
index 0000000..f9c818d
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ExporterListener
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+mockexporterlistener=org.apache.dubbo.config.mock.MockExporterListener
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Filter b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Filter
new file mode 100644
index 0000000..1938f96
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Filter
@@ -0,0 +1 @@
+mockfilter=org.apache.dubbo.config.mock.MockFilter
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.InvokerListener b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.InvokerListener
new file mode 100644
index 0000000..9e6d042
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.InvokerListener
@@ -0,0 +1 @@
+mockinvokerlistener=org.apache.dubbo.config.mock.MockInvokerListener
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Protocol b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Protocol
new file mode 100644
index 0000000..6c04497
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.Protocol
@@ -0,0 +1,2 @@
+mockprotocol=org.apache.dubbo.config.mock.MockProtocol
+mockprotocol2=org.apache.dubbo.config.mock.MockProtocol2
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ProxyFactory b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ProxyFactory
new file mode 100644
index 0000000..ded1b88
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.ProxyFactory
@@ -0,0 +1,2 @@
+mockproxyfactory=org.apache.dubbo.config.mock.MockProxyFactory
+testproxyfactory=org.apache.dubbo.config.mock.TestProxyFactory
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.Cluster b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.Cluster
new file mode 100644
index 0000000..066d136
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.Cluster
@@ -0,0 +1 @@
+mockcluster=org.apache.dubbo.config.mock.MockCluster
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.LoadBalance b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.LoadBalance
new file mode 100644
index 0000000..23b5087
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/META-INF/services/org.apache.dubbo.rpc.cluster.LoadBalance
@@ -0,0 +1 @@
+mockloadbalance=org.apache.dubbo.config.mock.MockLoadBalance
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/test/resources/log4j.xml b/dubbo-bootstrap/src/main/test/resources/log4j.xml
new file mode 100644
index 0000000..8607f5d
--- /dev/null
+++ b/dubbo-bootstrap/src/main/test/resources/log4j.xml
@@ -0,0 +1,28 @@
+<!--
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  See the NOTICE file distributed with
+  this work for additional information regarding copyright ownership.
+  The ASF licenses this file to You under the Apache License, Version 2.0
+  (the "License"); you may not use this file except in compliance with
+  the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+    <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+        <layout class="org.apache.log4j.PatternLayout">
+            <param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n"/>
+        </layout>
+    </appender>
+    <root>
+        <level value="INFO"/>
+        <appender-ref ref="CONSOLE"/>
+    </root>
+</log4j:configuration>
\ No newline at end of file


[incubator-dubbo] 05/06: Merge url part from cvictory and fix configuration override problems

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit 65450f5b8fda19b4b807adc06f59e4ffbc344f0d
Merge: 80f9091 91f1ce8
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 15:18:28 2018 +0800

    Merge url part from cvictory and fix configuration override problems

 dubbo-bom/pom.xml                                  |   5 +
 .../org/apache/dubbo/rpc/cluster/RouterChain.java  |  15 +-
 .../java/org/apache/dubbo/common/Constants.java    |  28 ++-
 .../dubbo/config/AbstractInterfaceConfig.java      |  89 ++++---
 ...eStoreConfig.java => MetadataReportConfig.java} |  39 +++-
 .../org/apache/dubbo/config/ReferenceConfig.java   |   5 +-
 .../org/apache/dubbo/config/RegistryConfig.java    |  17 --
 .../apache/dubbo/config/RegistryDataConfig.java    |  89 +++++++
 .../org/apache/dubbo/config/ServiceConfig.java     |   7 +-
 .../apache/dubbo/config/spring/ReferenceBean.java  |  14 +-
 .../apache/dubbo/config/spring/ServiceBean.java    |  14 +-
 .../spring/schema/DubboNamespaceHandler.java       |   2 -
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  16 +-
 .../src/main/resources/META-INF/dubbo.xsd          |  12 +-
 .../META-INF/spring/dubbo-demo-consumer.xml        |   2 +-
 dubbo-dependencies-bom/pom.xml                     |   6 +
 .../{ => dubbo-metadata-definition}/pom.xml        |  21 +-
 .../definition/ServiceDefinitionBuilder.java       | 106 +++++++++
 .../metadata/definition/TypeDefinitionBuilder.java |  79 +++++++
 .../definition/builder/ArrayTypeBuilder.java       |  54 +++++
 .../definition/builder/CollectionTypeBuilder.java  |  79 +++++++
 .../definition/builder/DefaultTypeBuilder.java     |  70 ++++++
 .../definition/builder/EnumTypeBuilder.java        |  63 +++++
 .../definition/builder/MapTypeBuilder.java         |  77 ++++++
 .../metadata/definition/builder/TypeBuilder.java}  |  26 ++-
 .../definition/model/FullServiceDefinition.java}   |  22 +-
 .../definition/model/MethodDefinition.java         |  74 ++++++
 .../definition/model/ServiceDefinition.java        |  80 +++++++
 .../metadata/definition/model/TypeDefinition.java  | 106 +++++++++
 .../dubbo/metadata/definition/util/ClassUtils.java | 112 +++++++++
 .../definition/util/JaketConfigurationUtils.java   | 100 ++++++++
 .../dubbo/metadata/definition/MetadataTest.java    | 153 ++++++++++++
 .../dubbo/metadata/definition/MetadataUtils.java   |  75 ++++++
 .../definition/common/ClassExtendsMap.java}        |  21 +-
 .../metadata/definition/common/ColorEnum.java}     |  14 +-
 .../metadata/definition/common/OuterClass.java}    |  28 ++-
 .../common/ResultWithRawCollections.java}          |  38 ++-
 .../metadata/definition/common/TestService.java}   |  42 +++-
 .../dubbo-metadata-report-api/pom.xml              |   9 +
 .../identifier/ConsumerMetadataIdentifier.java     |  31 +++
 .../metadata/identifier/MetadataIdentifier.java    |  85 +++++++
 .../identifier/ProviderMetadataIdentifier.java     |  17 ++
 .../integration/MetadataReportService.java         |  89 +++----
 .../dubbo/metadata/store/MetadataReport.java       |  25 +-
 .../metadata/store/MetadataReportFactory.java      |   4 +-
 .../metadata/support/AbstractMetadataReport.java   | 231 ++++++++++++------
 .../support/AbstractMetadataReportFactory.java     |  20 +-
 .../integration/MetadataReportServiceTest.java     |  75 ++----
 .../metadata/integration/RetryTestService.java     |  11 +
 .../store/test/JTestMetadataReport4Test.java       |  22 +-
 .../test/JTestMetadataReportFactory4Test.java      |   2 +-
 .../support/AbstractMetadataReportFactoryTest.java |  43 ++--
 .../support/AbstractMetadataReportTest.java        | 258 +++++++++++++++++----
 .../metadata/store/redis/RedisMetadataReport.java  |  29 ++-
 .../store/redis/RedisMetadataReportFactory.java    |   2 +-
 .../store/redis/RedisMetadata4TstService.java      |  12 +
 .../store/redis/RedisMetadataReportTest.java       | 111 +++++----
 .../store/zookeeper/ZookeeperMetadataReport.java   |  79 ++-----
 .../zookeeper/ZookeeperMetadataReportFactory.java  |   2 +-
 .../ZookeeperMetadataReport4TstService.java        |  11 +
 .../zookeeper/ZookeeperMetadataReportTest.java     | 209 ++++++-----------
 dubbo-metadata-report/pom.xml                      |   1 +
 .../registry/integration/RegistryProtocol.java     |   9 +-
 63 files changed, 2435 insertions(+), 752 deletions(-)

diff --cc dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
index aaac226,aaac226..0826ad9
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java
@@@ -26,10 -26,10 +26,10 @@@ import org.apache.dubbo.rpc.RpcInvocati
  import org.apache.dubbo.rpc.cluster.router.InvokerTreeCache;
  import org.apache.dubbo.rpc.cluster.router.TreeNode;
  
--import java.util.ArrayList;
  import java.util.Collections;
  import java.util.List;
  import java.util.Map;
++import java.util.concurrent.CopyOnWriteArrayList;
  import java.util.stream.Collectors;
  
  /**
@@@ -45,7 -45,7 +45,7 @@@ public class RouterChain<T> 
      // it's aimed to improve performance, only routers explicitly specifies 'runtime=true' will be executed when an RPC comes.
      private InvokerTreeCache<T> treeCache;
      // containing all routers, reconstruct every time 'route://' urls change.
--    private List<Router> routers;
++    private List<Router> routers = new CopyOnWriteArrayList<>();
      // Fixed router instances: ConfigConditionRouter, TagRouter, e.g., the rule for each instance may change but the instance will never delete or recreate.
      private List<Router> residentRouters;
  
@@@ -63,12 -63,12 +63,11 @@@
      }
  
      protected RouterChain(List<Router> routers) {
--        this.routers = routers;
++        this.routers.addAll(routers);
          treeCache = new InvokerTreeCache<>();
      }
  
      protected RouterChain(URL url) {
--        this.routers = new ArrayList<>();
          treeCache = new InvokerTreeCache<>();
          this.url = url;
      }
@@@ -92,9 -92,9 +91,11 @@@
       * @param generatedRouters
       */
      public void setGeneratedRouters(List<Router> generatedRouters) {
--        this.routers = new ArrayList<>();
--        this.routers.addAll(residentRouters);
--        this.routers.addAll(generatedRouters);
++        List<Router> newRouters = new CopyOnWriteArrayList<>();
++        newRouters.addAll(residentRouters);
++        newRouters.addAll(generatedRouters);
++        this.routers = newRouters;
++        // FIXME will sort cause concurrent problem? since it's kind of a write operation.
          this.sort();
          if (fullMethodInvokers != null) {
              this.preRoute(fullMethodInvokers, url, null);
diff --cc dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index 559ec6b,e765e2d..df0415b
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@@ -24,8 -25,6 +24,7 @@@ import org.apache.dubbo.config.MonitorC
  import org.apache.dubbo.config.ProtocolConfig;
  import org.apache.dubbo.config.ProviderConfig;
  import org.apache.dubbo.config.RegistryConfig;
- import org.apache.dubbo.config.ServiceStoreConfig;
 +import org.apache.dubbo.config.spring.ConfigCenterBean;
  import org.apache.dubbo.config.spring.ReferenceBean;
  import org.apache.dubbo.config.spring.ServiceBean;
  import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
@@@ -46,8 -45,7 +45,7 @@@ public class DubboNamespaceHandler exte
          registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
          registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
          registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
-         registerBeanDefinitionParser("servicestore", new DubboBeanDefinitionParser(ServiceStoreConfig.class, true));
 -        registerBeanDefinitionParser("configcenter", new DubboBeanDefinitionParser(ConfigCenterConfig.class, true));
 +        registerBeanDefinitionParser("configcenter", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
          registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
          registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
          registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));


[incubator-dubbo] 02/06: Change ZooKeeper's data structure as a config center

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit d20a6aa5481b37392754429edfc0d150e0cc2b3e
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 10:47:11 2018 +0800

    Change ZooKeeper's data structure as a config center
---
 .../dubbo/config/context/ConfigurationWrapper.java | 53 ++++++++++++++++++++++
 .../apache/dubbo/config/context/Environment.java   | 28 ++++++++----
 .../support/apollo/ApolloDynamicConfiguration.java |  7 +++
 .../sources/ZooKeeperConfigurationSource.java      | 12 ++++-
 .../java/org/apache/dubbo/registry/ZKTools.java    | 21 ++++++++-
 5 files changed, 109 insertions(+), 12 deletions(-)

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.java
new file mode 100644
index 0000000..2d758ae
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigurationWrapper.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.config.context;
+
+import org.apache.dubbo.common.config.AbstractConfiguration;
+import org.apache.dubbo.common.config.Configuration;
+
+/**
+ *
+ */
+public class ConfigurationWrapper extends AbstractConfiguration {
+    private String application;
+    private String service;
+    private String method;
+
+    private Configuration delegate;
+
+    public ConfigurationWrapper(String application, String service, String method, Configuration configuration) {
+        this.application = application;
+        this.service = service;
+        this.method = method;
+        this.delegate = configuration;
+    }
+
+    @Override
+    protected Object getInternalProperty(String key) {
+        Object value = delegate.getProperty(application + "." + key);
+        if (value == null) {
+            value = delegate.getProperty(service + "." + key);
+        }
+        if (value == null) {
+            value = delegate.getProperty(service + "." + method + "." + key);
+        }
+        if (value == null) {
+            value = delegate.getProperty(key);
+        }
+        return value;
+    }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
index edd8134..db9daaa 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/Environment.java
@@ -79,17 +79,27 @@ public class Environment {
         });
     }
 
-    public CompositeConfiguration getRuntimeCompositeConf(URL url) {
-        return runtimeCompositeConfsHolder.computeIfAbsent(url.toIdentityString(), k -> {
-            CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
-            compositeConfiguration.addConfiguration(getDynamicConfiguration());
-            compositeConfiguration.addConfiguration(this.getSystemConf(null, null));
-            compositeConfiguration.addConfiguration(url.toConfiguration());
-            compositeConfiguration.addConfiguration(this.getPropertiesConf(null, null));
-            return compositeConfiguration;
-        });
+    /**
+     * FIXME This method will recreate Configuration for each RPC, how much latency affect will this action has on performance?
+     *
+     * @param url
+     * @return
+     */
+    public CompositeConfiguration getRuntimeCompositeConf(URL url, String method) {
+        CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
+
+        String app = url.getParameter(Constants.APPLICATION_KEY);
+        String service = url.getServiceKey();
+        compositeConfiguration.addConfiguration(new ConfigurationWrapper(app, service, method, getDynamicConfiguration()));
+
+        compositeConfiguration.addConfiguration(url.toConfiguration());
+        compositeConfiguration.addConfiguration(this.getSystemConf(null, null));
+        compositeConfiguration.addConfiguration(this.getPropertiesConf(null, null));
+        return compositeConfiguration;
     }
 
+
+
     /**
      * If user opens DynamicConfig, the extension instance must has been created during the initialization of ConfigCenterConfig with the right extension type user specified.
      * If no DynamicConfig presents, NopDynamicConfiguration will be used.
diff --git a/dubbo-governance/dubbo-governance-apollo/src/main/java/org/apache/dubbo/governance/support/apollo/ApolloDynamicConfiguration.java b/dubbo-governance/dubbo-governance-apollo/src/main/java/org/apache/dubbo/governance/support/apollo/ApolloDynamicConfiguration.java
index 14db27b..0c83088 100644
--- a/dubbo-governance/dubbo-governance-apollo/src/main/java/org/apache/dubbo/governance/support/apollo/ApolloDynamicConfiguration.java
+++ b/dubbo-governance/dubbo-governance-apollo/src/main/java/org/apache/dubbo/governance/support/apollo/ApolloDynamicConfiguration.java
@@ -98,6 +98,13 @@ public class ApolloDynamicConfiguration extends AbstractDynamicConfiguration<Con
      */
     @Override
     protected String getInternalProperty(String key, String group, long timeout) {
+        if (group != null) {
+            Config config = ConfigService.getConfig(group);
+            if (config != null) {
+                return config.getProperty(key, null);
+            }
+            return null;
+        }
         return dubboConfig.getProperty(key, null);
     }
 
diff --git a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
index 7a96c4d..7cdf108 100644
--- a/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
+++ b/dubbo-governance/dubbo-governance-zookeeper/src/main/java/org/apache/dubbo/governance/support/archaius/sources/ZooKeeperConfigurationSource.java
@@ -55,6 +55,7 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
     private Executor executor = Executors.newFixedThreadPool(1);
     private final CuratorFramework client;
 
+    // The final root path would be: /configRootPath/"config"
     private final String configRootPath;
     private final TreeCache treeCache;
     private boolean connected = false;
@@ -72,13 +73,19 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
     }
 
 
+    /**
+     * @param connectString,  the zookeeper address
+     * @param sessionTimeout, timeout for session
+     * @param connectTimeout, timeout to wait before build a connection
+     * @param configRootPath, the final path would be: configRootPath/"config"
+     */
     public ZooKeeperConfigurationSource(String connectString, int sessionTimeout, int connectTimeout, String configRootPath) {
         if (connectString == null) {
             throw new IllegalArgumentException("connectString==null, must specify the address to connect for zookeeper archaius source.");
         }
 
         if (!configRootPath.startsWith("/")) {
-            configRootPath = "/" + configRootPath;
+            configRootPath = "/" + configRootPath + "/config";
         }
 
         CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, sessionTimeout, connectTimeout,
@@ -136,6 +143,7 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
                     return;
                 }
 
+                // TODO?
                 if (data.getPath().split("/").length == 5) {
                     byte[] value = data.getData();
                     String stringValue = new String(value, charset);
@@ -191,7 +199,7 @@ public class ZooKeeperConfigurationSource implements WatchedConfigurationSource,
         Map<String, Object> all = new HashMap<>();
 
         if (!connected) {
-            logger.warn("ConfigCenter is not connected yet, zookeeper don't support local snapshot yet, so there's no old data to use!");
+            logger.warn("ConfigCenter is not connected yet, zookeeper does't support local snapshot, so there's no backup data to use!");
             return all;
         }
 
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
index e310349..e113b93 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
+++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/ZKTools.java
@@ -43,13 +43,32 @@ public class ZKTools {
                 new ExponentialBackoffRetry(1000, 3));
         client.start();
 
-        testProviderConfig();
+        testStartupConfig();
+//        testProviderConfig();
 //        testPathCache();
 //        testTreeCache();
 //        testCuratorListener();
         System.in.read();
     }
 
+    public static void testStartupConfig() {
+        String str = "dubbo.registry.address=\"zookeeper://127.0.0.1:2181\"\n" +
+                "dubbo.registry.group=\"dubboregistrygroup1\"\n" +
+                "dubbo.servicestore.address=\"zookeeper://127.0.0.1:2181\"\n" +
+                "dubbo.protocol.port=20990\n" +
+                "dubbo.service.org.apache.dubbo.demo.DemoService.timeout=9999\n";
+
+        try {
+            String path = "/dubboregistrygroup1/dubbo.properties";
+            if (client.checkExists().forPath(path) == null) {
+                client.create().creatingParentsIfNeeded().forPath(path);
+            }
+            setData(path, str);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
     public static void testProviderConfig() {
         String str = "{\n" +
                 "\t\"service\": \"org.apache.dubbo.demo.DemoService\",\n" +


[incubator-dubbo] 01/06: Add xml schema and spring bean support for ConfigCenterConfig

Posted by li...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch dev-metadata
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git

commit d423f551d945c86af33e56752b4e9356499db1a5
Author: ken.lj <ke...@gmail.com>
AuthorDate: Thu Nov 1 10:45:39 2018 +0800

    Add xml schema and spring bean support for ConfigCenterConfig
---
 .../org/apache/dubbo/config/AbstractConfig.java    |  4 +--
 .../apache/dubbo/config/ConfigCenterConfig.java    | 10 +++---
 .../org/apache/dubbo/config/RegistryConfig.java    |  1 +
 .../dubbo/config/spring/ConfigCenterBean.java      | 37 ++++++++++++++++++++++
 .../spring/schema/DubboNamespaceHandler.java       |  4 +--
 .../src/main/resources/META-INF/compat/dubbo.xsd   |  8 ++++-
 .../src/main/resources/META-INF/dubbo.xsd          |  6 ++++
 7 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index ff74233..69e266f 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -31,7 +31,6 @@ import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.config.utils.ConfigConverter;
 import org.apache.dubbo.rpc.model.ConsumerMethodModel;
 
-import javax.annotation.PostConstruct;
 import java.io.Serializable;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
@@ -509,6 +508,7 @@ public abstract class AbstractConfig implements Serializable {
         return metaData;
     }
 
+    @Parameter(excluded = true)
     public String getPrefix() {
         return Constants.DUBBO + "." + getTagName(this.getClass());
     }
@@ -517,7 +517,6 @@ public abstract class AbstractConfig implements Serializable {
      * TODO
      * Currently, only support overriding of properties explicitly defined in Config class, doesn't support overriding of customized parameters stored in 'parameters'.
      */
-    @PostConstruct
     public void refresh() {
         if (init) {
             return;
@@ -620,6 +619,7 @@ public abstract class AbstractConfig implements Serializable {
     /**
      * FIXME check @Parameter(required=true) and any conditions that need to match.
      */
+    @Parameter(excluded = true)
     public boolean isValid() {
         return true;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index b532dd6..0e1497c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -25,7 +25,6 @@ import org.apache.dubbo.config.support.Parameter;
 import org.apache.dubbo.governance.DynamicConfiguration;
 import org.apache.dubbo.governance.DynamicConfigurationFactory;
 
-import javax.annotation.PostConstruct;
 import java.io.IOException;
 import java.io.StringReader;
 import java.util.HashMap;
@@ -40,15 +39,15 @@ public class ConfigCenterConfig extends AbstractConfig {
     private String address;
     private String env;
     private String cluster;
-    private String namespace;
+    private String namespace = "dubbo";
     private String appnamespace;
     private String username;
     private String password;
-    private long timeout;
+    private long timeout = 3000;
     private boolean priority;
     private boolean check;
 
-    private String dataid;
+    private String dataid = "dubbo.properties";
 
     // customized parameters
     private Map<String, String> parameters;
@@ -74,10 +73,9 @@ public class ConfigCenterConfig extends AbstractConfig {
         }
 
         Map<String, String> map = this.getMetaData();
-        return new URL("config", username, password, host, port, ConfigCenterConfig.class.getSimpleName(), map);
+        return new URL(Constants.CONFIG_PROTOCOL, username, password, host, port, ConfigCenterConfig.class.getSimpleName(), map);
     }
 
-    @PostConstruct
     public void init() throws Exception {
         // give jvm properties the chance of overriding local configs.
         refresh();
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
index a897ca2..721dd29 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -351,6 +351,7 @@ public class RegistryConfig extends AbstractConfig {
         this.addParamKeys = addParamKeys;
     }
 
+    @Parameter(excluded = true)
     public boolean isValid() {
         // empty protocol will default to 'dubbo'
         return !StringUtils.isEmpty(address);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
new file mode 100644
index 0000000..4995acc
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring;
+
+import org.apache.dubbo.config.ConfigCenterConfig;
+import org.springframework.beans.factory.DisposableBean;
+import org.springframework.beans.factory.InitializingBean;
+
+/**
+ *
+ */
+public class ConfigCenterBean extends ConfigCenterConfig implements InitializingBean, DisposableBean {
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        this.init();
+    }
+
+    @Override
+    public void destroy() throws Exception {
+
+    }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index 8642d64..559ec6b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring.schema;
 
 import org.apache.dubbo.common.Version;
 import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConfigCenterConfig;
 import org.apache.dubbo.config.ConsumerConfig;
 import org.apache.dubbo.config.ModuleConfig;
 import org.apache.dubbo.config.MonitorConfig;
@@ -26,6 +25,7 @@ import org.apache.dubbo.config.ProtocolConfig;
 import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.ServiceStoreConfig;
+import org.apache.dubbo.config.spring.ConfigCenterBean;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
 import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
@@ -47,7 +47,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport {
         registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
         registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
         registerBeanDefinitionParser("servicestore", new DubboBeanDefinitionParser(ServiceStoreConfig.class, true));
-        registerBeanDefinitionParser("configcenter", new DubboBeanDefinitionParser(ConfigCenterConfig.class, true));
+        registerBeanDefinitionParser("configcenter", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
         registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
         registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
         registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index 7cb6f28..3ecdf57 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -1322,7 +1322,7 @@
         </xsd:annotation>
     </xsd:element>
 
-    <xsd:element name="servicestore" type="servicestoreType">
+    <xsd:element name="servicestore" type="serviceStoreType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The servicestore config ]]></xsd:documentation>
             <xsd:appinfo>
@@ -1333,6 +1333,12 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="configcenter" type="configCenterType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The config center config ]]></xsd:documentation>
+        </xsd:annotation>
+    </xsd:element>
+
     <xsd:element name="monitor" type="monitorType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The logstat monitor config ]]></xsd:documentation>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 38baa24..c371b77 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -1322,6 +1322,12 @@
         </xsd:annotation>
     </xsd:element>
 
+    <xsd:element name="configcenter" type="configCenterType">
+        <xsd:annotation>
+            <xsd:documentation><![CDATA[ The config center config ]]></xsd:documentation>
+        </xsd:annotation>
+    </xsd:element>
+
     <xsd:element name="monitor" type="monitorType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The logstat monitor config ]]></xsd:documentation>