You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2021/09/14 02:17:28 UTC
[dubbo] branch 3.0 updated: [3.0] Multi instance - multi module
config/deploy and spring support (#8789)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.0
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.0 by this push:
new 5c2161a [3.0] Multi instance - multi module config/deploy and spring support (#8789)
5c2161a is described below
commit 5c2161aa0e9a073a51dd14e0c0edb36668d371a8
Author: Gong Dewei <ky...@qq.com>
AuthorDate: Tue Sep 14 10:17:07 2021 +0800
[3.0] Multi instance - multi module config/deploy and spring support (#8789)
* Add spring support for multi instance
* Fix testMultiModuleApplication
* polish ApplicationModel and so on
* destroy application when all module are removed
* Extract ApplicationDeployer and ModuleDeployer, add ModuleConfigManager, add spring support for module manage
* Fix ut
* Initialize SpringExtensionInjector
* Fix DubboHealthIndicatorTest
* Fix SpringExtensionInjector avoid using not completed Spring ApplicationContext
* Prepare application instance before refer services, fix SpringXmlConfigTest
* App index starts from 1 in each FrameworkModel
* Add ConfigScopeModelInitializer, Refactor DubboShutdownHook
* Register bean with class is change to getOrRegisterBean
* Fix ShutdownTelnetTest
* Fix missing dependency
* Fix not found ApplicationModel bean in spring context
* Add module deploy and reload test
* Put deployer to scope model attributes
* Add getDeployer() to ApplicationModel/ModuleModel
---
.../cluster/router/tag/TagDynamicStateRouter.java | 10 +-
.../cluster/router/tag/TagStaticStateRouter.java | 11 +-
.../dubbo/rpc/cluster/merger/ResultMergerTest.java | 1 -
.../support/AbstractClusterInvokerTest.java | 1 -
.../rpc/cluster/support/ClusterUtilsTest.java | 1 -
.../dubbo/common/CommonScopeModelInitializer.java | 2 +
.../common/beans/factory/ScopeBeanFactory.java | 37 +-
.../beans/factory/ScopeBeanFactoryInitializer.java | 75 -
.../beans/support/InstantiationStrategy.java | 16 +-
.../dubbo/common/bytecode/ClassGenerator.java | 7 +-
.../apache/dubbo/common/config/ReferenceCache.java | 38 +-
.../file/FileSystemDynamicConfiguration.java | 38 +-
.../dubbo/common/deploy/ApplicationDeployer.java | 34 +-
.../apache/dubbo/common/deploy/ModuleDeployer.java | 35 +-
.../dubbo/common/lang/ShutdownHookCallbacks.java | 10 +-
.../manager/DefaultExecutorRepository.java | 4 +-
.../org/apache/dubbo/config/AbstractConfig.java | 22 +-
.../dubbo/config/AbstractInterfaceConfig.java | 9 +-
.../apache/dubbo/config/AbstractMethodConfig.java | 5 +
.../apache/dubbo/config/ReferenceConfigBase.java | 12 +-
.../org/apache/dubbo/config/ServiceConfigBase.java | 19 +-
.../config/context/AbstractConfigManager.java | 527 ++++++
.../apache/dubbo/config/context/ConfigManager.java | 549 +------
.../dubbo/config/context/ConfigValidator.java | 19 +-
.../dubbo/config/context/ModuleConfigManager.java | 264 +++
.../apache/dubbo/rpc/model/ApplicationModel.java | 62 +-
.../org/apache/dubbo/rpc/model/FrameworkModel.java | 26 +-
...ModelPostProcessor.java => ModelConstants.java} | 15 +-
.../org/apache/dubbo/rpc/model/ModuleModel.java | 27 +-
.../org/apache/dubbo/rpc/model/ScopeModel.java | 73 +-
.../compiler/support/AdaptiveCompilerTest.java | 1 -
.../common/extension/ExtensionDirectorTest.java | 1 -
.../extension/support/ActivateComparatorTest.java | 1 -
.../common/lang/ShutdownHookCallbacksTest.java | 3 +-
.../dubbo/common/logger/LoggerFactoryTest.java | 1 -
.../apache/dubbo/common/utils/ConfigUtilsTest.java | 1 -
...sInterfaceDisplayNameHasMetaCharactersTest.java | 6 +-
.../dubbo/config/context/ConfigManagerTest.java | 50 +-
.../dubbo/config/ConfigScopeModelInitializer.java | 23 +-
.../org/apache/dubbo/config/DubboShutdownHook.java | 35 +-
.../org/apache/dubbo/config/ReferenceConfig.java | 33 +-
.../org/apache/dubbo/config/ServiceConfig.java | 83 +-
.../config/bootstrap/BootstrapTakeoverMode.java | 2 +-
.../bootstrap/DefaultApplicationDeployer.java | 941 +++++++++++
.../config/bootstrap/DefaultModuleDeployer.java | 345 ++++
.../dubbo/config/bootstrap/DubboBootstrap.java | 1733 ++++----------------
.../config/bootstrap/ModuleDeployListener.java | 21 +-
.../ConfigurableMetadataServiceExporter.java | 2 -
.../config/utils/CompositeReferenceCache.java | 109 ++
.../dubbo/config/utils/DefaultConfigValidator.java | 59 +
...eConfigCache.java => SimpleReferenceCache.java} | 164 +-
...rg.apache.dubbo.rpc.model.ScopeModelInitializer | 1 +
.../apache/dubbo/config/AbstractConfigTest.java | 1 -
.../dubbo/config/ConfigCenterConfigTest.java | 1 -
.../apache/dubbo/config/ConsumerConfigTest.java | 9 +-
.../apache/dubbo/config/ReferenceConfigTest.java | 28 +-
.../bootstrap/DubboBootstrapMultiInstanceTest.java | 174 +-
.../dubbo/config/bootstrap/DubboBootstrapTest.java | 20 +-
.../ServiceInstanceHostPortCustomizerTest.java | 1 -
.../dubbo/config/utils/MockReferenceConfig.java | 1 +
...onfigCacheTest.java => ReferenceCacheTest.java} | 37 +-
.../dubbo/config/utils/XxxMockReferenceConfig.java | 1 +
...egistryCenterExportProviderIntegrationTest.java | 2 -
...MultipleRegistryCenterInjvmIntegrationTest.java | 9 +-
...terServiceDiscoveryRegistryIntegrationTest.java | 7 +-
...RegistryCenterDubboProtocolIntegrationTest.java | 4 +-
...egistryCenterExportProviderIntegrationTest.java | 2 -
.../SingleRegistryCenterInjvmIntegrationTest.java | 7 +-
.../dubbo/config/spring/ConfigCenterBean.java | 3 -
.../apache/dubbo/config/spring/ReferenceBean.java | 16 +-
.../apache/dubbo/config/spring/ServiceBean.java | 10 +-
.../context/DubboBootstrapApplicationListener.java | 28 +-
.../DubboBootstrapServletContextListener.java | 58 -
.../spring/context/DubboConfigBeanInitializer.java | 42 +-
.../DubboInfraBeanRegisterPostProcessor.java | 11 +-
.../context/DubboSpringInitializationContext.java | 74 +
.../DubboSpringInitializationCustomizer.java | 6 +-
.../spring/context/DubboSpringInitializer.java | 131 +-
.../context/event/DubboAnnotationInitedEvent.java | 11 +-
.../spring/extension/SpringExtensionInjector.java | 86 +-
.../spring/reference/ReferenceBeanManager.java | 8 +-
.../spring/schema/DubboNamespaceHandler.java | 3 +-
.../spring/status/DataSourceStatusChecker.java | 26 +-
.../config/spring/status/SpringStatusChecker.java | 55 +-
.../dubbo/config/spring/util/DubboBeanUtils.java | 58 +-
.../org/apache/dubbo/config/spring/ConfigTest.java | 35 +-
.../dubbo/config/spring/JavaConfigBeanTest.java | 6 +-
.../annotation/MethodConfigCallbackTest.java | 4 +-
.../configprops/SpringBootConfigPropsTest.java | 10 +-
.../SpringBootMultipleConfigPropsTest.java | 10 +-
.../DubboComponentScanRegistrarTest.java | 5 +-
.../extension/SpringExtensionInjectorTest.java | 55 +-
.../config/spring/impl/MethodCallbackImpl.java | 3 +-
.../spring/issues/issue7003/Issue7003Test.java | 3 +-
.../consumer/PropertyConfigurerTest.java | 5 -
.../consumer2/PropertySourcesConfigurerTest.java | 6 +-
.../consumer3/PropertySourcesInJavaConfigTest.java | 9 -
.../javaconfig/JavaConfigReferenceBeanTest.java | 22 -
.../spring/schema/DubboNamespaceHandlerTest.java | 4 +-
.../config/spring/schema/GenericServiceTest.java | 10 +-
.../schema/GenericServiceWithoutInterfaceTest.java | 6 +-
.../spring/status/DataSourceStatusCheckerTest.java | 5 +-
.../spring/status/SpringStatusCheckerTest.java | 37 +-
.../dubbo/container/spring/SpringContainer.java | 1 -
.../apache/dubbo/demo/consumer/Application.java | 3 +-
.../dubbo/demo/consumer/GenericApplication.java | 3 +-
.../dubbo/demo/graalvm/consumer/Application.java | 3 +-
dubbo-metadata/dubbo-metadata-processor/pom.xml | 10 +-
.../dubbo/monitor/dubbo/MetricsFilterTest.java | 17 +-
.../dubbo/auth/AccessKeyAuthenticatorTest.java | 1 -
.../dubbo/auth/filter/ConsumerSignFilterTest.java | 1 -
.../dubbo/auth/filter/ProviderAuthFilterTest.java | 1 -
.../dubbo/qos/command/impl/ShutdownTelnet.java | 6 +-
.../dubbo/qos/command/impl/ShutdownTelnetTest.java | 5 +-
.../legacy/service/generic/GenericServiceTest.java | 6 +-
.../registry/client/DefaultServiceInstance.java | 3 +-
.../client/FileSystemServiceDiscovery.java | 8 +-
.../metadata/ServiceInstanceMetadataUtils.java | 3 +-
.../SpringCloudMetadataServiceURLBuilder.java | 3 +-
.../store/InMemoryWritableMetadataService.java | 3 +-
.../client/migration/model/MigrationRule.java | 1 -
.../registry/integration/RegistryProtocol.java | 2 +-
.../registry/CacheableFallbackRegistryTest.java | 1 -
.../client/ServiceDiscoveryRegistryTest.java | 1 -
.../metadata/MetadataServiceNameMappingTest.java | 1 -
.../client/metadata/MetadataUtilsTest.java | 1 -
.../ProtocolPortsMetadataCustomizerTest.java | 7 +-
.../store/InMemoryMetadataServiceTest.java | 1 -
.../client/migration/model/MigrationRuleTest.java | 1 -
.../registry/dns/DNSServiceDiscoveryTest.java | 3 +-
.../apache/dubbo/registry/nacos/NacosRegistry.java | 17 +-
.../nacos/util/NacosNamingServiceUtils.java | 13 +-
.../apache/dubbo/registry/xds/util/XdsChannel.java | 9 +-
.../zookeeper/ZookeeperServiceDiscovery.java | 5 +-
.../ZookeeperServiceDiscoveryChangeWatcher.java | 3 +-
.../org/apache/dubbo/remoting/api/Connection.java | 17 +-
.../dubbo/remoting/api/PortUnificationServer.java | 17 +-
.../remoting/api/PortUnificationServerHandler.java | 3 +-
.../org/apache/dubbo/remoting/api/SslContexts.java | 11 +-
.../apache/dubbo/remoting/api/WireProtocol.java | 5 +-
.../apache/dubbo/remoting/api/EmptyProtocol.java | 3 +-
.../remoting/transport/netty4/NettyClient.java | 21 +-
.../org/apache/dubbo/rpc/filter/GenericFilter.java | 7 +-
.../org/apache/dubbo/rpc/support/MockInvoker.java | 3 +-
.../apache/dubbo/rpc/support/MockInvokerTest.java | 1 -
.../dubbo/decode/DubboTelnetDecodeTest.java | 7 +-
.../dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java | 19 +-
.../dubbo/rpc/protocol/grpc/GrpcProtocolTest.java | 9 +-
.../rpc/protocol/tri/AbstractServerStream.java | 3 +-
.../apache/dubbo/rpc/protocol/tri/GrpcStatus.java | 6 +-
.../tri/TripleHttp2FrameServerHandler.java | 23 +-
.../rpc/protocol/tri/TripleHttp2Protocol.java | 15 +-
.../dubbo/rpc/protocol/tri/TripleInvoker.java | 3 +-
.../dubbo/rpc/protocol/tri/UnaryClientStream.java | 8 +-
.../dubbo/rpc/protocol/tri/UnaryServerStream.java | 3 +-
.../rpc/protocol/tri/service/TriHealthImpl.java | 1 -
.../serialize/hessian2/Hessian2ObjectInput.java | 3 +-
.../serialize/hessian2/Hessian2ObjectOutput.java | 3 +-
.../endpoint/metadata/DubboShutdownMetadata.java | 6 +-
.../boot/actuate/health/DubboHealthIndicator.java | 11 +-
.../event/AwaitingNonWebApplicationListener.java | 19 +-
.../AwaitingNonWebApplicationListenerTest.java | 45 +-
.../test/spring/SpringJavaConfigBeanTest.java | 14 +-
163 files changed, 4120 insertions(+), 3038 deletions(-)
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagDynamicStateRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagDynamicStateRouter.java
index 5a6dadc..85e7d76 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagDynamicStateRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagDynamicStateRouter.java
@@ -16,11 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.router.tag;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
@@ -41,6 +36,11 @@ import org.apache.dubbo.rpc.cluster.router.state.RouterCache;
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRouterRule;
import org.apache.dubbo.rpc.cluster.router.tag.model.TagRuleParser;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
import static org.apache.dubbo.rpc.Constants.FORCE_USE_TAG;
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStaticStateRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStaticStateRouter.java
index 8ede3c1..6e29ba7 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStaticStateRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagStaticStateRouter.java
@@ -16,11 +16,6 @@
*/
package org.apache.dubbo.rpc.cluster.router.tag;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
@@ -31,6 +26,12 @@ import org.apache.dubbo.rpc.cluster.RouterChain;
import org.apache.dubbo.rpc.cluster.router.state.AbstractStateRouter;
import org.apache.dubbo.rpc.cluster.router.state.BitList;
import org.apache.dubbo.rpc.cluster.router.state.RouterCache;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
/**
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/merger/ResultMergerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/merger/ResultMergerTest.java
index ef921bb..e49ac1f 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/merger/ResultMergerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/merger/ResultMergerTest.java
@@ -17,7 +17,6 @@
package org.apache.dubbo.rpc.cluster.merger;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
index a621371..0c3dec7 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvokerTest.java
@@ -33,7 +33,6 @@ import org.apache.dubbo.rpc.cluster.filter.DemoService;
import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RandomLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
diff --git a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java
index 8e897df..7cf23b3 100644
--- a/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java
+++ b/dubbo-cluster/src/test/java/org/apache/dubbo/rpc/cluster/support/ClusterUtilsTest.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.rpc.cluster.support;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java
index 8caab81..4ac60c6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.common;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
+import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
@@ -32,6 +33,7 @@ public class CommonScopeModelInitializer implements ScopeModelInitializer {
@Override
public void initializeApplicationModel(ApplicationModel applicationModel) {
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
+ beanFactory.registerBean(ShutdownHookCallbacks.class);
beanFactory.registerBean(FrameworkStatusReportService.class);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
index e417591..21a8232 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactory.java
@@ -65,10 +65,14 @@ public class ScopeBeanFactory {
}
public <T> T registerBean(Class<T> bean) throws ScopeBeanException {
- return this.registerBean(null, bean);
+ return this.getOrRegisterBean(null, bean);
}
public <T> T registerBean(String name, Class<T> clazz) throws ScopeBeanException {
+ return getOrRegisterBean(name, clazz);
+ }
+
+ private <T> T createAndRegisterBean(String name, Class<T> clazz) {
T instance = getBean(name, clazz);
if (instance != null) {
throw new ScopeBeanException("already exists bean with same name and type, name=" + name + ", type=" + clazz.getName());
@@ -76,7 +80,7 @@ public class ScopeBeanFactory {
try {
instance = instantiationStrategy.instantiate(clazz);
} catch (Throwable e) {
- throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName());
+ throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName(), e);
}
registerBean(name, instance);
return instance;
@@ -101,23 +105,23 @@ public class ScopeBeanFactory {
registeredBeanInfos.add(new BeanInfo(name, bean));
}
- public <T> T registerBeanIfAbsent(Class<T> type) {
- return registerBeanIfAbsent(null, type);
+ public <T> T getOrRegisterBean(Class<T> type) {
+ return getOrRegisterBean(null, type);
}
- public <T> T registerBeanIfAbsent(String name, Class<T> type) {
+ public <T> T getOrRegisterBean(String name, Class<T> type) {
T bean = getBean(name, type);
if (bean == null) {
- bean = registerBean(name, type);
+ bean = createAndRegisterBean(name, type);
}
return bean;
}
- public <T> T registerBeanIfAbsent(Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
- return registerBeanIfAbsent(null, type, mappingFunction);
+ public <T> T getOrRegisterBean(Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
+ return getOrRegisterBean(null, type, mappingFunction);
}
- public <T> T registerBeanIfAbsent(String name, Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
+ public <T> T getOrRegisterBean(String name, Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
T bean = getBean(name, type);
if (bean == null) {
//TODO add lock for type
@@ -177,16 +181,23 @@ public class ScopeBeanFactory {
return null;
}
List<BeanInfo> candidates = null;
+ BeanInfo firstCandidate = null;
for (BeanInfo beanInfo : registeredBeanInfos) {
// if required bean type is same class/superclass/interface of the registered bean
if (type.isAssignableFrom(beanInfo.instance.getClass())) {
if (StringUtils.isEquals(beanInfo.name, name)) {
return (T) beanInfo.instance;
} else {
- if (candidates == null) {
- candidates = new ArrayList<>();
+ // optimize for only one matched bean
+ if (firstCandidate == null) {
+ firstCandidate = beanInfo;
+ } else {
+ if (candidates == null) {
+ candidates = new ArrayList<>();
+ candidates.add(firstCandidate);
+ }
+ candidates.add(beanInfo);
}
- candidates.add(beanInfo);
}
}
}
@@ -199,6 +210,8 @@ public class ScopeBeanFactory {
List<String> candidateBeanNames = candidates.stream().map(beanInfo -> beanInfo.name).collect(Collectors.toList());
throw new ScopeBeanException("expected single matching bean but found " + candidates.size() + " candidates for type [" + type.getName() + "]: " + candidateBeanNames);
}
+ } else if (firstCandidate != null) {
+ return (T) firstCandidate.instance;
}
return null;
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java
deleted file mode 100644
index 07ced8d..0000000
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/factory/ScopeBeanFactoryInitializer.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.common.beans.factory;
-
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.FrameworkModel;
-import org.apache.dubbo.rpc.model.ModuleModel;
-import org.apache.dubbo.rpc.model.ScopeModel;
-import org.apache.dubbo.rpc.model.ScopeModelPostProcessor;
-
-/**
- * Initialize the bean factory for ScopeModel
- */
-public abstract class ScopeBeanFactoryInitializer implements ScopeModelPostProcessor {
-
- @Override
- public void postProcessScopeModel(ScopeModel scopeModel) {
- if (scopeModel instanceof ApplicationModel) {
- ApplicationModel applicationModel = (ApplicationModel) scopeModel;
- registerApplicationBeans(applicationModel, applicationModel.getBeanFactory());
- } else if (scopeModel instanceof FrameworkModel) {
- FrameworkModel frameworkModel = (FrameworkModel) scopeModel;
- registerFrameworkBeans(frameworkModel, frameworkModel.getBeanFactory());
- } else if (scopeModel instanceof ModuleModel) {
- ModuleModel moduleModel = (ModuleModel) scopeModel;
- registerModuleBeans(moduleModel, moduleModel.getBeanFactory());
- }
- }
-
- /**
- * Initialize beans for framework
- *
- * @param frameworkModel
- * @param beanFactory
- */
- protected void registerFrameworkBeans(FrameworkModel frameworkModel, ScopeBeanFactory beanFactory) {
-
- }
-
- /**
- * Initialize beans for application
- *
- * @param applicationModel
- * @param beanFactory
- */
- protected void registerApplicationBeans(ApplicationModel applicationModel, ScopeBeanFactory beanFactory) {
-// beanFactory.registerBean(MetadataReportInstance.class);
-// beanFactory.registerBean(RemoteMetadataServiceImpl.class);
- }
-
- /**
- * Initialize beans for module
- *
- * @param moduleModel
- * @param beanFactory
- */
- protected void registerModuleBeans(ModuleModel moduleModel, ScopeBeanFactory beanFactory) {
-
- }
-
-}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/support/InstantiationStrategy.java b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/support/InstantiationStrategy.java
index 5e1fea3..b1b67ce 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/beans/support/InstantiationStrategy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/beans/support/InstantiationStrategy.java
@@ -61,12 +61,9 @@ public class InstantiationStrategy {
List<Constructor> matchedConstructors = new ArrayList<>();
Constructor<?>[] declaredConstructors = type.getConstructors();
for (Constructor<?> constructor : declaredConstructors) {
- for (Class<?> parameterType : constructor.getParameterTypes()) {
- if (!isSupportedConstructorParameterType(parameterType)) {
- break;
- }
+ if (isMatched(constructor)) {
+ matchedConstructors.add(constructor);
}
- matchedConstructors.add(constructor);
}
if (matchedConstructors.size() > 1) {
throw new IllegalArgumentException("Expect only one but found " +
@@ -86,6 +83,15 @@ public class InstantiationStrategy {
return (T) constructor.newInstance(args);
}
+ private boolean isMatched(Constructor<?> constructor) {
+ for (Class<?> parameterType : constructor.getParameterTypes()) {
+ if (!isSupportedConstructorParameterType(parameterType)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
private boolean isSupportedConstructorParameterType(Class<?> parameterType) {
return ScopeModel.class.isAssignableFrom(parameterType);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
index ed2ff6b..182b4de 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/ClassGenerator.java
@@ -16,10 +16,6 @@
*/
package org.apache.dubbo.common.bytecode;
-import org.apache.dubbo.common.utils.ArrayUtils;
-import org.apache.dubbo.common.utils.ReflectUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
@@ -29,6 +25,9 @@ import javassist.CtMethod;
import javassist.CtNewConstructor;
import javassist.CtNewMethod;
import javassist.NotFoundException;
+import org.apache.dubbo.common.utils.ArrayUtils;
+import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.common.utils.StringUtils;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
diff --git a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/EmptyProtocol.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ReferenceCache.java
similarity index 54%
copy from dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/EmptyProtocol.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/config/ReferenceCache.java
index 7d3b5cf..a7f23d9 100644
--- a/dubbo-remoting/dubbo-remoting-api/src/test/java/org/apache/dubbo/remoting/api/EmptyProtocol.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ReferenceCache.java
@@ -14,31 +14,33 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.remoting.api;
+package org.apache.dubbo.common.config;
-import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ReferenceConfigBase;
-import io.netty.channel.ChannelPipeline;
-import io.netty.handler.ssl.SslContext;
+import java.util.List;
-public class EmptyProtocol implements WireProtocol {
- @Override
- public ProtocolDetector detector() {
- return null;
- }
+public interface ReferenceCache {
+ @SuppressWarnings("unchecked")
+ <T> T get(ReferenceConfigBase<T> referenceConfig);
- @Override
- public void configServerPipeline(URL url, ChannelPipeline pipeline,SslContext sslContext) {
+ @SuppressWarnings("unchecked")
+ <T> T get(String key, Class<T> type);
- }
+ @SuppressWarnings("unchecked")
+ <T> T get(String key);
- @Override
- public void configClientPipeline(URL url, ChannelPipeline pipeline, SslContext sslContext) {
+ @SuppressWarnings("unchecked")
+ <T> List<T> getAll(Class<T> type);
- }
+ @SuppressWarnings("unchecked")
+ <T> T get(Class<T> type);
- @Override
- public void close() {
+ void destroy(String key, Class<?> type);
- }
+ void destroy(Class<?> type);
+
+ <T> void destroy(ReferenceConfigBase<T> referenceConfig);
+
+ void destroyAll();
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
index a41d711..2dcf71d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
@@ -16,6 +16,9 @@
*/
package org.apache.dubbo.common.config.configcenter.file;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
@@ -27,10 +30,8 @@ import org.apache.dubbo.common.function.ThrowableFunction;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.io.File;
import java.io.IOException;
@@ -54,6 +55,7 @@ import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.stream.Collectors;
@@ -147,7 +149,6 @@ public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration
MODIFIERS = initWatchEventModifiers();
DELAY = initDelay(MODIFIERS);
WATCH_EVENTS_LOOP_THREAD_POOL = newWatchEventsLoopThreadPool();
- registerDubboShutdownHook();
}
/**
@@ -168,6 +169,8 @@ public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration
private final Set<File> processingDirectories;
private final Map<File, List<ConfigurationListener>> listenersRepository;
+ private ScopeModel scopeModel;
+ private AtomicBoolean hasRegisteredShutdownHook = new AtomicBoolean();
public FileSystemDynamicConfiguration() {
this(new File(DEFAULT_CONFIG_CENTER_DIR_PATH));
@@ -199,11 +202,26 @@ public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration
this.encoding = encoding;
this.processingDirectories = initProcessingDirectories();
this.listenersRepository = new LinkedHashMap<>();
+ registerDubboShutdownHook();
+ }
+
+ public FileSystemDynamicConfiguration(File rootDirectory, String encoding,
+ String threadPoolPrefixName,
+ int threadPoolSize,
+ long keepAliveTime,
+ ScopeModel scopeModel) {
+ super(rootDirectory.getAbsolutePath(), threadPoolPrefixName, threadPoolSize, keepAliveTime, DEFAULT_GROUP, -1L);
+ this.rootDirectory = rootDirectory;
+ this.encoding = encoding;
+ this.processingDirectories = initProcessingDirectories();
+ this.listenersRepository = new LinkedHashMap<>();
+ this.scopeModel = scopeModel;
+ registerDubboShutdownHook();
}
public FileSystemDynamicConfiguration(URL url) {
this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url),
- getThreadPoolKeepAliveTime(url));
+ getThreadPoolKeepAliveTime(url), url.getScopeModel());
}
private Set<File> initProcessingDirectories() {
@@ -237,8 +255,12 @@ public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration
*
* @since 2.7.8
*/
- private static void registerDubboShutdownHook() {
- ShutdownHookCallbacks.INSTANCE.addCallback(() -> {
+ private void registerDubboShutdownHook() {
+ if (!hasRegisteredShutdownHook.compareAndSet(false, true)) {
+ return;
+ }
+ ShutdownHookCallbacks shutdownHookCallbacks = ScopeModelUtil.getApplicationModel(scopeModel).getBeanFactory().getBean(ShutdownHookCallbacks.class);
+ shutdownHookCallbacks.addCallback(() -> {
watchService.ifPresent(w -> {
try {
w.close();
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
similarity index 57%
copy from dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
index 08a5e09..7c2a04a 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ApplicationDeployer.java
@@ -14,23 +14,35 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.context;
+package org.apache.dubbo.common.deploy;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.apache.dubbo.common.config.ReferenceCache;
+import org.apache.dubbo.common.context.Lifecycle;
+import org.apache.dubbo.rpc.model.ApplicationModel;
/**
- * Dubbo spring initialization context object
+ * initialize and start application instance
*/
-public class DubboSpringInitializationContext {
+public interface ApplicationDeployer extends Lifecycle {
- private BeanDefinitionRegistry registry;
+ void initialize();
- public BeanDefinitionRegistry getRegistry() {
- return registry;
- }
+ void start();
- void setRegistry(BeanDefinitionRegistry registry) {
- this.registry = registry;
- }
+ void prepareApplicationInstance();
+
+ void destroy();
+
+ boolean isInitialized();
+
+ boolean isStarted();
+
+ boolean isStartup();
+
+ boolean isShutdown();
+
+ ApplicationModel getApplicationModel();
+
+ ReferenceCache getReferenceCache();
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java
similarity index 55%
copy from dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
copy to dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java
index 08a5e09..16f0161 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/deploy/ModuleDeployer.java
@@ -14,23 +14,36 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.context;
+package org.apache.dubbo.common.deploy;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.apache.dubbo.common.config.ReferenceCache;
+import org.apache.dubbo.config.ServiceConfigBase;
+
+import java.util.concurrent.CompletableFuture;
/**
- * Dubbo spring initialization context object
+ * Export/refer services of module
*/
-public class DubboSpringInitializationContext {
+public interface ModuleDeployer {
+
+ void initialize() throws IllegalStateException;
+
+ CompletableFuture start() throws IllegalStateException;
+
+ void destroy() throws IllegalStateException;
+
+ boolean isStartup();
+
+ boolean isInitialized();
+
+ boolean isExportBackground();
+
+ boolean isReferBackground();
- private BeanDefinitionRegistry registry;
+ ReferenceCache getReferenceCache();
- public BeanDefinitionRegistry getRegistry() {
- return registry;
- }
+ void prepare();
- void setRegistry(BeanDefinitionRegistry registry) {
- this.registry = registry;
- }
+ void notifyExportService(ServiceConfigBase<?> sc);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
index e1d01a2..da3f6a7 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/lang/ShutdownHookCallbacks.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.common.lang;
import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collection;
import java.util.LinkedList;
@@ -32,11 +33,12 @@ import static org.apache.dubbo.common.function.ThrowableAction.execute;
*/
public class ShutdownHookCallbacks {
- public static final ShutdownHookCallbacks INSTANCE = new ShutdownHookCallbacks();
-
private final List<ShutdownHookCallback> callbacks = new LinkedList<>();
- ShutdownHookCallbacks() {
+ private ApplicationModel applicationModel;
+
+ public ShutdownHookCallbacks(ApplicationModel applicationModel) {
+ this.applicationModel = applicationModel;
loadCallbacks();
}
@@ -62,7 +64,7 @@ public class ShutdownHookCallbacks {
private void loadCallbacks() {
ExtensionLoader<ShutdownHookCallback> loader =
- ExtensionLoader.getExtensionLoader(ShutdownHookCallback.class);
+ applicationModel.getExtensionLoader(ShutdownHookCallback.class);
loader.getSupportedExtensionInstances().forEach(this::addCallback);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
index 5c93b23..bf63c38 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/threadpool/manager/DefaultExecutorRepository.java
@@ -233,7 +233,7 @@ public class DefaultExecutorRepository implements ExecutorRepository, ExtensionA
}
private Integer getExportThreadNum() {
- List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getProviders()
+ List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getDefaultModule().getConfigManager().getProviders()
.stream()
.map(ProviderConfig::getExportThreadNum)
.filter(k -> k != null && k > 0)
@@ -280,7 +280,7 @@ public class DefaultExecutorRepository implements ExecutorRepository, ExtensionA
}
private Integer getReferThreadNum() {
- List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getConsumers()
+ List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getDefaultModule().getConfigManager().getConsumers()
.stream()
.map(ConsumerConfig::getReferThreadNum)
.filter(k -> k != null && k > 0)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index dc57114..3b4be54 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -338,20 +338,10 @@ public abstract class AbstractConfig implements Serializable {
public final void setScopeModel(ScopeModel scopeModel) {
if (this.scopeModel != scopeModel) {
checkScopeModel(scopeModel);
- // remove this config from current ConfigManager
ScopeModel oldScopeModel = this.scopeModel;
- if (oldScopeModel != null) {
- boolean removed = getConfigManager().removeConfig(this);
- // change scope model and add it into new ConfigManager
- this.scopeModel = scopeModel;
- if (removed) {
- getConfigManager().addConfig(this);
- }
- }else {
- this.scopeModel = scopeModel;
- }
+ this.scopeModel = scopeModel;
// reinitialize spi extension and change referenced config's scope model
- this.postProcessAfterScopeModelChanged();
+ this.postProcessAfterScopeModelChanged(oldScopeModel, this.scopeModel);
}
}
@@ -379,8 +369,14 @@ public abstract class AbstractConfig implements Serializable {
* }
* }
* </pre>
+ * @param oldScopeModel
+ * @param newScopeModel
*/
- protected void postProcessAfterScopeModelChanged() {
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ // remove this config from old ConfigManager
+// if (oldScopeModel != null && oldScopeModel instanceof ApplicationModel) {
+// ((ApplicationModel)oldScopeModel).getApplicationConfigManager().removeConfig(this);
+// }
}
protected <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 48de804..feb504a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -29,6 +29,7 @@ import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import org.apache.dubbo.rpc.model.ServiceMetadata;
@@ -205,8 +206,12 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
@Override
- protected void postProcessAfterScopeModelChanged() {
- super.postProcessAfterScopeModelChanged();
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
+ // remove this config from old ConfigManager
+// if (oldScopeModel != null && oldScopeModel instanceof ModuleModel) {
+// ((ModuleModel)oldScopeModel).getConfigManager().removeConfig(this);
+// }
// change referenced config's scope model
ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(scopeModel);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java
index e8b2f41..5bdb5cb 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractMethodConfig.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
@@ -117,6 +118,10 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
}
}
+ protected ModuleConfigManager getModuleConfigManager() {
+ return getScopeModel().getConfigManager();
+ }
+
public Integer getForks() {
return forks;
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
index b573b02..77c3f73 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ReferenceConfigBase.java
@@ -22,6 +22,7 @@ import org.apache.dubbo.common.utils.RegexProperties;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -114,7 +115,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
protected void preProcessRefresh() {
super.preProcessRefresh();
if (consumer == null) {
- consumer = getConfigManager()
+ consumer = getModuleConfigManager()
.getDefaultConsumer()
.orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized"));
}
@@ -211,8 +212,8 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
}
@Override
- protected void postProcessAfterScopeModelChanged() {
- super.postProcessAfterScopeModelChanged();
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
if (this.consumer != null && this.consumer.getScopeModel() != scopeModel) {
this.consumer.setScopeModel(scopeModel);
}
@@ -346,7 +347,8 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
public abstract T get();
- public abstract void destroy();
-
+ public void destroy() {
+ getModuleConfigManager().removeConfig(this);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
index cbce529..8694be3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ServiceConfigBase.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -105,8 +106,8 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
}
@Override
- protected void postProcessAfterScopeModelChanged() {
- super.postProcessAfterScopeModelChanged();
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
if (this.provider != null && this.provider.getScopeModel() != scopeModel) {
this.provider.setScopeModel(scopeModel);
}
@@ -206,7 +207,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
super.preProcessRefresh();
convertProviderIdToProvider();
if (provider == null) {
- provider = getConfigManager()
+ provider = getModuleConfigManager()
.getDefaultProvider()
.orElseThrow(() -> new IllegalArgumentException("Default provider is not initialized"));
}
@@ -254,7 +255,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
protected void convertProviderIdToProvider() {
if (provider == null && StringUtils.hasText(providerIds)) {
- provider = getConfigManager().getProvider(providerIds)
+ provider = getModuleConfigManager().getProvider(providerIds)
.orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds));
}
}
@@ -346,7 +347,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
}
public void setProvider(ProviderConfig provider) {
- getConfigManager().addProvider(provider);
+ getModuleConfigManager().addProvider(provider);
this.provider = provider;
}
@@ -446,8 +447,16 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return shouldExportAsync;
}
+ /**
+ * export service and auto start application instance
+ */
public abstract void export();
+ /**
+ * export service only, do not register application instance, for exporting services in batches by module
+ */
+ public abstract void exportOnly();
+
public abstract void unexport();
public abstract boolean isExported();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java
new file mode 100644
index 0000000..f7a4320
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java
@@ -0,0 +1,527 @@
+/*
+ * 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.ConfigurationUtils;
+import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.config.PropertiesConfiguration;
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.context.LifecycleAdapter;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.ConcurrentHashSet;
+import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.MetricsConfig;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.config.ReferenceConfigBase;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfigBase;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+
+import static java.lang.Boolean.TRUE;
+import static java.util.Collections.emptyMap;
+import static java.util.Optional.ofNullable;
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
+import static org.apache.dubbo.config.AbstractConfig.getTagName;
+
+public abstract class AbstractConfigManager extends LifecycleAdapter {
+
+ private static final String CONFIG_NAME_READ_METHOD = "getName";
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractConfigManager.class);
+
+ final Map<String, Map<String, AbstractConfig>> configsCache = new ConcurrentHashMap<>();
+
+ private final Map<String, AtomicInteger> configIdIndexes = new ConcurrentHashMap<>();
+
+ protected Set<AbstractConfig> duplicatedConfigs = new ConcurrentHashSet<>();
+
+ protected final ScopeModel scopeModel;
+ protected final ApplicationModel applicationModel;
+ private final Collection<Class<? extends AbstractConfig>> supportedConfigTypes;
+ private final Environment environment;
+ private ConfigValidator configValidator;
+
+ public AbstractConfigManager(ScopeModel scopeModel, Collection<Class<? extends AbstractConfig>> supportedConfigTypes) {
+ this.scopeModel = scopeModel;
+ this.applicationModel = ScopeModelUtil.getApplicationModel(scopeModel);
+ this.supportedConfigTypes = supportedConfigTypes;
+ environment = applicationModel.getApplicationEnvironment();
+ }
+
+ /**
+ * Add the dubbo {@link AbstractConfig config}
+ *
+ * @param config the dubbo {@link AbstractConfig config}
+ */
+ public final <T extends AbstractConfig> T addConfig(AbstractConfig config) {
+ if (config == null) {
+ return null;
+ }
+ // ignore MethodConfig
+ if (!isSupportConfigType(config.getClass())) {
+ throw new IllegalArgumentException("Unsupported config type: " + config);
+ }
+
+ if (config.getScopeModel() != scopeModel) {
+ config.setScopeModel(scopeModel);
+ }
+
+ Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> new ConcurrentHashMap<>());
+
+ // fast check duplicated equivalent config before write lock
+ if (!(config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase)) {
+ for (AbstractConfig value : configsMap.values()) {
+ if (value.equals(config)) {
+ return (T) value;
+ }
+ }
+ }
+
+ // lock by config type
+ synchronized (configsMap) {
+ return (T) addIfAbsent(config, configsMap);
+ }
+ }
+
+ protected boolean isSupportConfigType(Class<? extends AbstractConfig> type) {
+ for (Class<? extends AbstractConfig> supportedConfigType : supportedConfigTypes) {
+ if (supportedConfigType.isAssignableFrom(type)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Add config
+ *
+ * @param config
+ * @param configsMap
+ * @return the existing equivalent config or the new adding config
+ * @throws IllegalStateException
+ */
+ private <C extends AbstractConfig> C addIfAbsent(C config, Map<String, C> configsMap)
+ throws IllegalStateException {
+
+ if (config == null || configsMap == null) {
+ return config;
+ }
+
+ // find by value
+ Optional<C> prevConfig = findDuplicatedConfig(configsMap, config);
+ if (prevConfig.isPresent()) {
+ return prevConfig.get();
+ }
+
+ String key = config.getId();
+ if (key == null) {
+ do {
+ // generate key if id is not set
+ key = generateConfigId(config);
+ } while (configsMap.containsKey(key));
+ }
+
+ C existedConfig = configsMap.get(key);
+ if (existedConfig != null && !isEquals(existedConfig, config)) {
+ String type = config.getClass().getSimpleName();
+ logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
+ "you can try to give each %s a different id, override previous config with later config. id: %s, prev: %s, later: %s",
+ type, type, type, type, key, existedConfig, config));
+ }
+
+ // override existed config if any
+ configsMap.put(key, config);
+ return config;
+ }
+
+ protected <C extends AbstractConfig> Optional<C> findDuplicatedConfig(Map<String, C> configsMap, C config) {
+ Optional<C> prevConfig = findConfigByValue(configsMap.values(), config);
+ if (prevConfig.isPresent()) {
+ if (prevConfig.get() == config) {
+ // the new one is same as existing one
+ return prevConfig;
+ }
+
+ // ignore duplicated equivalent config
+ if (logger.isInfoEnabled() && duplicatedConfigs.add(config)) {
+ logger.info("Ignore duplicated config: " + config);
+ }
+ return prevConfig;
+ }
+ return Optional.empty();
+ }
+
+ public <C extends AbstractConfig> Map<String, C> getConfigsMap(Class<C> cls) {
+ return getConfigsMap(getTagName(cls));
+ }
+
+ protected <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
+ return (Map<String, C>) configsCache.getOrDefault(configType, emptyMap());
+ }
+
+ protected <C extends AbstractConfig> Collection<C> getConfigs(String configType) {
+ return (Collection<C>) getConfigsMap(configType).values();
+ }
+
+ public <C extends AbstractConfig> Collection<C> getConfigs(Class<C> configType) {
+ return (Collection<C>) getConfigsMap(getTagName(configType)).values();
+ }
+
+ /**
+ * Get config by id
+ *
+ * @param configType
+ * @param id
+ * @return
+ */
+ protected <C extends AbstractConfig> C getConfigById(String configType, String id) {
+ return (C) getConfigsMap(configType).get(id);
+ }
+
+ /**
+ * Get config instance by id or by name
+ *
+ * @param cls Config type
+ * @param idOrName the id or name of the config
+ * @return
+ */
+ public <T extends AbstractConfig> Optional<T> getConfig(Class<T> cls, String idOrName) {
+ T config = getConfigById(getTagName(cls), idOrName);
+ if (config == null) {
+ config = getConfigByName(cls, idOrName);
+ }
+ return ofNullable(config);
+ }
+
+ /**
+ * Get config by name if existed
+ *
+ * @param cls
+ * @param name
+ * @return
+ */
+ protected <C extends AbstractConfig> C getConfigByName(Class<? extends C> cls, String name) {
+ Map<String, ? extends C> configsMap = getConfigsMap(cls);
+ if (configsMap.isEmpty()) {
+ return null;
+ }
+ // try find config by name
+ if (ReflectUtils.hasMethod(cls, CONFIG_NAME_READ_METHOD)) {
+ List<C> list = configsMap.values().stream()
+ .filter(cfg -> name.equals(getConfigName(cfg)))
+ .collect(Collectors.toList());
+ if (list.size() > 1) {
+ throw new IllegalStateException("Found more than one config by name: " + name +
+ ", instances: " + list + ". Please remove redundant configs or get config by id.");
+ } else if (list.size() == 1) {
+ return list.get(0);
+ }
+ }
+ return null;
+ }
+
+ private <C extends AbstractConfig> String getConfigName(C config) {
+ try {
+ return (String) ReflectUtils.getProperty(config, CONFIG_NAME_READ_METHOD);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ protected <C extends AbstractConfig> Optional<C> findConfigByValue(Collection<C> values, C config) {
+ // 1. find same config instance (speed up raw api usage)
+ Optional<C> prevConfig = values.stream().filter(val -> val == config).findFirst();
+ if (prevConfig.isPresent()) {
+ return prevConfig;
+ }
+
+ // 2. find equal config
+ prevConfig = values.stream()
+ .filter(val -> isEquals(val, config))
+ .findFirst();
+ return prevConfig;
+ }
+
+ protected boolean isEquals(AbstractConfig oldOne, AbstractConfig newOne) {
+ if (oldOne == newOne) {
+ return true;
+ }
+ if (oldOne == null || newOne == null) {
+ return false;
+ }
+ if (oldOne.getClass() != newOne.getClass()) {
+ return false;
+ }
+ // make both are refreshed or none is refreshed
+ if (oldOne.isRefreshed() || newOne.isRefreshed()) {
+ if (!oldOne.isRefreshed()) {
+ oldOne.refresh();
+ }
+ if (!newOne.isRefreshed()) {
+ newOne.refresh();
+ }
+ }
+ return oldOne.equals(newOne);
+ }
+
+ protected <C extends AbstractConfig> String generateConfigId(C config) {
+ String tagName = getTagName(config.getClass());
+ int idx = configIdIndexes.computeIfAbsent(tagName, clazz -> new AtomicInteger(0)).incrementAndGet();
+ return tagName + "#" + idx;
+ }
+
+ public <C extends AbstractConfig> List<C> getDefaultConfigs(Class<C> cls) {
+ return getDefaultConfigs(getConfigsMap(getTagName(cls)));
+ }
+
+ static <C extends AbstractConfig> Boolean isDefaultConfig(C config) {
+ return config.isDefault();
+ }
+
+ static <C extends AbstractConfig> List<C> getDefaultConfigs(Map<String, C> configsMap) {
+ // find isDefault() == true
+ List<C> list = configsMap.values()
+ .stream()
+ .filter(c -> TRUE.equals(AbstractConfigManager.isDefaultConfig(c)))
+ .collect(Collectors.toList());
+ if (list.size() > 0) {
+ return list;
+ }
+
+ // find isDefault() == null
+ list = configsMap.values()
+ .stream()
+ .filter(c -> AbstractConfigManager.isDefaultConfig(c) == null)
+ .collect(Collectors.toList());
+ return list;
+
+ // exclude isDefault() == false
+ }
+
+ public abstract void loadConfigs();
+
+ public <T extends AbstractConfig> void loadConfigsOfTypeFromProps(Class<T> cls) {
+ PropertiesConfiguration properties = applicationModel.getApplicationEnvironment().getPropertiesConfiguration();
+
+ // load multiple configs with id
+ Set<String> configIds = this.getConfigIdsFromProps(cls);
+ configIds.forEach(id -> {
+ if (!this.getConfig(cls, id).isPresent()) {
+ T config = null;
+ try {
+ config = createConfig(cls, scopeModel);
+ config.setId(id);
+ } catch (Exception e) {
+ throw new IllegalStateException("create config instance failed, id: " + id + ", type:" + cls.getSimpleName());
+ }
+
+ String key = null;
+ boolean addDefaultNameConfig = false;
+ try {
+ // add default name config (same as id), e.g. dubbo.protocols.rest.port=1234
+ key = DUBBO + "." + AbstractConfig.getPluralTagName(cls) + "." + id + ".name";
+ if (properties.getProperty(key) == null) {
+ properties.setProperty(key, id);
+ addDefaultNameConfig = true;
+ }
+
+ config.refresh();
+ this.addConfig(config);
+ } catch (Exception e) {
+ logger.error("load config failed, id: " + id + ", type:" + cls.getSimpleName(), e);
+ throw new IllegalStateException("load config failed, id: " + id + ", type:" + cls.getSimpleName());
+ } finally {
+ if (addDefaultNameConfig && key != null) {
+ properties.remove(key);
+ }
+ }
+ }
+ });
+
+ // If none config of the type, try load single config
+ if (this.getConfigs(cls).isEmpty()) {
+ // load single config
+ List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
+ if (ConfigurationUtils.hasSubProperties(configurationMaps, AbstractConfig.getTypePrefix(cls))) {
+ T config = null;
+ try {
+ config = createConfig(cls, scopeModel);
+ config.refresh();
+ } catch (Exception e) {
+ throw new IllegalStateException("create default config instance failed, type:" + cls.getSimpleName());
+ }
+
+ this.addConfig(config);
+ }
+ }
+
+ }
+
+ private <T extends AbstractConfig> T createConfig(Class<T> cls, ScopeModel scopeModel) throws ReflectiveOperationException {
+ T config = cls.newInstance();
+ config.setScopeModel(scopeModel);
+ return config;
+ }
+
+ /**
+ * Search props and extract config ids of specify type.
+ * <pre>
+ * # properties
+ * dubbo.registries.registry1.address=xxx
+ * dubbo.registries.registry2.port=xxx
+ *
+ * # extract
+ * Set configIds = getConfigIds(RegistryConfig.class)
+ *
+ * # result
+ * configIds: ["registry1", "registry2"]
+ * </pre>
+ *
+ * @param clazz config type
+ * @return ids of specify config type
+ */
+ private Set<String> getConfigIdsFromProps(Class<? extends AbstractConfig> clazz) {
+ String prefix = CommonConstants.DUBBO + "." + AbstractConfig.getPluralTagName(clazz) + ".";
+ return ConfigurationUtils.getSubIds(environment.getConfigurationMaps(), prefix);
+ }
+
+
+ protected <T extends AbstractConfig> void checkDefaultAndValidateConfigs(Class<T> configType) {
+ try {
+ if (shouldAddDefaultConfig(configType)) {
+ T config = createConfig(configType, scopeModel);
+ config.refresh();
+ if (!isNeedValidation(config) || config.isValid()) {
+ this.addConfig(config);
+ } else {
+ logger.info("Ignore invalid config: " + config);
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException("Add default config failed: " + configType.getSimpleName(), e);
+ }
+
+ //validate configs
+ Collection<T> configs = this.getConfigs(configType);
+ for (T config : configs) {
+ getConfigValidator().validate(config);
+ }
+
+ // check required default
+ if (isRequired(configType) && configs.isEmpty()) {
+ throw new IllegalStateException("Default config not found for " + configType.getSimpleName());
+ }
+ }
+
+ /**
+ * The component configuration that does not affect the main process does not need to be verified.
+ *
+ * @param config
+ * @param <T>
+ * @return
+ */
+ protected <T extends AbstractConfig> boolean isNeedValidation(T config) {
+ if (config instanceof MetadataReportConfig) {
+ return false;
+ }
+ return true;
+ }
+
+ private ConfigValidator getConfigValidator() {
+ if (configValidator == null) {
+ configValidator = applicationModel.getBeanFactory().getBean(ConfigValidator.class);
+ }
+ return configValidator;
+ }
+
+ /**
+ * The configuration that does not affect the main process is not necessary.
+ *
+ * @param clazz
+ * @param <T>
+ * @return
+ */
+ protected <T extends AbstractConfig> boolean isRequired(Class<T> clazz) {
+ if (clazz == RegistryConfig.class ||
+ clazz == MetadataReportConfig.class ||
+ clazz == MonitorConfig.class ||
+ clazz == ModuleConfig.class ||
+ clazz == MetricsConfig.class) {
+ return false;
+ }
+ return true;
+ }
+
+ private <T extends AbstractConfig> boolean shouldAddDefaultConfig(Class<T> clazz) {
+ // Configurations that are not required will not be automatically added to the default configuration
+ if (!isRequired(clazz)) {
+ return false;
+ }
+ return this.getDefaultConfigs(clazz).isEmpty();
+ }
+
+
+ public void refreshAll() {
+
+ }
+
+
+ /**
+ * In some scenario, we may nee to add and remove ServiceConfig or ReferenceConfig dynamically.
+ *
+ * @param config the config instance to remove.
+ * @return
+ */
+ public boolean removeConfig(AbstractConfig config) {
+ if (config == null) {
+ return false;
+ }
+
+ Map<String, AbstractConfig> configs = configsCache.get(getTagName(config.getClass()));
+ if (CollectionUtils.isNotEmptyMap(configs)) {
+ return configs.values().removeIf(c -> config == c);
+ }
+ return false;
+ }
+
+ @Override
+ public void destroy() throws IllegalStateException {
+ clear();
+ }
+
+ public void clear() {
+ this.configsCache.clear();
+ this.configIdIndexes.clear();
+ this.duplicatedConfigs.clear();
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index 7bae399..433121e 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -18,83 +18,55 @@ package org.apache.dubbo.config.context;
import org.apache.dubbo.common.config.CompositeConfiguration;
import org.apache.dubbo.common.context.FrameworkExt;
-import org.apache.dubbo.common.context.LifecycleAdapter;
import org.apache.dubbo.common.extension.DisableInject;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
-import org.apache.dubbo.config.AbstractInterfaceConfig;
-import org.apache.dubbo.config.AbstractMethodConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConfigKeys;
-import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.MetricsConfig;
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.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-import static java.lang.Boolean.TRUE;
-import static java.util.Collections.emptyMap;
import static java.util.Optional.ofNullable;
-import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.config.AbstractConfig.getTagName;
/**
* A lock-free config manager (through ConcurrentHashMap), for fast read operation.
* The Write operation lock with sub configs map of config type, for safely check and add new config.
*/
-public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
+public class ConfigManager extends AbstractConfigManager implements FrameworkExt {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
public static final String NAME = "config";
public static final String BEAN_NAME = "dubboConfigManager";
- private static final String CONFIG_NAME_READ_METHOD = "getName";
public static final String DUBBO_CONFIG_MODE = ConfigKeys.DUBBO_CONFIG_MODE;
- final Map<String, Map<String, AbstractConfig>> configsCache = new ConcurrentHashMap<>();
-
- private Map<String, AbstractInterfaceConfig> referenceConfigCache = new ConcurrentHashMap<>();
-
- private Map<String, AbstractInterfaceConfig> serviceConfigCache = new ConcurrentHashMap<>();
-
- private Set<AbstractConfig> duplicatedConfigs = new ConcurrentHashSet<>();
-
private ConfigMode configMode = ConfigMode.STRICT;
- private boolean ignoreDuplicatedInterface = false;
-
private ApplicationModel applicationModel;
private AtomicBoolean inited = new AtomicBoolean(false);
- private static Map<String, AtomicInteger> configIdIndexes = new ConcurrentHashMap<>();
-
private static Set<Class<? extends AbstractConfig>> uniqueConfigTypes = new ConcurrentHashSet<>();
static {
@@ -104,14 +76,12 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
uniqueConfigTypes.add(MonitorConfig.class);
uniqueConfigTypes.add(MetricsConfig.class);
uniqueConfigTypes.add(SslConfig.class);
-
- List<String> configNames = new ArrayList<>(uniqueConfigTypes.size());
- for (Class<? extends AbstractConfig> configType : uniqueConfigTypes) {
- configNames.add(configType.getSimpleName());
- }
}
public ConfigManager(ApplicationModel applicationModel) {
+ super(applicationModel, Arrays.asList(ApplicationConfig.class, ModuleConfig.class, MonitorConfig.class,
+ MetricsConfig.class, SslConfig.class, ProtocolConfig.class, RegistryConfig.class, ConfigCenterConfig.class,
+ MetadataReportConfig.class));
this.applicationModel = applicationModel;
}
@@ -132,12 +102,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
throw new IllegalArgumentException(msg, e);
}
- String ignoreDuplicatedInterfaceStr = (String) configuration
- .getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_DUPLICATED_INTERFACE);
- if (ignoreDuplicatedInterfaceStr != null) {
- this.ignoreDuplicatedInterface = Boolean.parseBoolean(ignoreDuplicatedInterfaceStr);
- }
- logger.info("Dubbo config mode: " + configMode + ", ignore duplicated interface: " + ignoreDuplicatedInterface);
+ logger.info("Config settings - config mode: " + configMode);
}
@@ -151,7 +116,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
*/
@DisableInject
public void setApplication(ApplicationConfig application) {
- addConfig(application, true);
+ addConfig(application);
}
public Optional<ApplicationConfig> getApplication() {
@@ -166,7 +131,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
@DisableInject
public void setMonitor(MonitorConfig monitor) {
- addConfig(monitor, true);
+ addConfig(monitor);
}
public Optional<MonitorConfig> getMonitor() {
@@ -177,7 +142,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
@DisableInject
public void setModule(ModuleConfig module) {
- addConfig(module, true);
+ addConfig(module);
}
public Optional<ModuleConfig> getModule() {
@@ -186,7 +151,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
@DisableInject
public void setMetrics(MetricsConfig metrics) {
- addConfig(metrics, true);
+ addConfig(metrics);
}
public Optional<MetricsConfig> getMetrics() {
@@ -195,7 +160,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
@DisableInject
public void setSsl(SslConfig sslConfig) {
- addConfig(sslConfig, true);
+ addConfig(sslConfig);
}
public Optional<SslConfig> getSsl() {
@@ -250,64 +215,6 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return defaults;
}
- // MetadataReportConfig correlative methods
-
- public void addProvider(ProviderConfig providerConfig) {
- addConfig(providerConfig);
- }
-
- public void addProviders(Iterable<ProviderConfig> providerConfigs) {
- providerConfigs.forEach(this::addProvider);
- }
-
- public Optional<ProviderConfig> getProvider(String id) {
- return getConfig(ProviderConfig.class, id);
- }
-
- /**
- * Only allows one default ProviderConfig
- */
- public Optional<ProviderConfig> getDefaultProvider() {
- List<ProviderConfig> providerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ProviderConfig.class)));
- if (CollectionUtils.isNotEmpty(providerConfigs)) {
- return Optional.of(providerConfigs.get(0));
- }
- return Optional.empty();
- }
-
- public Collection<ProviderConfig> getProviders() {
- return getConfigs(getTagName(ProviderConfig.class));
- }
-
- // ConsumerConfig correlative methods
-
- public void addConsumer(ConsumerConfig consumerConfig) {
- addConfig(consumerConfig);
- }
-
- public void addConsumers(Iterable<ConsumerConfig> consumerConfigs) {
- consumerConfigs.forEach(this::addConsumer);
- }
-
- public Optional<ConsumerConfig> getConsumer(String id) {
- return getConfig(ConsumerConfig.class, id);
- }
-
- /**
- * Only allows one default ConsumerConfig
- */
- public Optional<ConsumerConfig> getDefaultConsumer() {
- List<ConsumerConfig> consumerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ConsumerConfig.class)));
- if (CollectionUtils.isNotEmpty(consumerConfigs)) {
- return Optional.of(consumerConfigs.get(0));
- }
- return Optional.empty();
- }
-
- public Collection<ConsumerConfig> getConsumers() {
- return getConfigs(getTagName(ConsumerConfig.class));
- }
-
// ProtocolConfig correlative methods
public void addProtocol(ProtocolConfig protocolConfig) {
@@ -353,21 +260,6 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return getConfig(RegistryConfig.class, id);
}
- /**
- * Get config instance by id or by name
- *
- * @param cls Config type
- * @param idOrName the id or name of the config
- * @return
- */
- public <T extends AbstractConfig> Optional<T> getConfig(Class<T> cls, String idOrName) {
- T config = getConfigById(getTagName(cls), idOrName);
- if (config == null) {
- config = getConfigByName(cls, idOrName);
- }
- return ofNullable(config);
- }
-
public List<RegistryConfig> getDefaultRegistries() {
return getDefaultConfigs(getConfigsMap(getTagName(RegistryConfig.class)));
}
@@ -376,47 +268,6 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return getConfigs(getTagName(RegistryConfig.class));
}
- // ServiceConfig correlative methods
-
- public void addService(ServiceConfigBase<?> serviceConfig) {
- if (serviceConfig.getScopeModel() == null) {
- serviceConfig.setScopeModel(applicationModel.getDefaultModule());
- }
- addConfig(serviceConfig);
- }
-
- public void addServices(Iterable<ServiceConfigBase<?>> serviceConfigs) {
- serviceConfigs.forEach(this::addService);
- }
-
- public Collection<ServiceConfigBase> getServices() {
- return getConfigs(getTagName(ServiceConfigBase.class));
- }
-
- public <T> ServiceConfigBase<T> getService(String id) {
- return getConfig(ServiceConfigBase.class, id).orElse(null);
- }
-
- // ReferenceConfig correlative methods
-
- public void addReference(ReferenceConfigBase<?> referenceConfig) {
- if (referenceConfig.getScopeModel() == null) {
- referenceConfig.setScopeModel(applicationModel.getDefaultModule());
- }
- addConfig(referenceConfig);
- }
-
- public void addReferences(Iterable<ReferenceConfigBase<?>> referenceConfigs) {
- referenceConfigs.forEach(this::addReference);
- }
-
- public Collection<ReferenceConfigBase<?>> getReferences() {
- return getConfigs(getTagName(ReferenceConfigBase.class));
- }
-
- public <T> ReferenceConfigBase<T> getReference(String id) {
- return getConfig(ReferenceConfigBase.class, id).orElse(null);
- }
public void refreshAll() {
// refresh all configs here,
@@ -428,157 +279,20 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
getProtocols().forEach(ProtocolConfig::refresh);
getRegistries().forEach(RegistryConfig::refresh);
- getProviders().forEach(ProviderConfig::refresh);
- getConsumers().forEach(ConsumerConfig::refresh);
getConfigCenters().forEach(ConfigCenterConfig::refresh);
getMetadataConfigs().forEach(MetadataReportConfig::refresh);
}
- /**
- * In some scenario, we may nee to add and remove ServiceConfig or ReferenceConfig dynamically.
- *
- * @param config the config instance to remove.
- * @return
- */
- public boolean removeConfig(AbstractConfig config) {
- if (config == null) {
- return false;
- }
-
- Map<String, AbstractConfig> configs = configsCache.get(getTagName(config.getClass()));
- if (CollectionUtils.isNotEmptyMap(configs)) {
- return configs.values().removeIf(c -> config == c);
- }
- return false;
- }
-
- public void clear() {
- this.configsCache.clear();
- configIdIndexes.clear();
- this.referenceConfigCache.clear();
- this.serviceConfigCache.clear();
- this.duplicatedConfigs.clear();
- }
-
- /**
- * @throws IllegalStateException
- * @since 2.7.8
- */
- @Override
- public void destroy() throws IllegalStateException {
- clear();
- }
-
- /**
- * Add the dubbo {@link AbstractConfig config}
- *
- * @param config the dubbo {@link AbstractConfig config}
- */
- public void addConfig(AbstractConfig config) {
- if (config == null) {
- return;
- }
- if (config.getScopeModel() == null) {
- config.setScopeModel(applicationModel);
- }
- addConfig(config, isUniqueConfig(config));
- }
-
private boolean isUniqueConfig(AbstractConfig config) {
- return uniqueConfigTypes.contains(config.getClass());
- }
-
- protected <T extends AbstractConfig> T addConfig(AbstractConfig config, boolean unique) {
- if (config == null) {
- return null;
- }
-
- if(!(config instanceof AbstractMethodConfig)) {
- config.setScopeModel(applicationModel);
- }
-
- // ignore MethodConfig
- if (config instanceof MethodConfig) {
- return null;
- }
-
- Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> newMap());
-
- // fast check duplicated equivalent config before write lock
- if (!(config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase)) {
- for (AbstractConfig value : configsMap.values()) {
- if (value.equals(config)) {
- return (T) value;
- }
- }
- }
-
- // lock by config type
- synchronized (configsMap) {
- return (T) addIfAbsent(config, configsMap, unique);
- }
- }
-
- public <C extends AbstractConfig> Map<String, C> getConfigsMap(Class<C> cls) {
- return getConfigsMap(getTagName(cls));
- }
-
- private <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
- return (Map<String, C>) configsCache.getOrDefault(configType, emptyMap());
- }
-
- private <C extends AbstractConfig> Collection<C> getConfigs(String configType) {
- return (Collection<C>) getConfigsMap(configType).values();
- }
-
- public <C extends AbstractConfig> Collection<C> getConfigs(Class<C> configType) {
- return (Collection<C>) getConfigsMap(getTagName(configType)).values();
- }
-
- /**
- * Get config by id
- *
- * @param configType
- * @param id
- * @return
- */
- private <C extends AbstractConfig> C getConfigById(String configType, String id) {
- return (C) getConfigsMap(configType).get(id);
- }
-
- /**
- * Get config by name if existed
- *
- * @param cls
- * @param name
- * @return
- */
- private <C extends AbstractConfig> C getConfigByName(Class<? extends C> cls, String name) {
- Map<String, ? extends C> configsMap = getConfigsMap(cls);
- if (configsMap.isEmpty()) {
- return null;
+ if (uniqueConfigTypes.contains(config.getClass())) {
+ return true;
}
- // try find config by name
- if (ReflectUtils.hasMethod(cls, CONFIG_NAME_READ_METHOD)) {
- List<C> list = configsMap.values().stream()
- .filter(cfg -> name.equals(getConfigName(cfg)))
- .collect(Collectors.toList());
- if (list.size() > 1) {
- throw new IllegalStateException("Found more than one config by name: " + name +
- ", instances: " + list + ". Please remove redundant configs or get config by id.");
- } else if (list.size() == 1) {
- return list.get(0);
+ for (Class<? extends AbstractConfig> uniqueConfigType : uniqueConfigTypes) {
+ if (uniqueConfigType.isAssignableFrom(config.getClass())) {
+ return true;
}
}
- return null;
- }
-
- private <C extends AbstractConfig> String getConfigName(C config) {
- try {
- return (String) ReflectUtils.getProperty(config, CONFIG_NAME_READ_METHOD);
- } catch (Exception e) {
- return null;
- }
+ return false;
}
protected <C extends AbstractConfig> C getSingleConfig(String configType) throws IllegalStateException {
@@ -594,74 +308,26 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return (C) configsMap.values().iterator().next();
}
- private static boolean isEquals(AbstractConfig oldOne, AbstractConfig newOne) {
- if (oldOne == newOne) {
- return true;
- }
- if (oldOne == null || newOne == null) {
- return false;
- }
- if (oldOne.getClass() != newOne.getClass()) {
- return false;
- }
- // make both are refreshed or none is refreshed
- if (oldOne.isRefreshed() || newOne.isRefreshed()) {
- if (!oldOne.isRefreshed()) {
- oldOne.refresh();
- }
- if (!newOne.isRefreshed()) {
- newOne.refresh();
- }
- }
- return oldOne.equals(newOne);
- }
-
- private static Map newMap() {
- return new ConcurrentHashMap();
- }
-
- /**
- * Add config
- *
- * @param config
- * @param configsMap
- * @param unique
- * @return the existing equivalent config or the new adding config
- * @throws IllegalStateException
- */
- private <C extends AbstractConfig> C addIfAbsent(C config, Map<String, C> configsMap, boolean unique)
- throws IllegalStateException {
-
- if (config == null || configsMap == null) {
- return config;
- }
+ @Override
+ protected <C extends AbstractConfig> Optional<C> findDuplicatedConfig(Map<String, C> configsMap, C config) {
- // check duplicated configs
- // special check service and reference config by unique service name, speed up the processing of large number of instances
- if (config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase) {
- C existedConfig = (C) checkDuplicatedInterfaceConfig((AbstractInterfaceConfig) config);
- if (existedConfig != null) {
- return existedConfig;
+ // find by value
+ Optional<C> prevConfig = findConfigByValue(configsMap.values(), config);
+ if (prevConfig.isPresent()) {
+ if (prevConfig.get() == config) {
+ // the new one is same as existing one
+ return prevConfig;
}
- } else {
- // find by value
- Optional<C> prevConfig = findConfigByValue(configsMap.values(), config);
- if (prevConfig.isPresent()) {
- if (prevConfig.get() == config) {
- // the new one is same as existing one
- return prevConfig.get();
- }
- // ignore duplicated equivalent config
- if (logger.isInfoEnabled() && duplicatedConfigs.add(config)) {
- logger.info("Ignore duplicated config: " + config);
- }
- return prevConfig.get();
+ // ignore duplicated equivalent config
+ if (logger.isInfoEnabled() && duplicatedConfigs.add(config)) {
+ logger.info("Ignore duplicated config: " + config);
}
+ return prevConfig;
}
// check unique config
- if (unique && configsMap.size() > 0) {
+ if (configsMap.size() > 0 && isUniqueConfig(config)) {
C oldOne = configsMap.values().iterator().next();
String configName = oldOne.getClass().getSimpleName();
String msgPrefix = "Duplicate Configs found for " + configName + ", only one unique " + configName +
@@ -678,7 +344,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
if (logger.isWarnEnabled() && duplicatedConfigs.add(config)) {
logger.warn(msgPrefix + "keep previous config and ignore later config");
}
- return oldOne;
+ return Optional.of(oldOne);
}
case OVERRIDE: {
// clear previous config, add new config
@@ -690,126 +356,73 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
}
}
-
- String key = getId(config);
- if (key == null) {
- do {
- // generate key if id is not set
- key = generateConfigId(config);
- } while (configsMap.containsKey(key));
- }
-
- C existedConfig = configsMap.get(key);
- if (existedConfig != null && !isEquals(existedConfig, config)) {
- String type = config.getClass().getSimpleName();
- logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
- "you can try to give each %s a different id, override previous config with later config. id: %s, prev: %s, later: %s",
- type, type, type, type, key, existedConfig, config));
- }
-
- // override existed config if any
- configsMap.put(key, config);
- return config;
+ return Optional.empty();
}
- private <C extends AbstractConfig> Optional<C> findConfigByValue(Collection<C> values, C config) {
- // 1. find same config instance (speed up raw api usage)
- Optional<C> prevConfig = values.stream().filter(val -> val == config).findFirst();
- if (prevConfig.isPresent()) {
- return prevConfig;
- }
+ @Override
+ public void loadConfigs() {
+ // application config has load before starting config center
+ // load dubbo.applications.xxx
+ loadConfigsOfTypeFromProps(ApplicationConfig.class);
- // 2. find equal config
- prevConfig = values.stream()
- .filter(val -> isEquals(val, config))
- .findFirst();
- return prevConfig;
- }
+ // load dubbo.modules.xxx
+ loadConfigsOfTypeFromProps(ModuleConfig.class);
- /**
- * check duplicated ReferenceConfig/ServiceConfig
- *
- * @param config
- */
- private AbstractInterfaceConfig checkDuplicatedInterfaceConfig(AbstractInterfaceConfig config) {
- String uniqueServiceName;
- Map<String, AbstractInterfaceConfig> configCache;
- if (config instanceof ReferenceConfigBase) {
- return null;
- } else if (config instanceof ServiceConfigBase) {
- ServiceConfigBase serviceConfig = (ServiceConfigBase) config;
- uniqueServiceName = serviceConfig.getUniqueServiceName();
- configCache = serviceConfigCache;
- } else {
- throw new IllegalArgumentException("Illegal type of parameter 'config' : " + config.getClass().getName());
- }
+ // load dubbo.monitors.xxx
+ loadConfigsOfTypeFromProps(MonitorConfig.class);
- AbstractInterfaceConfig prevConfig = configCache.putIfAbsent(uniqueServiceName, config);
- if (prevConfig != null) {
- if (prevConfig == config) {
- return prevConfig;
- }
+ // load dubbo.metricses.xxx
+ loadConfigsOfTypeFromProps(MetricsConfig.class);
- if (prevConfig.equals(config)) {
- // TODO Is there any problem with ignoring duplicate and equivalent but different ReferenceConfig instances?
- if (logger.isWarnEnabled() && duplicatedConfigs.add(config)) {
- logger.warn("Ignore duplicated and equal config: " + config);
- }
- return prevConfig;
- }
+ // load multiple config types:
+ // load dubbo.protocols.xxx
+ loadConfigsOfTypeFromProps(ProtocolConfig.class);
- String configType = config.getClass().getSimpleName();
- String msg = "Found multiple " + configType + "s with unique service name [" +
- uniqueServiceName + "], previous: " + prevConfig + ", later: " + config + ". " +
- "There can only be one instance of " + configType + " with the same triple (group, interface, version). " +
- "If multiple instances are required for the same interface, please use a different group or version.";
+ // load dubbo.registries.xxx
+ loadConfigsOfTypeFromProps(RegistryConfig.class);
- if (logger.isWarnEnabled() && duplicatedConfigs.add(config)) {
- logger.warn(msg);
- }
- if (!ignoreDuplicatedInterface) {
- throw new IllegalStateException(msg);
- }
- }
- return prevConfig;
- }
+ // load dubbo.metadata-report.xxx
+ loadConfigsOfTypeFromProps(MetadataReportConfig.class);
- public static <C extends AbstractConfig> String generateConfigId(C config) {
- String tagName = getTagName(config.getClass());
- int idx = configIdIndexes.computeIfAbsent(tagName, clazz -> new AtomicInteger(0)).incrementAndGet();
- return tagName + "#" + idx;
- }
+ // config centers has bean loaded before starting config center
+ //loadConfigsOfTypeFromProps(ConfigCenterConfig.class);
- static <C extends AbstractConfig> String getId(C config) {
- String id = config.getId();
- return isNotEmpty(id) ? id : null;
+ checkConfigs();
}
- static <C extends AbstractConfig> Boolean isDefaultConfig(C config) {
- return config.isDefault();
- }
+ private void checkConfigs() {
+ // check config types (ignore metadata-center)
+ List<Class<? extends AbstractConfig>> multipleConfigTypes = Arrays.asList(
+ ApplicationConfig.class,
+ ProtocolConfig.class,
+ RegistryConfig.class,
+ MetadataReportConfig.class,
+ MonitorConfig.class,
+ ModuleConfig.class,
+ MetricsConfig.class,
+ SslConfig.class);
- static <C extends AbstractConfig> List<C> getDefaultConfigs(Map<String, C> configsMap) {
- // find isDefault() == true
- List<C> list = configsMap.values()
- .stream()
- .filter(c -> TRUE.equals(ConfigManager.isDefaultConfig(c)))
- .collect(Collectors.toList());
- if (list.size() > 0) {
- return list;
+ for (Class<? extends AbstractConfig> configType : multipleConfigTypes) {
+ checkDefaultAndValidateConfigs(configType);
}
- // find isDefault() == null
- list = configsMap.values()
- .stream()
- .filter(c -> ConfigManager.isDefaultConfig(c) == null)
- .collect(Collectors.toList());
- return list;
-
- // exclude isDefault() == false
+ // check port conflicts
+ Map<Integer, ProtocolConfig> protocolPortMap = new LinkedHashMap<>();
+ for (ProtocolConfig protocol : this.getProtocols()) {
+ Integer port = protocol.getPort();
+ if (port == null || port == -1) {
+ continue;
+ }
+ ProtocolConfig prevProtocol = protocolPortMap.get(port);
+ if (prevProtocol != null) {
+ throw new IllegalStateException("Duplicated port used by protocol configs, port: " + port +
+ ", configs: " + Arrays.asList(prevProtocol, protocol));
+ }
+ protocolPortMap.put(port, protocol);
+ }
}
- protected ConfigMode getConfigMode() {
+ ConfigMode getConfigMode() {
return configMode;
}
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
similarity index 64%
copy from dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
copy to dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
index 08a5e09..7d20b1b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
@@ -14,23 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.context;
+package org.apache.dubbo.config.context;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.apache.dubbo.config.AbstractConfig;
-/**
- * Dubbo spring initialization context object
- */
-public class DubboSpringInitializationContext {
-
- private BeanDefinitionRegistry registry;
-
- public BeanDefinitionRegistry getRegistry() {
- return registry;
- }
+public interface ConfigValidator {
- void setRegistry(BeanDefinitionRegistry registry) {
- this.registry = registry;
- }
+ void validate(AbstractConfig config);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ModuleConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ModuleConfigManager.java
new file mode 100644
index 0000000..753bf27
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ModuleConfigManager.java
@@ -0,0 +1,264 @@
+/*
+ * 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.CompositeConfiguration;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.ConfigKeys;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.ReferenceConfigBase;
+import org.apache.dubbo.config.ServiceConfigBase;
+import org.apache.dubbo.rpc.model.ModuleModel;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static org.apache.dubbo.config.AbstractConfig.getTagName;
+
+/**
+ * Manage configs of module
+ */
+public class ModuleConfigManager extends AbstractConfigManager {
+
+ private static final Logger logger = LoggerFactory.getLogger(ModuleConfigManager.class);
+
+ private Map<String, AbstractInterfaceConfig> serviceConfigCache = new ConcurrentHashMap<>();
+
+ private boolean ignoreDuplicatedInterface = false;
+
+ private AtomicBoolean inited = new AtomicBoolean(false);
+
+
+ public ModuleConfigManager(ModuleModel moduleModel) {
+ super(moduleModel, Arrays.asList(ServiceConfigBase.class, ReferenceConfigBase.class, ProviderConfig.class, ConsumerConfig.class));
+ }
+
+ @Override
+ public void initialize() throws IllegalStateException {
+ super.initialize();
+ if (!inited.compareAndSet(false, true)) {
+ return;
+ }
+ CompositeConfiguration configuration = applicationModel.getApplicationEnvironment().getConfiguration();
+
+ String ignoreDuplicatedInterfaceStr = (String) configuration
+ .getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_DUPLICATED_INTERFACE);
+ if (ignoreDuplicatedInterfaceStr != null) {
+ this.ignoreDuplicatedInterface = Boolean.parseBoolean(ignoreDuplicatedInterfaceStr);
+ }
+ logger.info("Config settings - ignore duplicated interface: " + ignoreDuplicatedInterface);
+ }
+
+ // ServiceConfig correlative methods
+
+ public void addService(ServiceConfigBase<?> serviceConfig) {
+ addConfig(serviceConfig);
+ }
+
+ public void addServices(Iterable<ServiceConfigBase<?>> serviceConfigs) {
+ serviceConfigs.forEach(this::addService);
+ }
+
+ public Collection<ServiceConfigBase> getServices() {
+ return getConfigs(getTagName(ServiceConfigBase.class));
+ }
+
+ public <T> ServiceConfigBase<T> getService(String id) {
+ return getConfig(ServiceConfigBase.class, id).orElse(null);
+ }
+
+ // ReferenceConfig correlative methods
+
+ public void addReference(ReferenceConfigBase<?> referenceConfig) {
+ addConfig(referenceConfig);
+ }
+
+ public void addReferences(Iterable<ReferenceConfigBase<?>> referenceConfigs) {
+ referenceConfigs.forEach(this::addReference);
+ }
+
+ public Collection<ReferenceConfigBase<?>> getReferences() {
+ return getConfigs(getTagName(ReferenceConfigBase.class));
+ }
+
+ public <T> ReferenceConfigBase<T> getReference(String id) {
+ return getConfig(ReferenceConfigBase.class, id).orElse(null);
+ }
+
+ public void addProvider(ProviderConfig providerConfig) {
+ addConfig(providerConfig);
+ }
+
+ public void addProviders(Iterable<ProviderConfig> providerConfigs) {
+ providerConfigs.forEach(this::addProvider);
+ }
+
+ public Optional<ProviderConfig> getProvider(String id) {
+ return getConfig(ProviderConfig.class, id);
+ }
+
+ /**
+ * Only allows one default ProviderConfig
+ */
+ public Optional<ProviderConfig> getDefaultProvider() {
+ List<ProviderConfig> providerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ProviderConfig.class)));
+ if (CollectionUtils.isNotEmpty(providerConfigs)) {
+ return Optional.of(providerConfigs.get(0));
+ }
+ return Optional.empty();
+ }
+
+ public Collection<ProviderConfig> getProviders() {
+ return getConfigs(getTagName(ProviderConfig.class));
+ }
+
+ // ConsumerConfig correlative methods
+
+ public void addConsumer(ConsumerConfig consumerConfig) {
+ addConfig(consumerConfig);
+ }
+
+ public void addConsumers(Iterable<ConsumerConfig> consumerConfigs) {
+ consumerConfigs.forEach(this::addConsumer);
+ }
+
+ public Optional<ConsumerConfig> getConsumer(String id) {
+ return getConfig(ConsumerConfig.class, id);
+ }
+
+ /**
+ * Only allows one default ConsumerConfig
+ */
+ public Optional<ConsumerConfig> getDefaultConsumer() {
+ List<ConsumerConfig> consumerConfigs = getDefaultConfigs(getConfigsMap(getTagName(ConsumerConfig.class)));
+ if (CollectionUtils.isNotEmpty(consumerConfigs)) {
+ return Optional.of(consumerConfigs.get(0));
+ }
+ return Optional.empty();
+ }
+
+ public Collection<ConsumerConfig> getConsumers() {
+ return getConfigs(getTagName(ConsumerConfig.class));
+ }
+
+ public void refreshAll() {
+ // refresh all configs here,
+ getProviders().forEach(ProviderConfig::refresh);
+ getConsumers().forEach(ConsumerConfig::refresh);
+
+ for (ReferenceConfigBase<?> reference : getReferences()) {
+ reference.refresh();
+ }
+
+ for (ServiceConfigBase sc : getServices()) {
+ sc.refresh();
+ }
+ }
+
+ public void clear() {
+ super.clear();
+ this.serviceConfigCache.clear();
+ }
+
+
+ @Override
+ protected <C extends AbstractConfig> Optional<C> findDuplicatedConfig(Map<String, C> configsMap, C config) {
+ // check duplicated configs
+ // special check service and reference config by unique service name, speed up the processing of large number of instances
+ if (config instanceof ReferenceConfigBase || config instanceof ServiceConfigBase) {
+ C existedConfig = (C) findDuplicatedInterfaceConfig((AbstractInterfaceConfig) config);
+ if (existedConfig != null) {
+ return Optional.of(existedConfig);
+ }
+ } else {
+ return super.findDuplicatedConfig(configsMap, config);
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * check duplicated ReferenceConfig/ServiceConfig
+ *
+ * @param config
+ */
+ private AbstractInterfaceConfig findDuplicatedInterfaceConfig(AbstractInterfaceConfig config) {
+ String uniqueServiceName;
+ Map<String, AbstractInterfaceConfig> configCache;
+ if (config instanceof ReferenceConfigBase) {
+ return null;
+ } else if (config instanceof ServiceConfigBase) {
+ ServiceConfigBase serviceConfig = (ServiceConfigBase) config;
+ uniqueServiceName = serviceConfig.getUniqueServiceName();
+ configCache = serviceConfigCache;
+ } else {
+ throw new IllegalArgumentException("Illegal type of parameter 'config' : " + config.getClass().getName());
+ }
+
+ AbstractInterfaceConfig prevConfig = configCache.putIfAbsent(uniqueServiceName, config);
+ if (prevConfig != null) {
+ if (prevConfig == config) {
+ return prevConfig;
+ }
+
+ if (prevConfig.equals(config)) {
+ // Is there any problem with ignoring duplicate and equivalent but different ReferenceConfig instances?
+ if (logger.isWarnEnabled() && duplicatedConfigs.add(config)) {
+ logger.warn("Ignore duplicated and equal config: " + config);
+ }
+ return prevConfig;
+ }
+
+ String configType = config.getClass().getSimpleName();
+ String msg = "Found multiple " + configType + "s with unique service name [" +
+ uniqueServiceName + "], previous: " + prevConfig + ", later: " + config + ". " +
+ "There can only be one instance of " + configType + " with the same triple (group, interface, version). " +
+ "If multiple instances are required for the same interface, please use a different group or version.";
+
+ if (logger.isWarnEnabled() && duplicatedConfigs.add(config)) {
+ logger.warn(msg);
+ }
+ if (!ignoreDuplicatedInterface) {
+ throw new IllegalStateException(msg);
+ }
+ }
+ return prevConfig;
+ }
+
+ @Override
+ public void loadConfigs() {
+ // load dubbo.providers.xxx
+ loadConfigsOfTypeFromProps(ProviderConfig.class);
+
+ // load dubbo.consumers.xxx
+ loadConfigsOfTypeFromProps(ConsumerConfig.class);
+
+ // check configs
+ checkDefaultAndValidateConfigs(ProviderConfig.class);
+ checkDefaultAndValidateConfigs(ConsumerConfig.class);
+ }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index ad6e309..b7d84e6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@ -18,11 +18,13 @@ package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.context.FrameworkExt;
+import org.apache.dubbo.common.deploy.ApplicationDeployer;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
+import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
@@ -31,7 +33,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicInteger;
/**
* {@link ExtensionLoader}, {@code DubboBootstrap} and this class are at present designed to be
@@ -49,7 +51,6 @@ import java.util.concurrent.atomic.AtomicLong;
public class ApplicationModel extends ScopeModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
- private static final AtomicLong index = new AtomicLong(0);
public static final String NAME = "ApplicationModel";
private static volatile ApplicationModel defaultInstance;
@@ -62,6 +63,11 @@ public class ApplicationModel extends ScopeModel {
private ModuleModel internalModule;
+ private volatile ModuleModel defaultModule;
+
+ // internal module index is 0, default module index is 1
+ private AtomicInteger moduleIndex = new AtomicInteger(0);
+
// --------- static methods ----------//
@@ -152,16 +158,16 @@ public class ApplicationModel extends ScopeModel {
public ApplicationModel(FrameworkModel frameworkModel) {
super(frameworkModel, ExtensionScope.APPLICATION);
+ Assert.notNull(frameworkModel, "FrameworkModel can not be null");
this.frameworkModel = frameworkModel;
frameworkModel.addApplication(this);
initialize();
- this.modelName = NAME + "-" + index.getAndIncrement();
}
@Override
protected void initialize() {
super.initialize();
- internalModule = new ModuleModel(this.modelName + "-internal", this);
+ internalModule = new ModuleModel(this);
this.serviceRepository = new ServiceRepository(this);
ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
@@ -177,8 +183,6 @@ public class ApplicationModel extends ScopeModel {
for (ScopeModelInitializer initializer : initializers) {
initializer.initializeApplicationModel(this);
}
-
- postProcessAfterCreated();
}
private void initFrameworkExts() {
@@ -223,6 +227,10 @@ public class ApplicationModel extends ScopeModel {
return frameworkModel;
}
+ public synchronized ModuleModel newModule() {
+ return new ModuleModel(this);
+ }
+
public Environment getApplicationEnvironment() {
if (environment == null) {
environment = (Environment) this.getExtensionLoader(FrameworkExt.class)
@@ -255,33 +263,47 @@ public class ApplicationModel extends ScopeModel {
return getCurrentConfig().getName();
}
- public synchronized void addModule(ModuleModel model) {
- if (!this.moduleModels.contains(model)) {
- this.moduleModels.add(model);
+ synchronized void addModule(ModuleModel moduleModel) {
+ if (!this.moduleModels.contains(moduleModel)) {
+ this.moduleModels.add(moduleModel);
+ moduleModel.setInternalName(buildInternalName(ModuleModel.NAME, getInternalId(), moduleIndex.getAndIncrement()));
}
}
- public synchronized void removeModule(ModuleModel model) {
- this.moduleModels.remove(model);
+ synchronized void removeModule(ModuleModel moduleModel) {
+ this.moduleModels.remove(moduleModel);
+ if (moduleModel == defaultModule) {
+ defaultModule = findDefaultModule();
+ }
if (this.moduleModels.size() == 1 && this.moduleModels.get(0) == internalModule) {
this.internalModule.destroy();
}
- destroy();
+ if (this.moduleModels.isEmpty()) {
+ destroy();
+ }
}
public List<ModuleModel> getModuleModels() {
- return moduleModels;
+ return Collections.unmodifiableList(moduleModels);
}
public synchronized ModuleModel getDefaultModule() {
+ if (defaultModule == null) {
+ defaultModule = findDefaultModule();
+ if (defaultModule == null) {
+ defaultModule = this.newModule();
+ }
+ }
+ return defaultModule;
+ }
+
+ private ModuleModel findDefaultModule() {
for (ModuleModel moduleModel : moduleModels) {
if (moduleModel != internalModule) {
return moduleModel;
}
}
- ModuleModel moduleModel = new ModuleModel(this);
- this.addModule(moduleModel);
- return moduleModel;
+ return null;
}
public ModuleModel getInternalModule() {
@@ -327,4 +349,12 @@ public class ApplicationModel extends ScopeModel {
protected boolean containsClassLoader(ClassLoader classLoader) {
return moduleModels.stream().anyMatch(moduleModel -> moduleModel.getClassLoaders().contains(classLoader));
}
+
+ public ApplicationDeployer getDeployer() {
+ return getAttribute(ModelConstants.DEPLOYER, ApplicationDeployer.class);
+ }
+
+ public void setDeployer(ApplicationDeployer deployer) {
+ setAttribute(ModelConstants.DEPLOYER, deployer);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
index 53ee49c..547485f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/FrameworkModel.java
@@ -34,8 +34,11 @@ public class FrameworkModel extends ScopeModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(FrameworkModel.class);
- private static final AtomicLong index = new AtomicLong(0);
public static final String NAME = "FrameworkModel";
+ private static final AtomicLong index = new AtomicLong(1);
+ // app index starts from 1 in each FrameworkModel
+ private final AtomicLong appIndex = new AtomicLong(1);
+
private volatile static FrameworkModel defaultInstance;
private static List<FrameworkModel> allInstances = Collections.synchronizedList(new ArrayList<>());
@@ -45,10 +48,11 @@ public class FrameworkModel extends ScopeModel {
private FrameworkServiceRepository serviceRepository;
+
public FrameworkModel() {
super(null, ExtensionScope.FRAMEWORK);
initialize();
- this.modelName = NAME + "-" + index.getAndIncrement();
+ this.setInternalName(buildInternalName(NAME, null, index.getAndIncrement()));
}
@Override
@@ -62,9 +66,6 @@ public class FrameworkModel extends ScopeModel {
for (ScopeModelInitializer initializer : initializers) {
initializer.initializeFrameworkModel(this);
}
-
-
- postProcessAfterCreated();
}
@Override
@@ -105,13 +106,18 @@ public class FrameworkModel extends ScopeModel {
}
}
- public void addApplication(ApplicationModel model) {
- if (!this.applicationModels.contains(model)) {
- this.applicationModels.add(model);
+ public ApplicationModel newApplication() {
+ return new ApplicationModel(this);
+ }
+
+ synchronized void addApplication(ApplicationModel applicationModel) {
+ if (!this.applicationModels.contains(applicationModel)) {
+ this.applicationModels.add(applicationModel);
+ applicationModel.setInternalName(buildInternalName(ApplicationModel.NAME, getInternalId(), appIndex.getAndIncrement()));
}
}
- public void removeApplication(ApplicationModel model) {
+ synchronized void removeApplication(ApplicationModel model) {
this.applicationModels.remove(model);
if (applicationModels.size() == 0) {
destroy();
@@ -119,7 +125,7 @@ public class FrameworkModel extends ScopeModel {
}
public List<ApplicationModel> getApplicationModels() {
- return applicationModels;
+ return Collections.unmodifiableList(applicationModels);
}
public FrameworkServiceRepository getServiceRepository() {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelConstants.java
similarity index 65%
copy from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
copy to dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelConstants.java
index 5a78a3f..d226d6d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModelConstants.java
@@ -16,19 +16,8 @@
*/
package org.apache.dubbo.rpc.model;
-import org.apache.dubbo.common.extension.ExtensionScope;
-import org.apache.dubbo.common.extension.SPI;
+public interface ModelConstants {
-/**
- * A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel)
- */
-@SPI(scope = ExtensionScope.FRAMEWORK)
-public interface ScopeModelPostProcessor {
-
- /**
- * Post-process after a scope model is created.
- * @param scopeModel
- */
- void postProcessScopeModel(ScopeModel scopeModel);
+ String DEPLOYER = "deployer";
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
index 81e9114..5f16a6f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ModuleModel.java
@@ -16,10 +16,13 @@
*/
package org.apache.dubbo.rpc.model;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import java.util.List;
import java.util.Set;
@@ -36,31 +39,29 @@ public class ModuleModel extends ScopeModel {
private final ApplicationModel applicationModel;
private ModuleServiceRepository serviceRepository;
+ private ModuleConfigManager moduleConfigManager;
- public ModuleModel(ApplicationModel applicationModel) {
- this(NAME + "-" + index.getAndIncrement(), applicationModel);
- }
- public ModuleModel(String name, ApplicationModel applicationModel) {
+ public ModuleModel(ApplicationModel applicationModel) {
super(applicationModel, ExtensionScope.MODULE);
+ Assert.notNull(applicationModel, "ApplicationModel can not be null");
this.applicationModel = applicationModel;
applicationModel.addModule(this);
initialize();
- this.modelName = name;
}
@Override
protected void initialize() {
super.initialize();
this.serviceRepository = new ModuleServiceRepository(this);
+ this.moduleConfigManager = new ModuleConfigManager(this);
+ this.moduleConfigManager.initialize();
ExtensionLoader<ScopeModelInitializer> initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class);
Set<ScopeModelInitializer> initializers = initializerExtensionLoader.getSupportedExtensionInstances();
for (ScopeModelInitializer initializer : initializers) {
initializer.initializeModuleModel(this);
}
-
- postProcessAfterCreated();
}
@Override
@@ -108,4 +109,16 @@ public class ModuleModel extends ScopeModel {
public ModuleServiceRepository getServiceRepository() {
return serviceRepository;
}
+
+ public ModuleConfigManager getConfigManager() {
+ return moduleConfigManager;
+ }
+
+ public ModuleDeployer getDeployer() {
+ return getAttribute(ModelConstants.DEPLOYER, ModuleDeployer.class);
+ }
+
+ public void setDeployer(ModuleDeployer deployer) {
+ setAttribute(ModelConstants.DEPLOYER, deployer);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
index 4b1d9ed..b22e0e9 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModel.java
@@ -33,7 +33,21 @@ import java.util.concurrent.atomic.AtomicBoolean;
public abstract class ScopeModel implements ExtensionAccessor {
- protected String modelName;
+ /**
+ * The internal name is used to represent the hierarchy of the model tree, such as:
+ * <ol>
+ * <li>FrameworkModel-1</li>
+ * FrameworkModel (index=1)
+ * <li>ApplicationModel-1.2</li>
+ * FrameworkModel (index=1) -> ApplicationModel (index=2)
+ * <li>ModuleModel-1.2.0</li>
+ * FrameworkModel (index=1) -> ApplicationModel (index=2) -> ModuleModel (index=0, internal module)
+ * <li>ModuleModel-1.2.1</li>
+ * FrameworkModel (index=1) -> ApplicationModel (index=2) -> ModuleModel (index=1, first user module)
+ * </ol>
+ */
+ private String internalName;
+
private Set<ClassLoader> classLoaders;
private final ScopeModel parent;
@@ -44,7 +58,7 @@ public abstract class ScopeModel implements ExtensionAccessor {
private ScopeBeanFactory beanFactory;
private List<ScopeModelDestroyListener> destroyListeners;
- private Map<String, Object> attribute;
+ private Map<String, Object> attributes;
private AtomicBoolean destroyed = new AtomicBoolean(false);
public ScopeModel(ScopeModel parent, ExtensionScope scope) {
@@ -66,7 +80,7 @@ public abstract class ScopeModel implements ExtensionAccessor {
this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector);
this.destroyListeners = new LinkedList<>();
- this.attribute = new ConcurrentHashMap<>();
+ this.attributes = new ConcurrentHashMap<>();
this.classLoaders = new ConcurrentHashSet<>();
// Add Framework's ClassLoader by default
@@ -84,7 +98,7 @@ public abstract class ScopeModel implements ExtensionAccessor {
removeClassLoader(classLoader);
}
onDestroy();
- }catch (Throwable t) {
+ } catch (Throwable t) {
t.printStackTrace();
}
}
@@ -102,8 +116,20 @@ public abstract class ScopeModel implements ExtensionAccessor {
destroyListeners.add(listener);
}
- public Map<String, Object> getAttribute() {
- return attribute;
+ public Map<String, Object> getAttributes() {
+ return attributes;
+ }
+
+ public <T> T getAttribute(String key, Class<T> type) {
+ return (T) attributes.get(key);
+ }
+
+ public Object getAttribute(String key) {
+ return attributes.get(key);
+ }
+
+ public void setAttribute(String key, Object value) {
+ attributes.put(key, value);
}
public ExtensionDirector getExtensionDirector() {
@@ -118,20 +144,12 @@ public abstract class ScopeModel implements ExtensionAccessor {
return parent;
}
- protected void postProcessAfterCreated() {
- Set<ScopeModelPostProcessor> scopeModelPostProcessors = getExtensionLoader(ScopeModelPostProcessor.class)
- .getSupportedExtensionInstances();
- for (ScopeModelPostProcessor processor : scopeModelPostProcessors) {
- processor.postProcessScopeModel(this);
- }
+ public String getInternalName() {
+ return internalName;
}
- public String getModelName() {
- return modelName;
- }
-
- public void setModelName(String modelName) {
- this.modelName = modelName;
+ protected void setInternalName(String internalName) {
+ this.internalName = internalName;
}
public void addClassLoader(ClassLoader classLoader) {
@@ -159,4 +177,23 @@ public abstract class ScopeModel implements ExtensionAccessor {
public Set<ClassLoader> getClassLoaders() {
return Collections.unmodifiableSet(classLoaders);
}
+
+ public String getInternalId() {
+ // XxxModule-1.1
+ if (this.internalName == null) {
+ return null;
+ }
+ return this.internalName.substring(this.internalName.indexOf('-') + 1);
+ }
+
+ protected String buildInternalName(String type, String parentInternalId, long childIndex) {
+ // FrameworkModel-1
+ // ApplicationModel-1.1
+ // ModuleModel-1.1.1
+ if (parentInternalId != null) {
+ return type + "-" + parentInternalId + "." + childIndex;
+ } else {
+ return type + "-" + childIndex;
+ }
+ }
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/AdaptiveCompilerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/AdaptiveCompilerTest.java
index 8252470..4192c36 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/AdaptiveCompilerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/compiler/support/AdaptiveCompilerTest.java
@@ -17,7 +17,6 @@
package org.apache.dubbo.common.compiler.support;
import org.apache.dubbo.rpc.model.FrameworkModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
index 0a68d06..e0031d4 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/ExtensionDirectorTest.java
@@ -25,7 +25,6 @@ import org.apache.dubbo.common.extension.director.impl.TestModuleService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/ActivateComparatorTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/ActivateComparatorTest.java
index 29d8b1c..c6baf04 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/ActivateComparatorTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/extension/support/ActivateComparatorTest.java
@@ -17,7 +17,6 @@
package org.apache.dubbo.common.extension.support;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/lang/ShutdownHookCallbacksTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/lang/ShutdownHookCallbacksTest.java
index c599148..6d0e7a4 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/lang/ShutdownHookCallbacksTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/lang/ShutdownHookCallbacksTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.lang;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -34,7 +35,7 @@ public class ShutdownHookCallbacksTest {
@BeforeEach
public void init() {
- callbacks = new ShutdownHookCallbacks();
+ callbacks = new ShutdownHookCallbacks(ApplicationModel.defaultModel());
}
@Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerFactoryTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerFactoryTest.java
index c83765f..685569c 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerFactoryTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/logger/LoggerFactoryTest.java
@@ -17,7 +17,6 @@
package org.apache.dubbo.common.logger;
import org.apache.dubbo.rpc.model.FrameworkModel;
-
import org.junit.jupiter.api.Test;
import java.io.File;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
index 76f6977..5fda7ff 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/ConfigUtilsTest.java
@@ -21,7 +21,6 @@ import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.threadpool.ThreadPool;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsInterfaceDisplayNameHasMetaCharactersTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsInterfaceDisplayNameHasMetaCharactersTest.java
index e927c50..6e6ce36 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsInterfaceDisplayNameHasMetaCharactersTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/NetUtilsInterfaceDisplayNameHasMetaCharactersTest.java
@@ -20,10 +20,10 @@ import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
-import java.util.Enumeration;
-import java.util.NoSuchElementException;
import java.net.InetAddress;
import java.net.NetworkInterface;
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_NETWORK_IGNORED_INTERFACE;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -110,4 +110,4 @@ public class NetUtilsInterfaceDisplayNameHasMetaCharactersTest {
}
}
-}
\ No newline at end of file
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
index a80fffd..8894252 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
@@ -26,7 +26,6 @@ import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -50,6 +49,7 @@ import static org.junit.jupiter.api.Assertions.fail;
public class ConfigManagerTest {
private ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
+ private ModuleConfigManager moduleConfigManager = ApplicationModel.defaultModel().getDefaultModule().getConfigManager();
@BeforeEach
public void init() {
@@ -69,12 +69,6 @@ public class ConfigManagerTest {
assertFalse(configManager.getModule().isPresent());
assertFalse(configManager.getMetrics().isPresent());
- // providers and consumers
- assertFalse(configManager.getDefaultProvider().isPresent());
- assertFalse(configManager.getDefaultConsumer().isPresent());
- assertTrue(configManager.getProviders().isEmpty());
- assertTrue(configManager.getConsumers().isEmpty());
-
// protocols
assertTrue(configManager.getProtocols().isEmpty());
assertTrue(configManager.getDefaultProtocols().isEmpty());
@@ -83,15 +77,21 @@ public class ConfigManagerTest {
assertTrue(configManager.getRegistries().isEmpty());
assertTrue(configManager.getDefaultRegistries().isEmpty());
- // services and references
- assertTrue(configManager.getServices().isEmpty());
- assertTrue(configManager.getReferences().isEmpty());
-
// config centers
assertTrue(configManager.getConfigCenters().isEmpty());
// metadata
assertTrue(configManager.getMetadataConfigs().isEmpty());
+
+ // services and references
+ assertTrue(moduleConfigManager.getServices().isEmpty());
+ assertTrue(moduleConfigManager.getReferences().isEmpty());
+
+ // providers and consumers
+ assertFalse(moduleConfigManager.getDefaultProvider().isPresent());
+ assertFalse(moduleConfigManager.getDefaultConsumer().isPresent());
+ assertTrue(moduleConfigManager.getProviders().isEmpty());
+ assertTrue(moduleConfigManager.getConsumers().isEmpty());
}
// Test ApplicationConfig correlative methods
@@ -135,18 +135,18 @@ public class ConfigManagerTest {
@Test
public void testProviderConfig() {
ProviderConfig config = new ProviderConfig();
- configManager.addProviders(asList(config, null));
- Collection<ProviderConfig> configs = configManager.getProviders();
+ moduleConfigManager.addProviders(asList(config, null));
+ Collection<ProviderConfig> configs = moduleConfigManager.getProviders();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
- assertTrue(configManager.getDefaultProvider().isPresent());
+ assertTrue(moduleConfigManager.getDefaultProvider().isPresent());
config = new ProviderConfig();
config.setId(DEFAULT_KEY);
config.setQueues(10);
- configManager.addProvider(config);
- assertTrue(configManager.getDefaultProvider().isPresent());
- configs = configManager.getProviders();
+ moduleConfigManager.addProvider(config);
+ assertTrue(moduleConfigManager.getDefaultProvider().isPresent());
+ configs = moduleConfigManager.getProviders();
assertEquals(2, configs.size());
}
@@ -154,18 +154,18 @@ public class ConfigManagerTest {
@Test
public void testConsumerConfig() {
ConsumerConfig config = new ConsumerConfig();
- configManager.addConsumers(asList(config, null));
- Collection<ConsumerConfig> configs = configManager.getConsumers();
+ moduleConfigManager.addConsumers(asList(config, null));
+ Collection<ConsumerConfig> configs = moduleConfigManager.getConsumers();
assertEquals(1, configs.size());
assertEquals(config, configs.iterator().next());
- assertTrue(configManager.getDefaultConsumer().isPresent());
+ assertTrue(moduleConfigManager.getDefaultConsumer().isPresent());
config = new ConsumerConfig();
config.setId(DEFAULT_KEY);
config.setThreads(10);
- configManager.addConsumer(config);
- assertTrue(configManager.getDefaultConsumer().isPresent());
- configs = configManager.getConsumers();
+ moduleConfigManager.addConsumer(config);
+ assertTrue(moduleConfigManager.getDefaultConsumer().isPresent());
+ configs = moduleConfigManager.getConsumers();
assertEquals(2, configs.size());
}
@@ -216,12 +216,12 @@ public class ConfigManagerTest {
@Test
public void testAddConfig() {
configManager.addConfig(new ApplicationConfig("ConfigManagerTest"));
- configManager.addConfig(new ProviderConfig());
configManager.addConfig(new ProtocolConfig());
+ moduleConfigManager.addConfig(new ProviderConfig());
assertTrue(configManager.getApplication().isPresent());
- assertFalse(configManager.getProviders().isEmpty());
assertFalse(configManager.getProtocols().isEmpty());
+ assertFalse(moduleConfigManager.getProviders().isEmpty());
}
@Test
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
similarity index 59%
copy from dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java
copy to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
index 8caab81..994116d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
@@ -14,16 +14,21 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.common;
+package org.apache.dubbo.config;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
-import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
+import org.apache.dubbo.common.deploy.ApplicationDeployer;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
+import org.apache.dubbo.config.bootstrap.DefaultApplicationDeployer;
+import org.apache.dubbo.config.bootstrap.DefaultModuleDeployer;
+import org.apache.dubbo.config.utils.DefaultConfigValidator;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModelInitializer;
-public class CommonScopeModelInitializer implements ScopeModelInitializer {
+public class ConfigScopeModelInitializer implements ScopeModelInitializer {
+
@Override
public void initializeFrameworkModel(FrameworkModel frameworkModel) {
@@ -32,11 +37,19 @@ public class CommonScopeModelInitializer implements ScopeModelInitializer {
@Override
public void initializeApplicationModel(ApplicationModel applicationModel) {
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
- beanFactory.registerBean(FrameworkStatusReportService.class);
+ beanFactory.registerBean(DubboShutdownHook.class);
+ beanFactory.registerBean(DefaultConfigValidator.class);
+ // applicationDeployer
+ ApplicationDeployer applicationDeployer = beanFactory.registerBean(DefaultApplicationDeployer.class);
+ applicationModel.setDeployer(applicationDeployer);
+
}
@Override
public void initializeModuleModel(ModuleModel moduleModel) {
-
+ ScopeBeanFactory beanFactory = moduleModel.getBeanFactory();
+ // moduleDeployer
+ ModuleDeployer moduleDeployer = beanFactory.registerBean(DefaultModuleDeployer.class);
+ moduleModel.setDeployer(moduleDeployer);
}
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
index 9e03a23..45daa42 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
@@ -16,10 +16,14 @@
*/
package org.apache.dubbo.config;
+import org.apache.dubbo.common.lang.ShutdownHookCallback;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.Assert;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
/**
@@ -32,9 +36,7 @@ public class DubboShutdownHook extends Thread {
private static final Logger logger = LoggerFactory.getLogger(DubboShutdownHook.class);
- private static final DubboShutdownHook DUBBO_SHUTDOWN_HOOK = new DubboShutdownHook("DubboShutdownHook");
-
- private final ShutdownHookCallbacks callbacks = ShutdownHookCallbacks.INSTANCE;
+ private final ShutdownHookCallbacks callbacks;
/**
* Has it already been registered or not?
@@ -46,13 +48,15 @@ public class DubboShutdownHook extends Thread {
*/
private final AtomicBoolean destroyed = new AtomicBoolean(false);
- private DubboShutdownHook(String name) {
- super(name);
+ public DubboShutdownHook(ApplicationModel applicationModel) {
+ super("DubboShutdownHook");
+ this.callbacks = applicationModel.getBeanFactory().getBean(ShutdownHookCallbacks.class);
+ Assert.notNull(this.callbacks, "ShutdownHookCallbacks is null");
}
- public static DubboShutdownHook getDubboShutdownHook() {
- return DUBBO_SHUTDOWN_HOOK;
- }
+// public static DubboShutdownHook getDubboShutdownHook() {
+// return DUBBO_SHUTDOWN_HOOK;
+// }
@Override
public void run() {
@@ -85,13 +89,21 @@ public class DubboShutdownHook extends Thread {
callbacks.callback();
}
+ public DubboShutdownHook addCallback(ShutdownHookCallback callback) {
+ callbacks.addCallback(callback);
+ return this;
+ }
+
+ public Collection<ShutdownHookCallback> getCallbacks() {
+ return callbacks.getCallbacks();
+ }
+
/**
* Register the ShutdownHook
*/
public void register() {
if (registered.compareAndSet(false, true)) {
- DubboShutdownHook dubboShutdownHook = getDubboShutdownHook();
- Runtime.getRuntime().addShutdownHook(dubboShutdownHook);
+ Runtime.getRuntime().addShutdownHook(this);
}
}
@@ -100,8 +112,7 @@ public class DubboShutdownHook extends Thread {
*/
public void unregister() {
if (registered.compareAndSet(true, false)) {
- DubboShutdownHook dubboShutdownHook = getDubboShutdownHook();
- Runtime.getRuntime().removeShutdownHook(dubboShutdownHook);
+ Runtime.getRuntime().removeShutdownHook(this);
}
}
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 0dade4d..e13400e 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
@@ -29,7 +29,6 @@ import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.common.utils.UrlUtils;
import org.apache.dubbo.config.annotation.Reference;
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.registry.client.metadata.MetadataUtils;
@@ -40,6 +39,7 @@ import org.apache.dubbo.rpc.cluster.Cluster;
import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
import org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.AsyncMethodInfo;
import org.apache.dubbo.rpc.model.ConsumerModel;
import org.apache.dubbo.rpc.model.ModuleServiceRepository;
@@ -134,8 +134,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
*/
private transient volatile boolean destroyed;
- private DubboBootstrap bootstrap;
-
/**
* The service names that the Dubbo interface subscribed.
*
@@ -152,8 +150,8 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
}
@Override
- protected void postProcessAfterScopeModelChanged() {
- super.postProcessAfterScopeModelChanged();
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
@@ -210,6 +208,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
@Override
public synchronized void destroy() {
+ super.destroy();
if (destroyed) {
return;
}
@@ -227,6 +226,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
ModuleServiceRepository repository = getScopeModel().getServiceRepository();
repository.unregisterConsumer(consumerModel);
}
+ getScopeModel().getConfigManager().removeConfig(this);
}
protected synchronized void init() {
@@ -234,19 +234,12 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
return;
}
- // Using DubboBootstrap API will associate bootstrap when registering reference.
- // Loading by Spring context will associate bootstrap in afterPropertiesSet() method.
- // Initializing bootstrap here only for compatible with old API usages.
- if (bootstrap == null) {
- bootstrap = DubboBootstrap.getInstance(getScopeModel().getApplicationModel());
- bootstrap.initialize();
- bootstrap.reference(this);
+ if (getScopeModel() == null) {
+ setScopeModel(ApplicationModel.defaultModel().getDefaultModule());
}
- // check bootstrap state
- if (!bootstrap.isInitialized()) {
- throw new IllegalStateException("DubboBootstrap is not initialized");
- }
+ // prepare application for reference
+ getScopeModel().getDeployer().prepare();
if (!this.isRefreshed()) {
this.refresh();
@@ -606,14 +599,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
return isJvmRefer;
}
- public DubboBootstrap getBootstrap() {
- return bootstrap;
- }
-
- public void setBootstrap(DubboBootstrap bootstrap) {
- this.bootstrap = bootstrap;
- }
-
private void postProcessConfig() {
List<ConfigPostProcessor> configPostProcessors = this.getExtensionLoader(ConfigPostProcessor.class)
.getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
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 b1f4cac..fe96dd3 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
@@ -19,6 +19,7 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.URLBuilder;
import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -29,8 +30,6 @@ import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Service;
-import org.apache.dubbo.config.bootstrap.BootstrapTakeoverMode;
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
@@ -45,6 +44,7 @@ import org.apache.dubbo.rpc.ProxyFactory;
import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
import org.apache.dubbo.rpc.model.ModuleServiceRepository;
import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@@ -133,8 +133,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
*/
private transient volatile boolean unexported;
- private DubboBootstrap bootstrap;
-
private transient volatile AtomicBoolean initialized = new AtomicBoolean(false);
/**
@@ -153,8 +151,8 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
}
@Override
- protected void postProcessAfterScopeModelChanged() {
- super.postProcessAfterScopeModelChanged();
+ protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
+ super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
localMetadataService = this.getScopeModel().getDefaultExtension(WritableMetadataService.class);
@@ -197,42 +195,33 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
repository.unregisterProvider(providerModel);
}
- public void init() {
+ private void init() {
if (this.initialized.compareAndSet(false, true)) {
- if (this.bootstrap == null) {
- this.bootstrap = DubboBootstrap.getInstance(getScopeModel().getApplicationModel());
- this.bootstrap.initialize();
- }
- this.bootstrap.service(this);
+ initServiceMetadata(provider);
+ serviceMetadata.setServiceType(getInterfaceClass());
+ serviceMetadata.setTarget(getRef());
+ serviceMetadata.generateServiceKey();
// load ServiceListeners from extension
ExtensionLoader<ServiceListener> extensionLoader = this.getExtensionLoader(ServiceListener.class);
this.serviceListeners.addAll(extensionLoader.getSupportedExtensionInstances());
}
-
- initServiceMetadata(provider);
- serviceMetadata.setServiceType(getInterfaceClass());
- serviceMetadata.setTarget(getRef());
- serviceMetadata.generateServiceKey();
}
@Override
public synchronized void export() {
- if (this.shouldExport() && !this.exported) {
- this.init();
-
- // check bootstrap state
- if (!bootstrap.isInitialized()) {
- throw new IllegalStateException("DubboBootstrap is not initialized");
- }
-
- if (!this.isRefreshed()) {
- this.refresh();
- }
+ if (this.exported) {
+ return;
+ }
+ // prepare for export
+ ModuleDeployer moduleDeployer = getScopeModel().getDeployer();
+ moduleDeployer.prepare();
- if (!shouldExport()) {
- return;
- }
+ if (!this.isRefreshed()) {
+ this.refresh();
+ }
+ if (this.shouldExport()) {
+ this.init();
if (shouldDelay()) {
doDelayExport();
@@ -240,9 +229,27 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
doExport();
}
- if (this.bootstrap.getTakeoverMode() == BootstrapTakeoverMode.AUTO) {
- this.bootstrap.start();
- }
+ // notify export this service
+ moduleDeployer.notifyExportService(this);
+ }
+ }
+
+ /**
+ * export service only, do not register application instance, for exporting services in batches by module
+ */
+ @Override
+ public synchronized void exportOnly() {
+ if (this.exported) {
+ return;
+ }
+ if (!this.isRefreshed()) {
+ this.refresh();
+ }
+ if (this.shouldExport()) {
+ this.init();
+
+ // just do export, delay export is done by caller
+ doExport();
}
}
@@ -813,14 +820,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
configPostProcessors.forEach(component -> component.postProcessServiceConfig(this));
}
- public DubboBootstrap getBootstrap() {
- return bootstrap;
- }
-
- public void setBootstrap(DubboBootstrap bootstrap) {
- this.bootstrap = bootstrap;
- }
-
public void addServiceListener(ServiceListener listener) {
this.serviceListeners.add(listener);
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/BootstrapTakeoverMode.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/BootstrapTakeoverMode.java
index 091de85..f2f3319 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/BootstrapTakeoverMode.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/BootstrapTakeoverMode.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.config.ServiceConfig;
* SPRING: will be controlled by spring context
* MANUAL: will be controlled by users, after all services init, should call {@link DubboBootstrap#start()} to init app-level env
* AUTO: env will be init once {@link ServiceConfig#export()} finished
- * SERVLET: will be controlled by tomcat
+ * SERVLET: will be controlled by java servlet container
*/
public enum BootstrapTakeoverMode {
SPRING, MANUAL, AUTO, SERVLET
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultApplicationDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultApplicationDeployer.java
new file mode 100644
index 0000000..d8b7703
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultApplicationDeployer.java
@@ -0,0 +1,941 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.bootstrap;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.config.ReferenceCache;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
+import org.apache.dubbo.common.deploy.ApplicationDeployer;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
+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.threadpool.manager.ExecutorRepository;
+import org.apache.dubbo.common.utils.ArrayUtils;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.DubboShutdownHook;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.utils.CompositeReferenceCache;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.report.MetadataReportFactory;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
+import org.apache.dubbo.registry.client.DefaultServiceInstance;
+import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
+import org.apache.dubbo.registry.client.metadata.store.InMemoryWritableMetadataService;
+import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl;
+import org.apache.dubbo.registry.support.AbstractRegistryFactory;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Optional;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Supplier;
+
+import static java.lang.String.format;
+import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.function.ThrowableAction.execute;
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_METADATA_PUBLISH_DELAY;
+import static org.apache.dubbo.metadata.MetadataConstants.METADATA_PUBLISH_DELAY_KEY;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.calInstanceRevision;
+import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
+import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getServiceDiscoveries;
+import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
+
+/**
+ * initialize and start application instance
+ */
+public class DefaultApplicationDeployer implements ApplicationDeployer {
+
+ private static final Logger logger = LoggerFactory.getLogger(DefaultApplicationDeployer.class);
+
+ private final ApplicationModel applicationModel;
+
+ private final ConfigManager configManager;
+
+ private final Environment environment;
+
+ private final ReferenceCache referenceCache;
+
+ private final ExecutorRepository executorRepository;
+
+ protected AtomicBoolean initialized = new AtomicBoolean(false);
+
+ protected AtomicBoolean started = new AtomicBoolean(false);
+
+ protected AtomicBoolean startup = new AtomicBoolean(true);
+
+ protected AtomicBoolean destroyed = new AtomicBoolean(false);
+
+ protected AtomicBoolean shutdown = new AtomicBoolean(false);
+
+ private final Lock destroyLock = new ReentrantLock();
+
+ protected volatile boolean isCurrentlyInStart = false;
+
+ protected volatile ServiceInstance serviceInstance;
+
+ protected AtomicBoolean hasPreparedApplicationInstance = new AtomicBoolean(false);
+
+ protected volatile MetadataService metadataService;
+
+ protected volatile MetadataServiceExporter metadataServiceExporter;
+
+ protected ScheduledFuture<?> asyncMetadataFuture;
+ private String identifier;
+
+
+ public DefaultApplicationDeployer(ApplicationModel applicationModel) {
+ this.applicationModel = applicationModel;
+ configManager = applicationModel.getApplicationConfigManager();
+ environment = applicationModel.getApplicationEnvironment();
+
+ referenceCache = new CompositeReferenceCache(applicationModel);
+ executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+ }
+
+ public static ApplicationDeployer get(ScopeModel moduleOrApplicationModel) {
+ ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(moduleOrApplicationModel);
+ ApplicationDeployer applicationDeployer = applicationModel.getDeployer();
+ if (applicationDeployer == null) {
+ applicationDeployer = applicationModel.getBeanFactory().getOrRegisterBean(DefaultApplicationDeployer.class);
+ }
+ return applicationDeployer;
+ }
+
+ @Override
+ public ApplicationModel getApplicationModel() {
+ return applicationModel;
+ }
+
+ private <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
+ return applicationModel.getExtensionLoader(type);
+ }
+
+ private void unRegisterShutdownHook() {
+ applicationModel.getBeanFactory().getBean(DubboShutdownHook.class).unregister();
+ }
+
+ private boolean isRegisterConsumerInstance() {
+ Boolean registerConsumer = getApplication().getRegisterConsumer();
+ return Boolean.TRUE.equals(registerConsumer);
+ }
+
+ private String getMetadataType() {
+ String type = getApplication().getMetadataType();
+ if (StringUtils.isEmpty(type)) {
+ type = DEFAULT_METADATA_STORAGE_TYPE;
+ }
+ return type;
+ }
+
+ @Override
+ public ReferenceCache getReferenceCache() {
+ return referenceCache;
+ }
+
+ /**
+ * Initialize
+ */
+ @Override
+ public synchronized void initialize() {
+ if (!initialized.compareAndSet(false, true)) {
+ return;
+ }
+ // register shutdown hook
+ registerShutdownHook();
+
+ startConfigCenter();
+
+ loadApplicationConfigs();
+
+ initModuleDeployers();
+
+ // @since 2.7.8
+ startMetadataCenter();
+
+ initMetadataService();
+
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " has been initialized!");
+ }
+ }
+
+ private void registerShutdownHook() {
+ applicationModel.getBeanFactory().getBean(DubboShutdownHook.class)
+ .addCallback(DefaultApplicationDeployer.this::destroy)
+ .register();
+ }
+
+ private void initModuleDeployers() {
+ // make sure created default module
+ applicationModel.getDefaultModule();
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ moduleModel.getDeployer().initialize();
+ }
+ }
+
+ private void loadApplicationConfigs() {
+ configManager.loadConfigs();
+ }
+
+ private void startConfigCenter() {
+
+ // load application config
+ configManager.loadConfigsOfTypeFromProps(ApplicationConfig.class);
+
+ // load config centers
+ configManager.loadConfigsOfTypeFromProps(ConfigCenterConfig.class);
+
+ useRegistryAsConfigCenterIfNecessary();
+
+ // check Config Center
+ Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
+ if (CollectionUtils.isEmpty(configCenters)) {
+ ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
+ configCenterConfig.setScopeModel(applicationModel);
+ configCenterConfig.refresh();
+ ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
+ if (configCenterConfig.isValid()) {
+ configManager.addConfigCenter(configCenterConfig);
+ configCenters = configManager.getConfigCenters();
+ }
+ } else {
+ for (ConfigCenterConfig configCenterConfig : configCenters) {
+ configCenterConfig.refresh();
+ ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
+ }
+ }
+
+ if (CollectionUtils.isNotEmpty(configCenters)) {
+ CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
+ for (ConfigCenterConfig configCenter : configCenters) {
+ // Pass config from ConfigCenterBean to environment
+ environment.updateExternalConfigMap(configCenter.getExternalConfiguration());
+ environment.updateAppExternalConfigMap(configCenter.getAppExternalConfiguration());
+
+ // Fetch config from remote config center
+ compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
+ }
+ environment.setDynamicConfiguration(compositeDynamicConfiguration);
+ }
+
+ configManager.refreshAll();
+ }
+
+ private void startMetadataCenter() {
+
+ useRegistryAsMetadataCenterIfNecessary();
+
+ ApplicationConfig applicationConfig = getApplication();
+
+ String metadataType = applicationConfig.getMetadataType();
+ // FIXME, multiple metadata config support.
+ Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
+ if (CollectionUtils.isEmpty(metadataReportConfigs)) {
+ if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
+ throw new IllegalStateException("No MetadataConfig found, Metadata Center address is required when 'metadata=remote' is enabled.");
+ }
+ return;
+ }
+
+ MetadataReportInstance metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
+ for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
+ ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
+ if (!metadataReportConfig.isValid()) {
+ logger.info("Ignore invalid metadata-report config: " + metadataReportConfig);
+ continue;
+ }
+ metadataReportInstance.init(metadataReportConfig);
+ }
+ }
+
+ /**
+ * For compatibility purpose, use registry as the default config center when
+ * there's no config center specified explicitly and
+ * useAsConfigCenter of registryConfig is null or true
+ */
+ private void useRegistryAsConfigCenterIfNecessary() {
+ // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
+ if (environment.getDynamicConfiguration().isPresent()) {
+ return;
+ }
+
+ if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
+ return;
+ }
+
+ // load registry
+ configManager.loadConfigsOfTypeFromProps(RegistryConfig.class);
+
+ List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
+ if (defaultRegistries.size() > 0) {
+ defaultRegistries
+ .stream()
+ .filter(this::isUsedRegistryAsConfigCenter)
+ .map(this::registryAsConfigCenter)
+ .forEach(configCenter -> {
+ if (configManager.getConfigCenter(configCenter.getId()).isPresent()) {
+ return;
+ }
+ configManager.addConfigCenter(configCenter);
+ logger.info("use registry as config-center: " + configCenter);
+
+ });
+ }
+ }
+
+ private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
+ return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsConfigCenter, "config",
+ DynamicConfigurationFactory.class);
+ }
+
+ private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) {
+ String protocol = registryConfig.getProtocol();
+ Integer port = registryConfig.getPort();
+ URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel());
+ String id = "config-center-" + protocol + "-" + url.getHost() + "-" + port;
+ ConfigCenterConfig cc = new ConfigCenterConfig();
+ cc.setId(id);
+ cc.setScopeModel(applicationModel);
+ if (cc.getParameters() == null) {
+ cc.setParameters(new HashMap<>());
+ }
+ if (registryConfig.getParameters() != null) {
+ cc.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
+ }
+ cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+ cc.setProtocol(protocol);
+ cc.setPort(port);
+ if (StringUtils.isNotEmpty(registryConfig.getGroup())) {
+ cc.setGroup(registryConfig.getGroup());
+ }
+ cc.setAddress(getRegistryCompatibleAddress(registryConfig));
+ cc.setNamespace(registryConfig.getGroup());
+ cc.setUsername(registryConfig.getUsername());
+ cc.setPassword(registryConfig.getPassword());
+ if (registryConfig.getTimeout() != null) {
+ cc.setTimeout(registryConfig.getTimeout().longValue());
+ }
+ cc.setHighestPriority(false);
+ return cc;
+ }
+
+ private void useRegistryAsMetadataCenterIfNecessary() {
+
+ Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();
+
+ if (CollectionUtils.isNotEmpty(metadataConfigs)) {
+ return;
+ }
+
+ List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
+ if (defaultRegistries.size() > 0) {
+ defaultRegistries
+ .stream()
+ .filter(this::isUsedRegistryAsMetadataCenter)
+ .map(this::registryAsMetadataCenter)
+ .forEach(metadataReportConfig -> {
+ Optional<MetadataReportConfig> configOptional = configManager.getConfig(MetadataReportConfig.class, metadataReportConfig.getId());
+ if (configOptional.isPresent()) {
+ return;
+ }
+ configManager.addMetadataReport(metadataReportConfig);
+ logger.info("use registry as metadata-center: " + metadataReportConfig);
+ });
+ }
+ }
+
+ private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
+ return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsMetadataCenter, "metadata",
+ MetadataReportFactory.class);
+ }
+
+ /**
+ * Is used the specified registry as a center infrastructure
+ *
+ * @param registryConfig the {@link RegistryConfig}
+ * @param usedRegistryAsCenter the configured value on
+ * @param centerType the type name of center
+ * @param extensionClass an extension class of a center infrastructure
+ * @return
+ * @since 2.7.8
+ */
+ private boolean isUsedRegistryAsCenter(RegistryConfig registryConfig, Supplier<Boolean> usedRegistryAsCenter,
+ String centerType,
+ Class<?> extensionClass) {
+ final boolean supported;
+
+ Boolean configuredValue = usedRegistryAsCenter.get();
+ if (configuredValue != null) { // If configured, take its value.
+ supported = configuredValue.booleanValue();
+ } else { // Or check the extension existence
+ String protocol = registryConfig.getProtocol();
+ supported = supportsExtension(extensionClass, protocol);
+ if (logger.isInfoEnabled()) {
+ logger.info(format("No value is configured in the registry, the %s extension[name : %s] %s as the %s center"
+ , extensionClass.getSimpleName(), protocol, supported ? "supports" : "does not support", centerType));
+ }
+ }
+
+ if (logger.isInfoEnabled()) {
+ logger.info(format("The registry[%s] will be %s as the %s center", registryConfig,
+ supported ? "used" : "not used", centerType));
+ }
+ return supported;
+ }
+
+ /**
+ * Supports the extension with the specified class and name
+ *
+ * @param extensionClass the {@link Class} of extension
+ * @param name the name of extension
+ * @return if supports, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ private boolean supportsExtension(Class<?> extensionClass, String name) {
+ if (isNotEmpty(name)) {
+ ExtensionLoader extensionLoader = getExtensionLoader(extensionClass);
+ return extensionLoader.hasExtension(name);
+ }
+ return false;
+ }
+
+ private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) {
+ String protocol = registryConfig.getProtocol();
+ URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel());
+ String id = "metadata-center-" + protocol + "-" + url.getHost() + "-" + url.getPort();
+ MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
+ metadataReportConfig.setId(id);
+ metadataReportConfig.setScopeModel(applicationModel);
+ if (metadataReportConfig.getParameters() == null) {
+ metadataReportConfig.setParameters(new HashMap<>());
+ }
+ if (registryConfig.getParameters() != null) {
+ metadataReportConfig.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
+ }
+ metadataReportConfig.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+ metadataReportConfig.setGroup(registryConfig.getGroup());
+ metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig));
+ metadataReportConfig.setUsername(registryConfig.getUsername());
+ metadataReportConfig.setPassword(registryConfig.getPassword());
+ metadataReportConfig.setTimeout(registryConfig.getTimeout());
+ return metadataReportConfig;
+ }
+
+ private String getRegistryCompatibleAddress(RegistryConfig registryConfig) {
+ String registryAddress = registryConfig.getAddress();
+ String[] addresses = REGISTRY_SPLIT_PATTERN.split(registryAddress);
+ if (ArrayUtils.isEmpty(addresses)) {
+ throw new IllegalStateException("Invalid registry address found.");
+ }
+ String address = addresses[0];
+ // since 2.7.8
+ // Issue : https://github.com/apache/dubbo/issues/6476
+ StringBuilder metadataAddressBuilder = new StringBuilder();
+ URL url = URL.valueOf(address, registryConfig.getScopeModel());
+ String protocolFromAddress = url.getProtocol();
+ if (isEmpty(protocolFromAddress)) {
+ // If the protocol from address is missing, is like :
+ // "dubbo.registry.address = 127.0.0.1:2181"
+ String protocolFromConfig = registryConfig.getProtocol();
+ metadataAddressBuilder.append(protocolFromConfig).append("://");
+ }
+ metadataAddressBuilder.append(address);
+ return metadataAddressBuilder.toString();
+ }
+
+ /**
+ * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
+ */
+ private void initMetadataService() {
+// startMetadataCenter();
+ this.metadataService = getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
+ // support injection by super type MetadataService
+ applicationModel.getBeanFactory().registerBean(this.metadataService);
+
+ //this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
+ this.metadataServiceExporter = getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
+ }
+
+ /**
+ * Start the bootstrap
+ */
+ @Override
+ public synchronized void start() {
+ // avoid re-entry start method multiple times in same thread
+ if (isCurrentlyInStart) {
+ return;
+ }
+
+ isCurrentlyInStart = true;
+ try {
+ if (started.compareAndSet(false, true)) {
+ startup.set(false);
+ shutdown.set(false);
+
+ initialize();
+
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " is starting...");
+ }
+
+ doStart();
+
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " has started.");
+ }
+ } else {
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " is started, export/refer new services.");
+ }
+
+ doStart();
+
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " finish export/refer new services.");
+ }
+ }
+ } finally {
+ isCurrentlyInStart = false;
+ }
+ }
+
+ private void doStart() {
+ // copy current modules, ignore new module during starting
+ List<ModuleModel> moduleModels = new ArrayList<>(applicationModel.getModuleModels());
+ List<ModuleDeployer> moduleDeployers = new ArrayList<>(moduleModels.size());
+ List<CompletableFuture> futures = new ArrayList<>(moduleModels.size());
+
+ for (ModuleModel moduleModel : moduleModels) {
+ // export services in module
+ ModuleDeployer moduleDeployer = moduleModel.getDeployer();
+ moduleDeployers.add(moduleDeployer);
+ CompletableFuture moduleFuture = moduleDeployer.start();
+ futures.add(moduleFuture);
+ }
+
+ // prepare application instance
+ prepareApplicationInstance();
+
+ // wait async export / refer finish if needed
+ if (isExportBackground(moduleDeployers) || isReferBackground(moduleDeployers)) {
+ new Thread(() -> {
+ awaitDeployFinished(futures);
+ onStarted();
+ }).start();
+ } else {
+ awaitDeployFinished(futures);
+ onStarted();
+ }
+ }
+
+ private void awaitDeployFinished(List<CompletableFuture> futures) {
+ try {
+ CompletableFuture mergedFuture = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
+ mergedFuture.get();
+ } catch (Exception e) {
+ logger.error(getIdentifier() + " await deploy finished failed", e);
+ }
+ }
+
+ @Override
+ public void prepareApplicationInstance() {
+ if (hasPreparedApplicationInstance.get()) {
+ return;
+ }
+ // if register consumer instance or has exported services
+ if (isRegisterConsumerInstance() || hasExportedServices()) {
+ if (!hasPreparedApplicationInstance.compareAndSet(false, true)) {
+ return;
+ }
+ // export MetadataService
+ exportMetadataService();
+ // start internal module
+ ModuleDeployer internalModuleDeployer = applicationModel.getInternalModule().getDeployer();
+ CompletableFuture internalModuleFuture = internalModuleDeployer.start();
+ try {
+ internalModuleFuture.get();
+ } catch (Exception e) {
+ logger.warn("Internal module start waiting was interrupted");
+ }
+ // register the local ServiceInstance if required
+ registerServiceInstance();
+ }
+ }
+
+ private boolean hasExportedServices() {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ if (CollectionUtils.isNotEmpty(moduleModel.getServiceRepository().getExportedServices())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isExportBackground(List<ModuleDeployer> moduleDeployers) {
+ // move export background option to application?
+ for (ModuleDeployer moduleDeployer : moduleDeployers) {
+ if (moduleDeployer.isExportBackground()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean isReferBackground(List<ModuleDeployer> moduleDeployers) {
+ // move refer background option to application?
+ for (ModuleDeployer moduleDeployer : moduleDeployers) {
+ if (moduleDeployer.isReferBackground()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized.get();
+ }
+
+ @Override
+ public boolean isStarted() {
+ return started.get();
+ }
+
+ @Override
+ public boolean isStartup() {
+ return startup.get();
+ }
+
+ @Override
+ public boolean isShutdown() {
+ return shutdown.get();
+ }
+
+
+ private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
+ if (configCenter.isValid()) {
+ if (!configCenter.checkOrUpdateInitialized(true)) {
+ return null;
+ }
+
+ DynamicConfiguration dynamicConfiguration = null;
+ try {
+ dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
+ } catch (Exception e) {
+ if (!configCenter.isCheck()) {
+ logger.warn("The configuration center failed to initialize", e);
+ configCenter.checkOrUpdateInitialized(false);
+ return null;
+ } else {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ String configContent = dynamicConfiguration.getProperties(configCenter.getConfigFile(), configCenter.getGroup());
+
+ String appGroup = getApplication().getName();
+ String appConfigContent = null;
+ if (isNotEmpty(appGroup)) {
+ appConfigContent = dynamicConfiguration.getProperties
+ (isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
+ appGroup
+ );
+ }
+ try {
+ environment.updateExternalConfigMap(parseProperties(configContent));
+ environment.updateAppExternalConfigMap(parseProperties(appConfigContent));
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
+ }
+ return dynamicConfiguration;
+ }
+ return null;
+ }
+
+ /**
+ * Get the instance of {@link DynamicConfiguration} by the specified connection {@link URL} of config-center
+ *
+ * @param connectionURL of config-center
+ * @return non-null
+ * @since 2.7.5
+ */
+ private DynamicConfiguration getDynamicConfiguration(URL connectionURL) {
+ String protocol = connectionURL.getProtocol();
+
+ DynamicConfigurationFactory factory = ConfigurationUtils.getDynamicConfigurationFactory(applicationModel, protocol);
+ return factory.getDynamicConfiguration(connectionURL);
+ }
+
+ /**
+ * export {@link MetadataService}
+ */
+ private void exportMetadataService() {
+ metadataServiceExporter.export();
+ }
+
+ private void unexportMetadataService() {
+ if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
+ try {
+ metadataServiceExporter.unexport();
+ } catch (Exception ignored) {
+ // ignored
+ }
+ }
+ }
+
+ private void registerServiceInstance() {
+ if (isRegisteredServiceInstance()) {
+ return;
+ }
+
+ ApplicationConfig application = getApplication();
+ String serviceName = application.getName();
+ ServiceInstance serviceInstance = createServiceInstance(serviceName);
+ boolean registered = true;
+ try {
+ ServiceInstanceMetadataUtils.registerMetadataAndInstance(serviceInstance);
+ } catch (Exception e) {
+ registered = false;
+ logger.error("Register instance error", e);
+ }
+ if (registered) {
+ // scheduled task for updating Metadata and ServiceInstance
+ asyncMetadataFuture = executorRepository.nextScheduledExecutor().scheduleAtFixedRate(() -> {
+ InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(applicationModel);
+ localMetadataService.blockUntilUpdated();
+ try {
+ ServiceInstanceMetadataUtils.refreshMetadataAndInstance(serviceInstance);
+ } catch (Exception e) {
+ logger.error("Refresh instance and metadata error", e);
+ } finally {
+ localMetadataService.releaseBlock();
+ }
+ }, 0, ConfigurationUtils.get(applicationModel, METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY), TimeUnit.MILLISECONDS);
+ }
+ }
+
+ private boolean isRegisteredServiceInstance() {
+ return this.serviceInstance != null;
+ }
+
+ private void doRegisterServiceInstance(ServiceInstance serviceInstance) {
+ // register instance only when at least one service is exported.
+ if (serviceInstance.getPort() > 0) {
+ publishMetadataToRemote(serviceInstance);
+ logger.info("Start registering instance address to registry.");
+ getServiceDiscoveries().forEach(serviceDiscovery ->
+ {
+ ServiceInstance serviceInstanceForRegistry = new DefaultServiceInstance((DefaultServiceInstance) serviceInstance);
+ calInstanceRevision(serviceDiscovery, serviceInstanceForRegistry);
+ if (logger.isDebugEnabled()) {
+ logger.info("Start registering instance address to registry" + serviceDiscovery.getUrl() + ", instance " + serviceInstanceForRegistry);
+ }
+ // register metadata
+ serviceDiscovery.register(serviceInstanceForRegistry);
+ });
+ }
+ }
+
+ private void publishMetadataToRemote(ServiceInstance serviceInstance) {
+// InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService)WritableMetadataService.getDefaultExtension();
+// localMetadataService.blockUntilUpdated();
+ if (logger.isInfoEnabled()) {
+ logger.info("Start publishing metadata to remote center, this only makes sense for applications enabled remote metadata center.");
+ }
+ RemoteMetadataServiceImpl remoteMetadataService = applicationModel.getBeanFactory().getBean(RemoteMetadataServiceImpl.class);
+ remoteMetadataService.publishMetadata(serviceInstance.getServiceName());
+ }
+
+ private void unregisterServiceInstance() {
+ if (isRegisteredServiceInstance()) {
+ getServiceDiscoveries().forEach(serviceDiscovery -> {
+ try {
+ serviceDiscovery.unregister(serviceInstance);
+ } catch (Exception ignored) {
+ // ignored
+ }
+ });
+ }
+ }
+
+ private ServiceInstance createServiceInstance(String serviceName) {
+ this.serviceInstance = new DefaultServiceInstance(serviceName, applicationModel);
+ setMetadataStorageType(serviceInstance, getMetadataType());
+ ServiceInstanceMetadataUtils.customizeInstance(this.serviceInstance);
+ return this.serviceInstance;
+ }
+
+ @Override
+ public void destroy() {
+ if (destroyLock.tryLock()
+ && shutdown.compareAndSet(false, true)) {
+ try {
+ if (destroyed.compareAndSet(false, true)) {
+ if (started.compareAndSet(true, false)) {
+ unregisterServiceInstance();
+ unexportMetadataService();
+ if (asyncMetadataFuture != null) {
+ asyncMetadataFuture.cancel(true);
+ }
+ }
+
+ destroyRegistries();
+ destroyServiceDiscoveries();
+ destroyMetadataReports();
+
+ applicationModel.destroy();
+ destroyProtocols(applicationModel.getFrameworkModel());
+ destroyExecutorRepository();
+
+ onStop();
+ }
+
+ destroyDynamicConfigurations();
+ } catch (Throwable ignored) {
+ // ignored
+ logger.warn(ignored.getMessage(), ignored);
+ } finally {
+ initialized.set(false);
+ startup.set(false);
+ destroyLock.unlock();
+ unRegisterShutdownHook();
+ }
+
+ applicationModel.destroy();
+ }
+ }
+
+ private void onStarted() {
+ startup.set(true);
+ if (logger.isInfoEnabled()) {
+ logger.info(getIdentifier() + " is ready.");
+ }
+ DubboBootstrap dubboBootstrap = applicationModel.getBeanFactory().getBean(DubboBootstrap.class);
+ ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
+ exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(dubboBootstrap));
+ }
+
+ private void onStop() {
+ DubboBootstrap dubboBootstrap = applicationModel.getBeanFactory().getBean(DubboBootstrap.class);
+ ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
+ exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(dubboBootstrap));
+ }
+
+ private void destroyExecutorRepository() {
+ getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
+ }
+
+ private void destroyRegistries() {
+ AbstractRegistryFactory.destroyAll();
+ }
+
+ /**
+ * Destroy all the protocols.
+ */
+ private static void destroyProtocols(FrameworkModel frameworkModel) {
+ if (frameworkModel.getApplicationModels().isEmpty()) {
+ //TODO destroy protocol in framework scope
+ ExtensionLoader<Protocol> loader = frameworkModel.getExtensionLoader(Protocol.class);
+ for (String protocolName : loader.getLoadedExtensions()) {
+ try {
+ Protocol protocol = loader.getLoadedExtension(protocolName);
+ if (protocol != null) {
+ protocol.destroy();
+ }
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
+ }
+ }
+ }
+ }
+
+ private static void destroyAllProtocols() {
+ for (FrameworkModel frameworkModel : FrameworkModel.getAllInstances()) {
+ destroyProtocols(frameworkModel);
+ }
+ }
+
+ private void destroyServiceDiscoveries() {
+ getServiceDiscoveries().forEach(serviceDiscovery -> {
+ try {
+ execute(serviceDiscovery::destroy);
+ } catch (Throwable ignored) {
+ logger.warn(ignored.getMessage(), ignored);
+ }
+ });
+ if (logger.isDebugEnabled()) {
+ logger.debug(getIdentifier() + "'s all ServiceDiscoveries have been destroyed.");
+ }
+ }
+
+ private void destroyMetadataReports() {
+ AbstractMetadataReportFactory.destroy();
+ MetadataReportInstance.reset();
+ }
+
+ private void destroyDynamicConfigurations() {
+ // DynamicConfiguration may be cached somewhere, and maybe used during destroy
+ // destroy them may cause some troubles, so just clear instances cache
+ // ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
+ }
+
+ private ApplicationConfig getApplication() {
+ return configManager.getApplicationOrElseThrow();
+ }
+
+ private String getIdentifier() {
+ if (identifier == null) {
+ identifier = "Dubbo Application-" + applicationModel.getInternalId();
+ }
+ return identifier;
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultModuleDeployer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultModuleDeployer.java
new file mode 100644
index 0000000..1131741
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DefaultModuleDeployer.java
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.bootstrap;
+
+import org.apache.dubbo.common.config.ReferenceCache;
+import org.apache.dubbo.common.deploy.ApplicationDeployer;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.ServiceConfigBase;
+import org.apache.dubbo.config.context.ModuleConfigManager;
+import org.apache.dubbo.config.utils.SimpleReferenceCache;
+import org.apache.dubbo.rpc.model.ModelConstants;
+import org.apache.dubbo.rpc.model.ModuleModel;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Export/refer services of module
+ */
+public class DefaultModuleDeployer implements ModuleDeployer {
+
+ private static final Logger logger = LoggerFactory.getLogger(DefaultModuleDeployer.class);
+
+ private final List<CompletableFuture<?>> asyncExportingFutures = new ArrayList<>();
+
+ private final List<CompletableFuture<?>> asyncReferringFutures = new ArrayList<>();
+
+ private List<ServiceConfigBase<?>> exportedServices = new ArrayList<>();
+
+ private ModuleModel moduleModel;
+
+ private ExecutorRepository executorRepository;
+
+ private final ModuleConfigManager configManager;
+
+ private final SimpleReferenceCache referenceCache;
+ private String identifier;
+
+ private volatile boolean startup;
+
+ protected AtomicBoolean initialized = new AtomicBoolean(false);
+
+ private ApplicationDeployer applicationDeployer;
+
+ public static ModuleDeployer get(ModuleModel moduleModel) {
+ return moduleModel.getAttribute(ModelConstants.DEPLOYER, DefaultModuleDeployer.class);
+ }
+
+ public DefaultModuleDeployer(ModuleModel moduleModel) {
+ this.moduleModel = moduleModel;
+ configManager = moduleModel.getConfigManager();
+ executorRepository = moduleModel.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+ referenceCache = SimpleReferenceCache.newCache();
+ applicationDeployer = DefaultApplicationDeployer.get(moduleModel);
+ }
+
+ @Override
+ public void initialize() throws IllegalStateException {
+ if (!initialized.compareAndSet(false, true)) {
+ return;
+ }
+ loadConfigs();
+ }
+
+ @Override
+ public CompletableFuture start() throws IllegalStateException {
+
+ CompletableFuture startFuture = new CompletableFuture();
+
+ applicationDeployer.initialize();
+
+ // initialize
+ initialize();
+
+ // export services
+ exportServices();
+
+ // prepare application instance
+ if (hasExportedServices()) {
+ applicationDeployer.prepareApplicationInstance();
+ }
+
+ // refer services
+ referServices();
+
+ executorRepository.getSharedExecutor().submit(() -> {
+ awaitFinish();
+ onModuleStarted(startFuture);
+ });
+ return startFuture;
+ }
+
+ private boolean hasExportedServices() {
+ return configManager.getServices().size() > 0;
+ }
+
+ @Override
+ public void destroy() throws IllegalStateException {
+ unexportServices();
+ unreferServices();
+ onModuleStopped();
+ }
+
+ private void onModuleStopped() {
+ startup = false;
+ logger.info(getIdentifier() + " has stopped.");
+ Set<ModuleDeployListener> listeners = moduleModel.getExtensionLoader(ModuleDeployListener.class).getSupportedExtensionInstances();
+ for (ModuleDeployListener listener : listeners) {
+ listener.onModuleStopped(moduleModel);
+ }
+ }
+
+ private void onModuleStarted(CompletableFuture startFuture) {
+ startup = true;
+ logger.info(getIdentifier() + " has started.");
+ startFuture.complete(true);
+ Set<ModuleDeployListener> listeners = moduleModel.getExtensionLoader(ModuleDeployListener.class).getSupportedExtensionInstances();
+ for (ModuleDeployListener listener : listeners) {
+ listener.onModuleStarted(moduleModel);
+ }
+ }
+
+ private void loadConfigs() {
+ // load module configs
+ moduleModel.getConfigManager().loadConfigs();
+ moduleModel.getConfigManager().refreshAll();
+ }
+
+ private void exportServices() {
+ for (ServiceConfigBase sc : configManager.getServices()) {
+ exportServiceInternal(sc);
+ }
+ }
+
+ private void exportServiceInternal(ServiceConfigBase sc) {
+ ServiceConfig<?> serviceConfig = (ServiceConfig<?>) sc;
+ if (!serviceConfig.isRefreshed()) {
+ serviceConfig.refresh();
+ }
+ if (sc.isExported()) {
+ return;
+ }
+ if (sc.shouldExportAsync()) {
+ ExecutorService executor = executorRepository.getServiceExportExecutor();
+ CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+ try {
+ if (!sc.isExported()) {
+ sc.exportOnly();
+ exportedServices.add(sc);
+ }
+ } catch (Throwable t) {
+ logger.error(getIdentifier() + " export async catch error : " + t.getMessage(), t);
+ }
+ }, executor);
+
+ asyncExportingFutures.add(future);
+ } else {
+ if (!sc.isExported()) {
+ sc.exportOnly();
+ exportedServices.add(sc);
+ }
+ }
+ }
+
+ private void unexportServices() {
+ exportedServices.forEach(sc -> {
+ try {
+ configManager.removeConfig(sc);
+ sc.unexport();
+ } catch (Exception ignored) {
+ // ignored
+ }
+ });
+
+ asyncExportingFutures.forEach(future -> {
+ if (!future.isDone()) {
+ future.cancel(true);
+ }
+ });
+ asyncExportingFutures.clear();
+ }
+
+ private void referServices() {
+ configManager.getReferences().forEach(rc -> {
+ try {
+ // TODO, compatible with ReferenceConfig.refer()
+ ReferenceConfig<?> referenceConfig = (ReferenceConfig<?>) rc;
+ if (!referenceConfig.isRefreshed()) {
+ referenceConfig.refresh();
+ }
+
+ if (rc.shouldInit()) {
+ if (rc.shouldReferAsync()) {
+ ExecutorService executor = executorRepository.getServiceReferExecutor();
+ CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
+ try {
+ referenceCache.get(rc);
+ } catch (Throwable t) {
+ logger.error(getIdentifier() + " refer async catch error : " + t.getMessage(), t);
+ }
+ }, executor);
+
+ asyncReferringFutures.add(future);
+ } else {
+ referenceCache.get(rc);
+ }
+ }
+ } catch (Throwable t) {
+ logger.error(getIdentifier() + " refer catch error", t);
+ referenceCache.destroy(rc);
+ }
+ });
+ }
+
+ private void unreferServices() {
+ try {
+ asyncReferringFutures.forEach(future -> {
+ if (!future.isDone()) {
+ future.cancel(true);
+ }
+ });
+ asyncReferringFutures.clear();
+ referenceCache.destroyAll();
+ } catch (Exception ignored) {
+ }
+ }
+
+ private void waitExportFinish() {
+ try {
+ logger.info(getIdentifier() + " waiting services exporting ...");
+ CompletableFuture<?> future = CompletableFuture.allOf(asyncExportingFutures.toArray(new CompletableFuture[0]));
+ future.get();
+ } catch (Exception e) {
+ logger.warn(getIdentifier() + " export services occurred an exception.");
+ } finally {
+ executorRepository.shutdownServiceExportExecutor();
+ logger.info(getIdentifier() + " export services finished.");
+ asyncExportingFutures.clear();
+ }
+ }
+
+ private void waitReferFinish() {
+ try {
+ logger.info(getIdentifier() + " waiting services referring ...");
+ CompletableFuture<?> future = CompletableFuture.allOf(asyncReferringFutures.toArray(new CompletableFuture[0]));
+ future.get();
+ } catch (Exception e) {
+ logger.warn(getIdentifier() + " refer services occurred an exception.");
+ } finally {
+ executorRepository.shutdownServiceReferExecutor();
+ logger.info(getIdentifier() + " refer services finished.");
+ asyncReferringFutures.clear();
+ }
+ }
+
+ private void awaitFinish() {
+ waitExportFinish();
+ waitReferFinish();
+ }
+
+ @Override
+ public boolean isStartup() {
+ return startup;
+ }
+
+ @Override
+ public boolean isInitialized() {
+ return initialized.get();
+ }
+
+ @Override
+ public boolean isExportBackground() {
+ return moduleModel.getConfigManager().getProviders()
+ .stream()
+ .map(ProviderConfig::getExportBackground)
+ .filter(k -> k != null && k)
+ .findAny()
+ .isPresent();
+ }
+
+ @Override
+ public boolean isReferBackground() {
+ return moduleModel.getConfigManager().getConsumers()
+ .stream()
+ .map(ConsumerConfig::getReferBackground)
+ .filter(k -> k != null && k)
+ .findAny()
+ .isPresent();
+ }
+
+ private String getIdentifier() {
+ if (identifier == null) {
+ identifier = "Dubbo Module-" + moduleModel.getInternalId();
+ }
+ return identifier;
+ }
+
+ @Override
+ public ReferenceCache getReferenceCache() {
+ return referenceCache;
+ }
+
+ /**
+ * Prepare for export/refer service, trigger initializing application and module
+ */
+ @Override
+ public void prepare() {
+ applicationDeployer.initialize();
+ this.initialize();
+ }
+
+ /**
+ * After export one service, trigger starting application
+ */
+ @Override
+ public void notifyExportService(ServiceConfigBase<?> sc) {
+ applicationDeployer.prepareApplicationInstance();
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index 97e8abb..7e69f0e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -16,27 +16,17 @@
*/
package org.apache.dubbo.config.bootstrap;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.config.Environment;
-import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
-import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
-import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
-import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.common.extension.ExtensionDirector;
+import org.apache.dubbo.common.config.ReferenceCache;
+import org.apache.dubbo.common.deploy.ApplicationDeployer;
import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
-import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConsumerConfig;
-import org.apache.dubbo.config.DubboShutdownHook;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.ModuleConfig;
@@ -44,10 +34,8 @@ import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.ReferenceConfig;
-import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.config.bootstrap.builders.ApplicationBuilder;
import org.apache.dubbo.config.bootstrap.builders.ConsumerBuilder;
@@ -57,64 +45,22 @@ import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder;
import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder;
import org.apache.dubbo.config.bootstrap.builders.ServiceBuilder;
import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.config.utils.ConfigValidationUtils;
-import org.apache.dubbo.config.utils.ReferenceConfigCache;
-import org.apache.dubbo.metadata.MetadataService;
-import org.apache.dubbo.metadata.MetadataServiceExporter;
-import org.apache.dubbo.metadata.WritableMetadataService;
-import org.apache.dubbo.metadata.report.MetadataReportFactory;
+import org.apache.dubbo.config.utils.CompositeReferenceCache;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
-import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
-import org.apache.dubbo.registry.client.DefaultServiceInstance;
-import org.apache.dubbo.registry.client.ServiceInstance;
-import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
-import org.apache.dubbo.registry.client.metadata.store.InMemoryWritableMetadataService;
-import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.ScheduledFuture;
-import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
-import java.util.function.Supplier;
-import java.util.stream.Collectors;
-import static java.lang.String.format;
import static java.util.Collections.singletonList;
-import static java.util.concurrent.Executors.newSingleThreadExecutor;
-import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
-import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
-import static org.apache.dubbo.common.function.ThrowableAction.execute;
-import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
-import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
-import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_METADATA_PUBLISH_DELAY;
-import static org.apache.dubbo.metadata.MetadataConstants.METADATA_PUBLISH_DELAY_KEY;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.calInstanceRevision;
-import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
-import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getServiceDiscoveries;
-import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
/**
* See {@link ApplicationModel} and {@link ExtensionLoader} for why this class is designed to be singleton.
@@ -142,53 +88,17 @@ public final class DubboBootstrap {
private final Condition condition = lock.newCondition();
- private final Lock destroyLock = new ReentrantLock();
-
- private final ExecutorService executorService = newSingleThreadExecutor();
-
private ExecutorRepository executorRepository;
private final ApplicationModel applicationModel;
- protected ScheduledFuture<?> asyncMetadataFuture;
-
protected final ConfigManager configManager;
protected final Environment environment;
- protected ReferenceConfigCache cache;
-
- protected AtomicBoolean initialized = new AtomicBoolean(false);
-
- protected AtomicBoolean started = new AtomicBoolean(false);
-
- protected AtomicBoolean startup = new AtomicBoolean(true);
-
- protected AtomicBoolean destroyed = new AtomicBoolean(false);
-
- protected AtomicBoolean shutdown = new AtomicBoolean(false);
-
- protected volatile boolean isCurrentlyInStart = false;
-
- protected volatile ServiceInstance serviceInstance;
-
- protected volatile MetadataService metadataService;
-
- protected volatile MetadataServiceExporter metadataServiceExporter;
-
- protected List<ServiceConfigBase<?>> exportedServices = new ArrayList<>();
-
- protected final List<CompletableFuture<?>> asyncExportingFutures = new ArrayList<>();
-
- protected final List<CompletableFuture<?>> asyncReferringFutures = new ArrayList<>();
-
- protected boolean asyncExportFinish = true;
+ protected ReferenceCache referenceCache;
- protected volatile boolean asyncReferFinish = true;
-
- protected static boolean ignoreConfigState;
-
- private Module currentModule;
+ private ApplicationDeployer applicationDeployer;
/**
* See {@link ApplicationModel} and {@link ExtensionLoader} for why DubboBootstrap is designed to be singleton.
@@ -204,31 +114,18 @@ public final class DubboBootstrap {
return instance;
}
- public static DubboBootstrap getInstance(ApplicationModel applicationModel) {
- Map<String, Object> attribute = applicationModel.getAttribute();
- Object cached = attribute.get(NAME);
- if (cached instanceof DubboBootstrap) {
- return (DubboBootstrap) cached;
- } else {
- synchronized (applicationModel) {
- cached = attribute.get(NAME);
- if (cached instanceof DubboBootstrap) {
- return (DubboBootstrap) cached;
- } else {
- return new DubboBootstrap(applicationModel);
- }
- }
- }
- }
-
public static DubboBootstrap newInstance() {
- return new DubboBootstrap(new FrameworkModel());
+ return new DubboBootstrap(FrameworkModel.defaultModel());
}
public static DubboBootstrap newInstance(FrameworkModel frameworkModel) {
return new DubboBootstrap(frameworkModel);
}
+ public static DubboBootstrap newInstance(ApplicationModel applicationModel) {
+ return new DubboBootstrap(applicationModel);
+ }
+
/**
* Try reset dubbo status for new instance.
*
@@ -246,7 +143,6 @@ public final class DubboBootstrap {
*/
@Deprecated
public static void reset(boolean destroy) {
- DubboBootstrap.ignoreConfigState = true;
if (destroy) {
if (instance != null) {
instance.destroy();
@@ -261,7 +157,6 @@ public final class DubboBootstrap {
}
ApplicationModel.reset();
- ShutdownHookCallbacks.INSTANCE.clear();
}
private DubboBootstrap(FrameworkModel frameworkModel) {
@@ -270,49 +165,143 @@ public final class DubboBootstrap {
private DubboBootstrap(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
- applicationModel.getAttribute().put(NAME, this);
configManager = applicationModel.getApplicationConfigManager();
environment = applicationModel.getApplicationEnvironment();
- executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
- DubboShutdownHook.getDubboShutdownHook().register();
- ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy);
- cache = ReferenceConfigCache.newCache();
+ referenceCache = new CompositeReferenceCache(applicationModel);
+ executorRepository = applicationModel.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+ applicationDeployer = applicationModel.getDeployer();
+ // register DubboBootstrap bean
+ applicationModel.getBeanFactory().registerBean(this);
}
- public ApplicationModel getApplicationModel() {
- return applicationModel;
+ /**
+ * Initialize
+ */
+ public void initialize() {
+ applicationDeployer.initialize();
}
- public ConfigManager getConfigManager() {
- return configManager;
+ /**
+ * Start the bootstrap
+ */
+ public DubboBootstrap start() {
+ applicationDeployer.start();
+ return this;
+ }
+
+ public DubboBootstrap stop() throws IllegalStateException {
+ destroy();
+ return this;
+ }
+
+ public void destroy() {
+ applicationDeployer.destroy();
+ }
+
+ public boolean isInitialized() {
+ return applicationDeployer.isInitialized();
}
- public ExtensionDirector getExtensionDirector() {
- return applicationModel.getExtensionDirector();
+ public boolean isStarted() {
+ return applicationDeployer.isStarted();
+ }
+
+ public boolean isStartup() {
+ return applicationDeployer.isStartup();
+ }
+
+ public boolean isShutdown() {
+ return applicationDeployer.isShutdown();
+ }
+
+ /**
+ * Block current thread to be await.
+ *
+ * @return {@link DubboBootstrap}
+ */
+ public DubboBootstrap await() {
+ // if has been waited, no need to wait again, return immediately
+ if (!awaited.get()) {
+ if (!isShutdown()) {
+ executeMutually(() -> {
+ while (!awaited.get()) {
+ if (logger.isInfoEnabled()) {
+ logger.info(NAME + " awaiting ...");
+ }
+ try {
+ condition.await();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ });
+ }
+ }
+ return this;
}
- public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
- return applicationModel.getExtensionLoader(type);
+ public ReferenceCache getCache() {
+ return referenceCache;
}
- public void unRegisterShutdownHook() {
- DubboShutdownHook.getDubboShutdownHook().unregister();
+ /**
+ * Destroy all the protocols.
+ */
+ private static void destroyProtocols(FrameworkModel frameworkModel) {
+ //TODO destroy protocol in framework scope
+ ExtensionLoader<Protocol> loader = frameworkModel.getExtensionLoader(Protocol.class);
+ for (String protocolName : loader.getLoadedExtensions()) {
+ try {
+ Protocol protocol = loader.getLoadedExtension(protocolName);
+ if (protocol != null) {
+ protocol.destroy();
+ }
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
+ }
+ }
}
- private boolean isRegisterConsumerInstance() {
- Boolean registerConsumer = getApplication().getRegisterConsumer();
- return Boolean.TRUE.equals(registerConsumer);
+ private static void destroyAllProtocols() {
+ for (FrameworkModel frameworkModel : FrameworkModel.getAllInstances()) {
+ destroyProtocols(frameworkModel);
+ }
}
- private String getMetadataType() {
- String type = getApplication().getMetadataType();
- if (StringUtils.isEmpty(type)) {
- type = DEFAULT_METADATA_STORAGE_TYPE;
+ private void executeMutually(Runnable runnable) {
+ try {
+ lock.lock();
+ runnable.run();
+ } finally {
+ lock.unlock();
}
- return type;
}
+ public ApplicationConfig getApplication() {
+ return configManager.getApplicationOrElseThrow();
+ }
+
+ public void setTakeoverMode(BootstrapTakeoverMode takeoverMode) {
+ //TODO this.started.set(false);
+ this.takeoverMode = takeoverMode;
+ }
+
+ public BootstrapTakeoverMode getTakeoverMode() {
+ return takeoverMode;
+ }
+
+ public ApplicationModel getApplicationModel() {
+ return applicationModel;
+ }
+
+ public ConfigManager getConfigManager() {
+ return configManager;
+ }
+
+
+ // MetadataReportConfig correlative methods
+
public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
configManager.addMetadataReport(metadataReportConfig);
return this;
@@ -445,93 +434,144 @@ public final class DubboBootstrap {
return this;
}
- private Module getCurrentModule() {
- if (currentModule == null) {
- currentModule = new Module(applicationModel.getDefaultModule());
- }
- return currentModule;
- }
-
// {@link ServiceConfig} correlative methods
public <S> DubboBootstrap service(Consumer<ServiceBuilder<S>> consumerBuilder) {
- getCurrentModule().service(consumerBuilder);
- return this;
+ return service(null, consumerBuilder);
}
public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
- getCurrentModule().service(id, consumerBuilder);
+ return service(createServiceConfig(id, consumerBuilder));
+ }
+
+ private <S> ServiceConfig createServiceConfig(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
+ ServiceBuilder builder = createServiceBuilder(id);
+ consumerBuilder.accept(builder);
+ ServiceConfig serviceConfig = builder.build();
+ return serviceConfig;
+ }
+
+ public DubboBootstrap services(List<ServiceConfig> serviceConfigs) {
+ if (CollectionUtils.isEmpty(serviceConfigs)) {
+ return this;
+ }
+ for (ServiceConfig serviceConfig : serviceConfigs) {
+ this.service(serviceConfig);
+ }
return this;
}
public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
- getCurrentModule().service(serviceConfig);
+ this.service(serviceConfig, applicationModel.getDefaultModule());
return this;
}
- public DubboBootstrap services(List<ServiceConfig> serviceConfigs) {
- getCurrentModule().services(serviceConfigs);
+ public DubboBootstrap service(ServiceConfig<?> serviceConfig, ModuleModel moduleModel) {
+ serviceConfig.setScopeModel(moduleModel);
+ moduleModel.getConfigManager().addService(serviceConfig);
return this;
}
// {@link Reference} correlative methods
public <S> DubboBootstrap reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
- getCurrentModule().reference(consumerBuilder);
- return this;
+ return reference(null, consumerBuilder);
}
public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
- getCurrentModule().reference(id, consumerBuilder);
+ return reference(createReferenceConfig(id, consumerBuilder));
+ }
+
+ private <S> ReferenceConfig createReferenceConfig(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
+ ReferenceBuilder builder = createReferenceBuilder(id);
+ consumerBuilder.accept(builder);
+ ReferenceConfig referenceConfig = builder.build();
+ return referenceConfig;
+ }
+
+ public DubboBootstrap references(List<ReferenceConfig> referenceConfigs) {
+ if (CollectionUtils.isEmpty(referenceConfigs)) {
+ return this;
+ }
+ for (ReferenceConfig referenceConfig : referenceConfigs) {
+ this.reference(referenceConfig);
+ }
return this;
}
public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
- getCurrentModule().reference(referenceConfig);
- return this;
+ return reference(referenceConfig, applicationModel.getDefaultModule());
}
- public DubboBootstrap references(List<ReferenceConfig> referenceConfigs) {
- getCurrentModule().references(referenceConfigs);
+ public DubboBootstrap reference(ReferenceConfig<?> referenceConfig, ModuleModel moduleModel) {
+ referenceConfig.setScopeModel(moduleModel);
+ moduleModel.getConfigManager().addReference(referenceConfig);
return this;
}
// {@link ProviderConfig} correlative methods
public DubboBootstrap provider(Consumer<ProviderBuilder> builderConsumer) {
- getCurrentModule().provider(builderConsumer);
+ provider(null, builderConsumer);
return this;
}
public DubboBootstrap provider(String id, Consumer<ProviderBuilder> builderConsumer) {
- getCurrentModule().provider(id, builderConsumer);
+ this.provider(createProviderConfig(id, builderConsumer));
return this;
}
+ private ProviderConfig createProviderConfig(String id, Consumer<ProviderBuilder> builderConsumer) {
+ ProviderBuilder builder = createProviderBuilder(id);
+ builderConsumer.accept(builder);
+ ProviderConfig providerConfig = builder.build();
+ return providerConfig;
+ }
+
public DubboBootstrap provider(ProviderConfig providerConfig) {
- return providers(singletonList(providerConfig));
+ return this.provider(providerConfig, applicationModel.getDefaultModule());
}
public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
- getCurrentModule().providers(providerConfigs);
+ for (ProviderConfig providerConfig : providerConfigs) {
+ this.provider(providerConfig, applicationModel.getDefaultModule());
+ }
+ return this;
+ }
+
+ public DubboBootstrap provider(ProviderConfig providerConfig, ModuleModel moduleModel) {
+ providerConfig.setScopeModel(moduleModel);
+ moduleModel.getConfigManager().addProvider(providerConfig);
return this;
}
// {@link ConsumerConfig} correlative methods
public DubboBootstrap consumer(Consumer<ConsumerBuilder> builderConsumer) {
- getCurrentModule().consumer(builderConsumer);
- return this;
+ return consumer(null, builderConsumer);
}
public DubboBootstrap consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
- getCurrentModule().consumer(id, builderConsumer);
- return this;
+ return consumer(createConsumerConfig(id, builderConsumer));
+ }
+
+ private ConsumerConfig createConsumerConfig(String id, Consumer<ConsumerBuilder> builderConsumer) {
+ ConsumerBuilder builder = createConsumerBuilder(id);
+ builderConsumer.accept(builder);
+ ConsumerConfig consumerConfig = builder.build();
+ return consumerConfig;
}
public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
- getCurrentModule().consumer(consumerConfig);
- return this;
+ return this.consumer(consumerConfig, applicationModel.getDefaultModule());
}
public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
- getCurrentModule().consumers(consumerConfigs);
+ for (ConsumerConfig consumerConfig : consumerConfigs) {
+ this.consumer(consumerConfig, applicationModel.getDefaultModule());
+ }
+ return this;
+ }
+
+ public DubboBootstrap consumer(ConsumerConfig consumerConfig, ModuleModel moduleModel) {
+ consumerConfig.setScopeModel(moduleModel);
+ moduleModel.getConfigManager().addConsumer(consumerConfig);
return this;
}
// module configs end
@@ -566,7 +606,6 @@ public final class DubboBootstrap {
}
public DubboBootstrap module(ModuleConfig module) {
- //TODO module config?
module.setScopeModel(applicationModel);
configManager.setModule(module);
return this;
@@ -578,1307 +617,99 @@ public final class DubboBootstrap {
return this;
}
- public ReferenceConfigCache getCache() {
- return cache;
- }
+ /* serve for builder apis, begin */
- /**
- * Initialize
- */
- public synchronized void initialize() {
- if (!initialized.compareAndSet(false, true)) {
- return;
- }
+ private ApplicationBuilder createApplicationBuilder(String name) {
+ return new ApplicationBuilder().name(name);
+ }
- startConfigCenter();
+ private RegistryBuilder createRegistryBuilder(String id) {
+ return new RegistryBuilder().id(id);
+ }
- loadConfigsFromProps();
+ private ProtocolBuilder createProtocolBuilder(String id) {
+ return new ProtocolBuilder().id(id);
+ }
- checkGlobalConfigs();
+ private ServiceBuilder createServiceBuilder(String id) {
+ return new ServiceBuilder().id(id);
+ }
- // @since 2.7.8
- startMetadataCenter();
+ private ReferenceBuilder createReferenceBuilder(String id) {
+ return new ReferenceBuilder().id(id);
+ }
- initMetadataService();
+ private ProviderBuilder createProviderBuilder(String id) {
+ return new ProviderBuilder().id(id);
+ }
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " has been initialized!");
- }
+ private ConsumerBuilder createConsumerBuilder(String id) {
+ return new ConsumerBuilder().id(id);
}
+ /* serve for builder apis, end */
- private void checkGlobalConfigs() {
- // check config types (ignore metadata-center)
- List<Class<? extends AbstractConfig>> multipleConfigTypes = Arrays.asList(
- ApplicationConfig.class,
- ProtocolConfig.class,
- RegistryConfig.class,
- MetadataReportConfig.class,
- ProviderConfig.class,
- ConsumerConfig.class,
- MonitorConfig.class,
- ModuleConfig.class,
- MetricsConfig.class,
- SslConfig.class);
-
- for (Class<? extends AbstractConfig> configType : multipleConfigTypes) {
- checkDefaultAndValidateConfigs(configType);
- }
- // check port conflicts
- Map<Integer, ProtocolConfig> protocolPortMap = new LinkedHashMap<>();
- for (ProtocolConfig protocol : configManager.getProtocols()) {
- Integer port = protocol.getPort();
- if (port == null || port == -1) {
- continue;
- }
- ProtocolConfig prevProtocol = protocolPortMap.get(port);
- if (prevProtocol != null) {
- throw new IllegalStateException("Duplicated port used by protocol configs, port: " + port +
- ", configs: " + Arrays.asList(prevProtocol, protocol));
- }
- protocolPortMap.put(port, protocol);
- }
+ public Module newModule() {
+ return new Module(applicationModel.newModule());
+ }
- // check reference and service
- for (ReferenceConfigBase<?> reference : configManager.getReferences()) {
- reference.refresh();
- }
- for (ServiceConfigBase service : configManager.getServices()) {
- service.refresh();
- }
+ public DubboBootstrap endModule() {
+ return this;
}
- private <T extends AbstractConfig> void checkDefaultAndValidateConfigs(Class<T> configType) {
- try {
- if (shouldAddDefaultConfig(configType)) {
- T config = createConfig(configType);
- config.refresh();
- if (!isNeedValidation(config) || config.isValid()) {
- configManager.addConfig(config);
- } else {
- logger.info("Ignore invalid config: " + config);
- }
- }
- } catch (Exception e) {
- throw new IllegalStateException("Add default config failed: " + configType.getSimpleName(), e);
- }
- //validate configs
- Collection<T> configs = configManager.getConfigs(configType);
- for (T config : configs) {
- validateConfig(config);
- }
+ public class Module {
+ private ModuleModel moduleModel;
+ private DubboBootstrap bootstrap;
- // check required default
- if (isRequired(configType) && configs.isEmpty()) {
- throw new IllegalStateException("Default config not found for " + configType.getSimpleName());
+ public Module(ModuleModel moduleModel) {
+ this.moduleModel = moduleModel;
+ this.bootstrap = DubboBootstrap.this;
}
- }
- /**
- * The component configuration that does not affect the main process does not need to be verified.
- *
- * @param config
- * @param <T>
- * @return
- */
- private <T extends AbstractConfig> boolean isNeedValidation(T config) {
- if (config instanceof MetadataReportConfig) {
- return false;
- }
- return true;
- }
-
- private <T extends AbstractConfig> void validateConfig(T config) {
- if (config instanceof ProtocolConfig) {
- ConfigValidationUtils.validateProtocolConfig((ProtocolConfig) config);
- } else if (config instanceof RegistryConfig) {
- ConfigValidationUtils.validateRegistryConfig((RegistryConfig) config);
- } else if (config instanceof MetadataReportConfig) {
- ConfigValidationUtils.validateMetadataConfig((MetadataReportConfig) config);
- } else if (config instanceof ProviderConfig) {
- ConfigValidationUtils.validateProviderConfig((ProviderConfig) config);
- } else if (config instanceof ConsumerConfig) {
- ConfigValidationUtils.validateConsumerConfig((ConsumerConfig) config);
- } else if (config instanceof ApplicationConfig) {
- ConfigValidationUtils.validateApplicationConfig((ApplicationConfig) config);
- } else if (config instanceof MonitorConfig) {
- ConfigValidationUtils.validateMonitorConfig((MonitorConfig) config);
- } else if (config instanceof ModuleConfig) {
- ConfigValidationUtils.validateModuleConfig((ModuleConfig) config);
- } else if (config instanceof MetricsConfig) {
- ConfigValidationUtils.validateMetricsConfig((MetricsConfig) config);
- } else if (config instanceof SslConfig) {
- ConfigValidationUtils.validateSslConfig((SslConfig) config);
+ public DubboBootstrap endModule() {
+ return this.bootstrap.endModule();
}
- }
- /**
- * The configuration that does not affect the main process is not necessary.
- *
- * @param clazz
- * @param <T>
- * @return
- */
- private <T extends AbstractConfig> boolean isRequired(Class<T> clazz) {
- if (clazz == RegistryConfig.class ||
- clazz == MetadataReportConfig.class ||
- clazz == MonitorConfig.class ||
- clazz == MetricsConfig.class) {
- return false;
+ public ModuleModel getModuleModel() {
+ return moduleModel;
}
- return true;
- }
- private <T extends AbstractConfig> boolean shouldAddDefaultConfig(Class<T> clazz) {
- // Configurations that are not required will not be automatically added to the default configuration
- if (!isRequired(clazz)) {
- return false;
+ // {@link ServiceConfig} correlative methods
+ public <S> Module service(Consumer<ServiceBuilder<S>> consumerBuilder) {
+ return service(null, consumerBuilder);
}
- return configManager.getDefaultConfigs(clazz).isEmpty();
- }
-
- private void startConfigCenter() {
-
- // load application config
- loadConfigs(ApplicationConfig.class);
-
- // load config centers
- loadConfigs(ConfigCenterConfig.class);
-
- useRegistryAsConfigCenterIfNecessary();
+ public <S> Module service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
+ return service(createServiceConfig(id, consumerBuilder));
+ }
- // check Config Center
- Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
- if (CollectionUtils.isEmpty(configCenters)) {
- ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
- configCenterConfig.setScopeModel(applicationModel);
- configCenterConfig.refresh();
- ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
- if (configCenterConfig.isValid()) {
- configManager.addConfigCenter(configCenterConfig);
- configCenters = configManager.getConfigCenters();
+ public Module services(List<ServiceConfig> serviceConfigs) {
+ if (CollectionUtils.isEmpty(serviceConfigs)) {
+ return this;
}
- } else {
- for (ConfigCenterConfig configCenterConfig : configCenters) {
- configCenterConfig.refresh();
- ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
+ for (ServiceConfig serviceConfig : serviceConfigs) {
+ this.service(serviceConfig);
}
+ return this;
}
- if (CollectionUtils.isNotEmpty(configCenters)) {
- CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
- for (ConfigCenterConfig configCenter : configCenters) {
- // Pass config from ConfigCenterBean to environment
- environment.updateExternalConfigMap(configCenter.getExternalConfiguration());
- environment.updateAppExternalConfigMap(configCenter.getAppExternalConfiguration());
-
- // Fetch config from remote config center
- compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
- }
- environment.setDynamicConfiguration(compositeDynamicConfiguration);
+ public Module service(ServiceConfig<?> serviceConfig) {
+ DubboBootstrap.this.service(serviceConfig, moduleModel);
+ return this;
}
- configManager.refreshAll();
- }
-
- private void startMetadataCenter() {
+ // {@link Reference} correlative methods
+ public <S> Module reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
+ return reference(null, consumerBuilder);
+ }
- useRegistryAsMetadataCenterIfNecessary();
-
- ApplicationConfig applicationConfig = getApplication();
-
- String metadataType = applicationConfig.getMetadataType();
- // FIXME, multiple metadata config support.
- Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
- if (CollectionUtils.isEmpty(metadataReportConfigs)) {
- if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
- throw new IllegalStateException("No MetadataConfig found, Metadata Center address is required when 'metadata=remote' is enabled.");
- }
- return;
- }
-
- MetadataReportInstance metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class);
- for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
- ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
- if (!metadataReportConfig.isValid()) {
- logger.info("Ignore invalid metadata-report config: " + metadataReportConfig);
- continue;
- }
- metadataReportInstance.init(metadataReportConfig);
- }
- }
-
- /**
- * For compatibility purpose, use registry as the default config center when
- * there's no config center specified explicitly and
- * useAsConfigCenter of registryConfig is null or true
- */
- private void useRegistryAsConfigCenterIfNecessary() {
- // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
- if (environment.getDynamicConfiguration().isPresent()) {
- return;
- }
-
- if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
- return;
- }
-
- // load registry
- loadConfigs(RegistryConfig.class);
-
- List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
- if (defaultRegistries.size() > 0) {
- defaultRegistries
- .stream()
- .filter(this::isUsedRegistryAsConfigCenter)
- .map(this::registryAsConfigCenter)
- .forEach(configCenter -> {
- if (configManager.getConfigCenter(configCenter.getId()).isPresent()) {
- return;
- }
- configManager.addConfigCenter(configCenter);
- logger.info("use registry as config-center: " + configCenter);
-
- });
- }
- }
-
- private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
- return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsConfigCenter, "config",
- DynamicConfigurationFactory.class);
- }
-
- private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) {
- String protocol = registryConfig.getProtocol();
- Integer port = registryConfig.getPort();
- URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel());
- String id = "config-center-" + protocol + "-" + url.getHost() + "-" + port;
- ConfigCenterConfig cc = new ConfigCenterConfig();
- cc.setId(id);
- cc.setScopeModel(applicationModel);
- if (cc.getParameters() == null) {
- cc.setParameters(new HashMap<>());
- }
- if (registryConfig.getParameters() != null) {
- cc.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
- }
- cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
- cc.setProtocol(protocol);
- cc.setPort(port);
- if (StringUtils.isNotEmpty(registryConfig.getGroup())) {
- cc.setGroup(registryConfig.getGroup());
- }
- cc.setAddress(getRegistryCompatibleAddress(registryConfig));
- cc.setNamespace(registryConfig.getGroup());
- cc.setUsername(registryConfig.getUsername());
- cc.setPassword(registryConfig.getPassword());
- if (registryConfig.getTimeout() != null) {
- cc.setTimeout(registryConfig.getTimeout().longValue());
- }
- cc.setHighestPriority(false);
- return cc;
- }
-
- private void useRegistryAsMetadataCenterIfNecessary() {
-
- Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();
-
- if (CollectionUtils.isNotEmpty(metadataConfigs)) {
- return;
- }
-
- List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
- if (defaultRegistries.size() > 0) {
- defaultRegistries
- .stream()
- .filter(this::isUsedRegistryAsMetadataCenter)
- .map(this::registryAsMetadataCenter)
- .forEach(metadataReportConfig -> {
- Optional<MetadataReportConfig> configOptional = configManager.getConfig(MetadataReportConfig.class, metadataReportConfig.getId());
- if (configOptional.isPresent()) {
- return;
- }
- configManager.addMetadataReport(metadataReportConfig);
- logger.info("use registry as metadata-center: " + metadataReportConfig);
- });
- }
- }
-
- private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
- return isUsedRegistryAsCenter(registryConfig, registryConfig::getUseAsMetadataCenter, "metadata",
- MetadataReportFactory.class);
- }
-
- /**
- * Is used the specified registry as a center infrastructure
- *
- * @param registryConfig the {@link RegistryConfig}
- * @param usedRegistryAsCenter the configured value on
- * @param centerType the type name of center
- * @param extensionClass an extension class of a center infrastructure
- * @return
- * @since 2.7.8
- */
- private boolean isUsedRegistryAsCenter(RegistryConfig registryConfig, Supplier<Boolean> usedRegistryAsCenter,
- String centerType,
- Class<?> extensionClass) {
- final boolean supported;
-
- Boolean configuredValue = usedRegistryAsCenter.get();
- if (configuredValue != null) { // If configured, take its value.
- supported = configuredValue.booleanValue();
- } else { // Or check the extension existence
- String protocol = registryConfig.getProtocol();
- supported = supportsExtension(extensionClass, protocol);
- if (logger.isInfoEnabled()) {
- logger.info(format("No value is configured in the registry, the %s extension[name : %s] %s as the %s center"
- , extensionClass.getSimpleName(), protocol, supported ? "supports" : "does not support", centerType));
- }
- }
-
- if (logger.isInfoEnabled()) {
- logger.info(format("The registry[%s] will be %s as the %s center", registryConfig,
- supported ? "used" : "not used", centerType));
- }
- return supported;
- }
-
- /**
- * Supports the extension with the specified class and name
- *
- * @param extensionClass the {@link Class} of extension
- * @param name the name of extension
- * @return if supports, return <code>true</code>, or <code>false</code>
- * @since 2.7.8
- */
- private boolean supportsExtension(Class<?> extensionClass, String name) {
- if (isNotEmpty(name)) {
- ExtensionLoader extensionLoader = getExtensionLoader(extensionClass);
- return extensionLoader.hasExtension(name);
- }
- return false;
- }
-
- private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) {
- String protocol = registryConfig.getProtocol();
- URL url = URL.valueOf(registryConfig.getAddress(), registryConfig.getScopeModel());
- String id = "metadata-center-" + protocol + "-" + url.getHost() + "-" + url.getPort();
- MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
- metadataReportConfig.setId(id);
- metadataReportConfig.setScopeModel(applicationModel);
- if (metadataReportConfig.getParameters() == null) {
- metadataReportConfig.setParameters(new HashMap<>());
- }
- if (registryConfig.getParameters() != null) {
- metadataReportConfig.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
- }
- metadataReportConfig.getParameters().put(CLIENT_KEY, registryConfig.getClient());
- metadataReportConfig.setGroup(registryConfig.getGroup());
- metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig));
- metadataReportConfig.setUsername(registryConfig.getUsername());
- metadataReportConfig.setPassword(registryConfig.getPassword());
- metadataReportConfig.setTimeout(registryConfig.getTimeout());
- return metadataReportConfig;
- }
-
- private String getRegistryCompatibleAddress(RegistryConfig registryConfig) {
- String registryAddress = registryConfig.getAddress();
- String[] addresses = REGISTRY_SPLIT_PATTERN.split(registryAddress);
- if (ArrayUtils.isEmpty(addresses)) {
- throw new IllegalStateException("Invalid registry address found.");
- }
- String address = addresses[0];
- // since 2.7.8
- // Issue : https://github.com/apache/dubbo/issues/6476
- StringBuilder metadataAddressBuilder = new StringBuilder();
- URL url = URL.valueOf(address, registryConfig.getScopeModel());
- String protocolFromAddress = url.getProtocol();
- if (isEmpty(protocolFromAddress)) {
- // If the protocol from address is missing, is like :
- // "dubbo.registry.address = 127.0.0.1:2181"
- String protocolFromConfig = registryConfig.getProtocol();
- metadataAddressBuilder.append(protocolFromConfig).append("://");
- }
- metadataAddressBuilder.append(address);
- return metadataAddressBuilder.toString();
- }
-
- private void loadConfigsFromProps() {
-
- // application config has load before starting config center
- // load dubbo.applications.xxx
- loadConfigs(ApplicationConfig.class);
-
- // load dubbo.modules.xxx
- loadConfigs(ModuleConfig.class);
-
- // load dubbo.monitors.xxx
- loadConfigs(MonitorConfig.class);
-
- // load dubbo.metricses.xxx
- loadConfigs(MetricsConfig.class);
-
- // load multiple config types:
- // load dubbo.protocols.xxx
- loadConfigs(ProtocolConfig.class);
-
- // load dubbo.registries.xxx
- loadConfigs(RegistryConfig.class);
-
- // load dubbo.providers.xxx
- loadConfigs(ProviderConfig.class);
-
- // load dubbo.consumers.xxx
- loadConfigs(ConsumerConfig.class);
-
- // load dubbo.metadata-report.xxx
- loadConfigs(MetadataReportConfig.class);
-
- // config centers has bean loaded before starting config center
- //loadConfigs(ConfigCenterConfig.class);
-
- }
-
- private <T extends AbstractConfig> void loadConfigs(Class<T> cls) {
- // load multiple configs with id
- Set<String> configIds = this.getConfigIds(cls);
- configIds.forEach(id -> {
- if (!configManager.getConfig(cls, id).isPresent()) {
- T config = null;
- try {
- config = createConfig(cls);
- config.setId(id);
- } catch (Exception e) {
- throw new IllegalStateException("create config instance failed, id: " + id + ", type:" + cls.getSimpleName());
- }
-
- String key = null;
- boolean addDefaultNameConfig = false;
- try {
- // add default name config (same as id), e.g. dubbo.protocols.rest.port=1234
- key = DUBBO + "." + AbstractConfig.getPluralTagName(cls) + "." + id + ".name";
- if (applicationModel.getApplicationEnvironment().getPropertiesConfiguration().getProperty(key) == null) {
- applicationModel.getApplicationEnvironment().getPropertiesConfiguration().setProperty(key, id);
- addDefaultNameConfig = true;
- }
-
- config.refresh();
- configManager.addConfig(config);
- } catch (Exception e) {
- logger.error("load config failed, id: " + id + ", type:" + cls.getSimpleName(), e);
- throw new IllegalStateException("load config failed, id: " + id + ", type:" + cls.getSimpleName());
- } finally {
- if (addDefaultNameConfig && key != null) {
- applicationModel.getApplicationEnvironment().getPropertiesConfiguration().remove(key);
- }
- }
- }
- });
-
- // If none config of the type, try load single config
- if (configManager.getConfigs(cls).isEmpty()) {
- // load single config
- List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
- if (ConfigurationUtils.hasSubProperties(configurationMaps, AbstractConfig.getTypePrefix(cls))) {
- T config = null;
- try {
- config = createConfig(cls);
- config.refresh();
- } catch (Exception e) {
- throw new IllegalStateException("create default config instance failed, type:" + cls.getSimpleName());
- }
-
- configManager.addConfig(config);
- }
- }
-
- }
-
- private <T extends AbstractConfig> T createConfig(Class<T> cls) throws InstantiationException, IllegalAccessException {
- T config = cls.newInstance();
- if (config instanceof ProviderConfig || config instanceof ConsumerConfig || config instanceof ReferenceConfigBase
- || config instanceof ServiceConfigBase) {
- config.setScopeModel(getCurrentModule().moduleModel);
- } else {
- config.setScopeModel(applicationModel);
- }
- return config;
- }
-
- /**
- * Search props and extract config ids of specify type.
- * <pre>
- * # properties
- * dubbo.registries.registry1.address=xxx
- * dubbo.registries.registry2.port=xxx
- *
- * # extract
- * Set configIds = getConfigIds(RegistryConfig.class)
- *
- * # result
- * configIds: ["registry1", "registry2"]
- * </pre>
- *
- * @param clazz config type
- * @return ids of specify config type
- */
- private Set<String> getConfigIds(Class<? extends AbstractConfig> clazz) {
- String prefix = CommonConstants.DUBBO + "." + AbstractConfig.getPluralTagName(clazz) + ".";
- return ConfigurationUtils.getSubIds(environment.getConfigurationMaps(), prefix);
- }
-
- /**
- * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
- */
- private void initMetadataService() {
-// startMetadataCenter();
- this.metadataService = getExtensionLoader(WritableMetadataService.class).getDefaultExtension();
- // support injection by super type MetadataService
- applicationModel.getBeanFactory().registerBean(this.metadataService);
-
- //this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
- this.metadataServiceExporter = getExtensionLoader(MetadataServiceExporter.class).getDefaultExtension();
- }
-
- /**
- * Start the bootstrap
- */
- public synchronized DubboBootstrap start() {
- // avoid re-entry start method multiple times in same thread
- if (isCurrentlyInStart) {
- return this;
- }
-
- isCurrentlyInStart = true;
- try {
- if (started.compareAndSet(false, true)) {
- startup.set(false);
- shutdown.set(false);
- awaited.set(false);
-
- initialize();
-
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " is starting...");
- }
-
- doStart();
-
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " has started.");
- }
- } else {
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " is started, export/refer new services.");
- }
-
- doStart();
-
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " finish export/refer new services.");
- }
- }
- return this;
- } finally {
- isCurrentlyInStart = false;
- }
- }
-
- private void doStart() {
- // 1. export Dubbo Services
- exportServices();
-
- // If register consumer instance or has exported services
- if (isRegisterConsumerInstance() || hasExportedServices()) {
- // 2. export MetadataService
- exportMetadataService();
- // 3. Register the local ServiceInstance if required
- registerServiceInstance();
- }
-
- referServices();
-
- // wait async export / refer finish if needed
- awaitFinish();
-
- if (isExportBackground() || isReferBackground()) {
- new Thread(() -> {
- while (!asyncExportFinish || !asyncReferFinish) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- logger.error(NAME + " waiting async export / refer occurred and error.", e);
- }
- }
- onStarted();
- }).start();
- } else {
- onStarted();
- }
- }
-
- private boolean hasExportedServices() {
- return CollectionUtils.isNotEmpty(configManager.getServices());
- }
-
- /**
- * Block current thread to be await.
- *
- * @return {@link DubboBootstrap}
- */
- public DubboBootstrap await() {
- // if has been waited, no need to wait again, return immediately
- if (!awaited.get()) {
- if (!executorService.isShutdown()) {
- executeMutually(() -> {
- while (!awaited.get()) {
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " awaiting ...");
- }
- try {
- condition.await();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- }
- }
- });
- }
- }
- return this;
- }
-
- private void waitAsyncExportIfNeeded() {
- if (asyncExportingFutures.size() > 0) {
- asyncExportFinish = false;
- if (isExportBackground()) {
- new Thread(this::waitExportFinish).start();
- } else {
- waitExportFinish();
- }
- }
- }
-
- private boolean isExportBackground() {
- List<Boolean> list = configManager.getProviders()
- .stream()
- .map(ProviderConfig::getExportBackground)
- .filter(k -> k != null && k)
- .collect(Collectors.toList());
-
- return CollectionUtils.isNotEmpty(list);
- }
-
- private void waitExportFinish() {
- try {
- logger.info(NAME + " waiting services exporting asynchronously...");
- CompletableFuture<?> future = CompletableFuture.allOf(asyncExportingFutures.toArray(new CompletableFuture[0]));
- future.get();
- } catch (Exception e) {
- logger.warn(NAME + " asynchronous export occurred an exception.");
- } finally {
- executorRepository.shutdownServiceExportExecutor();
- logger.info(NAME + " asynchronous export finished.");
- asyncExportFinish = true;
- }
- }
-
- private void waitAsyncReferIfNeeded() {
- if (asyncReferringFutures.size() > 0) {
- asyncReferFinish = false;
- if (isReferBackground()) {
- new Thread(this::waitReferFinish).start();
- } else {
- waitReferFinish();
- }
- }
- }
-
- private boolean isReferBackground() {
- List<Boolean> list = configManager.getConsumers()
- .stream()
- .map(ConsumerConfig::getReferBackground)
- .filter(k -> k != null && k)
- .collect(Collectors.toList());
-
- return CollectionUtils.isNotEmpty(list);
- }
-
- private void waitReferFinish() {
- try {
- logger.info(NAME + " waiting services referring asynchronously...");
- CompletableFuture<?> future = CompletableFuture.allOf(asyncReferringFutures.toArray(new CompletableFuture[0]));
- future.get();
- } catch (Exception e) {
- logger.warn(NAME + " asynchronous refer occurred an exception.");
- } finally {
- executorRepository.shutdownServiceExportExecutor();
- logger.info(NAME + " asynchronous refer finished.");
- asyncReferFinish = true;
- }
- }
-
- private void awaitFinish() {
- waitAsyncExportIfNeeded();
- waitAsyncReferIfNeeded();
- }
-
- public boolean isInitialized() {
- return initialized.get();
- }
-
- public boolean isStarted() {
- return started.get();
- }
-
- public boolean isStartup() {
- return startup.get();
- }
-
- public boolean isShutdown() {
- return shutdown.get();
- }
-
-
- public DubboBootstrap stop() throws IllegalStateException {
- destroy();
- return this;
- }
- /* serve for builder apis, begin */
-
- private ApplicationBuilder createApplicationBuilder(String name) {
- return new ApplicationBuilder().name(name);
- }
-
- private RegistryBuilder createRegistryBuilder(String id) {
- return new RegistryBuilder().id(id);
- }
-
- private ProtocolBuilder createProtocolBuilder(String id) {
- return new ProtocolBuilder().id(id);
- }
-
- private ServiceBuilder createServiceBuilder(String id) {
- return new ServiceBuilder().id(id);
- }
-
- private ReferenceBuilder createReferenceBuilder(String id) {
- return new ReferenceBuilder().id(id);
- }
-
- private ProviderBuilder createProviderBuilder(String id) {
- return new ProviderBuilder().id(id);
- }
-
- private ConsumerBuilder createConsumerBuilder(String id) {
- return new ConsumerBuilder().id(id);
- }
- /* serve for builder apis, end */
-
- private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
- if (configCenter.isValid()) {
- if (!configCenter.checkOrUpdateInitialized(true)) {
- return null;
- }
-
- DynamicConfiguration dynamicConfiguration = null;
- try {
- dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
- } catch (Exception e) {
- if (!configCenter.isCheck()) {
- logger.warn("The configuration center failed to initialize", e);
- configCenter.checkOrUpdateInitialized(false);
- return null;
- } else {
- throw new IllegalStateException(e);
- }
- }
-
- String configContent = dynamicConfiguration.getProperties(configCenter.getConfigFile(), configCenter.getGroup());
-
- String appGroup = getApplication().getName();
- String appConfigContent = null;
- if (isNotEmpty(appGroup)) {
- appConfigContent = dynamicConfiguration.getProperties
- (isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
- appGroup
- );
- }
- try {
- environment.updateExternalConfigMap(parseProperties(configContent));
- environment.updateAppExternalConfigMap(parseProperties(appConfigContent));
- } catch (IOException e) {
- throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
- }
- return dynamicConfiguration;
- }
- return null;
- }
-
- /**
- * Get the instance of {@link DynamicConfiguration} by the specified connection {@link URL} of config-center
- *
- * @param connectionURL of config-center
- * @return non-null
- * @since 2.7.5
- */
- private DynamicConfiguration getDynamicConfiguration(URL connectionURL) {
- String protocol = connectionURL.getProtocol();
-
- DynamicConfigurationFactory factory = ConfigurationUtils.getDynamicConfigurationFactory(applicationModel, protocol);
- return factory.getDynamicConfiguration(connectionURL);
- }
-
- /**
- * export {@link MetadataService}
- */
- private void exportMetadataService() {
- metadataServiceExporter.export();
- }
-
- private void unexportMetadataService() {
- if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
- try {
- metadataServiceExporter.unexport();
- } catch (Exception ignored) {
- // ignored
- }
- }
- }
-
- private void exportServices() {
- for (ServiceConfigBase sc : configManager.getServices()) {
- // TODO, compatible with ServiceConfig.export()
- ServiceConfig<?> serviceConfig = (ServiceConfig<?>) sc;
- serviceConfig.setBootstrap(this);
- if (!serviceConfig.isRefreshed()) {
- serviceConfig.refresh();
- }
- if (sc.isExported()) {
- continue;
- }
- if (sc.shouldExportAsync()) {
- ExecutorService executor = executorRepository.getServiceExportExecutor();
- CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
- try {
- if (!sc.isExported()) {
- sc.export();
- exportedServices.add(sc);
- }
- } catch (Throwable t) {
- logger.error("export async catch error : " + t.getMessage(), t);
- }
- }, executor);
-
- asyncExportingFutures.add(future);
- } else {
- if (!sc.isExported()) {
- sc.export();
- exportedServices.add(sc);
- }
- }
- }
- }
-
- private void unexportServices() {
- exportedServices.forEach(sc -> {
- try {
- configManager.removeConfig(sc);
- sc.unexport();
- } catch (Exception ignored) {
- // ignored
- }
- });
-
- asyncExportingFutures.forEach(future -> {
- if (!future.isDone()) {
- future.cancel(true);
- }
- });
- asyncExportingFutures.clear();
- exportedServices.clear();
- }
-
- private void referServices() {
- configManager.getReferences().forEach(rc -> {
- try {
- // TODO, compatible with ReferenceConfig.refer()
- ReferenceConfig<?> referenceConfig = (ReferenceConfig<?>) rc;
- referenceConfig.setBootstrap(this);
- if (!referenceConfig.isRefreshed()) {
- referenceConfig.refresh();
- }
-
- if (rc.shouldInit()) {
- if (rc.shouldReferAsync()) {
- ExecutorService executor = executorRepository.getServiceReferExecutor();
- CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
- try {
- cache.get(rc);
- } catch (Throwable t) {
- logger.error("refer async catch error : " + t.getMessage(), t);
- }
- }, executor);
-
- asyncReferringFutures.add(future);
- } else {
- cache.get(rc);
- }
- }
- } catch (Throwable t) {
- logger.error("refer catch error", t);
- cache.destroy(rc);
- }
- });
- }
-
- private void unreferServices() {
- try {
- asyncReferringFutures.forEach(future -> {
- if (!future.isDone()) {
- future.cancel(true);
- }
- });
- asyncReferringFutures.clear();
- cache.destroyAll();
- } catch (Exception ignored) {
- }
- }
-
- protected void registerServiceInstance() {
- if (this.serviceInstance != null) {
- return;
- }
-
- ApplicationConfig application = getApplication();
- String serviceName = application.getName();
- ServiceInstance serviceInstance = createServiceInstance(serviceName);
- boolean registered = true;
- try {
- ServiceInstanceMetadataUtils.registerMetadataAndInstance(serviceInstance);
- } catch (Exception e) {
- registered = false;
- logger.error("Register instance error", e);
- }
- if (registered) {
- // scheduled task for updating Metadata and ServiceInstance
- asyncMetadataFuture = executorRepository.nextScheduledExecutor().scheduleAtFixedRate(() -> {
- InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService) WritableMetadataService.getDefaultExtension(applicationModel);
- localMetadataService.blockUntilUpdated();
- try {
- ServiceInstanceMetadataUtils.refreshMetadataAndInstance(serviceInstance);
- } catch (Exception e) {
- logger.error("Refresh instance and metadata error", e);
- } finally {
- localMetadataService.releaseBlock();
- }
- }, 0, ConfigurationUtils.get(applicationModel, METADATA_PUBLISH_DELAY_KEY, DEFAULT_METADATA_PUBLISH_DELAY), TimeUnit.MILLISECONDS);
- }
- }
-
- private void doRegisterServiceInstance(ServiceInstance serviceInstance) {
- // register instance only when at least one service is exported.
- if (serviceInstance.getPort() > 0) {
- publishMetadataToRemote(serviceInstance);
- logger.info("Start registering instance address to registry.");
- getServiceDiscoveries().forEach(serviceDiscovery ->
- {
- ServiceInstance serviceInstanceForRegistry = new DefaultServiceInstance((DefaultServiceInstance) serviceInstance);
- calInstanceRevision(serviceDiscovery, serviceInstanceForRegistry);
- if (logger.isDebugEnabled()) {
- logger.info("Start registering instance address to registry" + serviceDiscovery.getUrl() + ", instance " + serviceInstanceForRegistry);
- }
- // register metadata
- serviceDiscovery.register(serviceInstanceForRegistry);
- });
- }
- }
-
- private void publishMetadataToRemote(ServiceInstance serviceInstance) {
-// InMemoryWritableMetadataService localMetadataService = (InMemoryWritableMetadataService)WritableMetadataService.getDefaultExtension();
-// localMetadataService.blockUntilUpdated();
- if (logger.isInfoEnabled()) {
- logger.info("Start publishing metadata to remote center, this only makes sense for applications enabled remote metadata center.");
- }
- RemoteMetadataServiceImpl remoteMetadataService = applicationModel.getBeanFactory().getBean(RemoteMetadataServiceImpl.class);
- remoteMetadataService.publishMetadata(serviceInstance.getServiceName());
- }
-
-
- private void unregisterServiceInstance() {
- if (serviceInstance != null) {
- getServiceDiscoveries().forEach(serviceDiscovery -> {
- try {
- serviceDiscovery.unregister(serviceInstance);
- } catch (Exception ignored) {
- // ignored
- }
- });
- }
- }
-
- private ServiceInstance createServiceInstance(String serviceName) {
- this.serviceInstance = new DefaultServiceInstance(serviceName, applicationModel);
- setMetadataStorageType(serviceInstance, getMetadataType());
- ServiceInstanceMetadataUtils.customizeInstance(this.serviceInstance);
- return this.serviceInstance;
- }
-
- public void destroy() {
- if (destroyLock.tryLock()
- && shutdown.compareAndSet(false, true)) {
- try {
- if (destroyed.compareAndSet(false, true)) {
- if (started.compareAndSet(true, false)) {
- unregisterServiceInstance();
- unexportMetadataService();
- unexportServices();
- unreferServices();
- if (asyncMetadataFuture != null) {
- asyncMetadataFuture.cancel(true);
- }
- }
-
- destroyRegistries();
- destroyProtocols(applicationModel.getFrameworkModel());
- destroyServiceDiscoveries();
- destroyExecutorRepository();
- destroyMetadataReports();
-
- // check config
- checkConfigState();
-
- clear();
- shutdown();
- release();
-
- onStop();
- }
-
- destroyDynamicConfigurations();
- ShutdownHookCallbacks.INSTANCE.clear();
- } catch (Throwable ignored) {
- // ignored
- logger.warn(ignored.getMessage(), ignored);
- } finally {
- initialized.set(false);
- startup.set(false);
- destroyLock.unlock();
- }
-
- applicationModel.destroy();
- }
- }
-
- private void onStarted() {
- startup.set(true);
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " is ready.");
- }
- ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
- exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
- }
-
- private void onStop() {
- ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
- exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(this));
- }
-
- private void checkConfigState() {
- // config manager should not be cleared at this moment
- if (!ignoreConfigState && !configManager.getApplication().isPresent()) {
- logger.error("Dubbo config was cleaned prematurely");
- throw new IllegalStateException("Dubbo config was cleaned prematurely");
- }
- }
-
- private void destroyExecutorRepository() {
- getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
- }
-
- private void destroyRegistries() {
- AbstractRegistryFactory.destroyAll();
- }
-
- /**
- * Destroy all the protocols.
- */
- private static void destroyProtocols(FrameworkModel frameworkModel) {
- //TODO destroy protocol in framework scope
- ExtensionLoader<Protocol> loader = frameworkModel.getExtensionLoader(Protocol.class);
- for (String protocolName : loader.getLoadedExtensions()) {
- try {
- Protocol protocol = loader.getLoadedExtension(protocolName);
- if (protocol != null) {
- protocol.destroy();
- }
- } catch (Throwable t) {
- logger.warn(t.getMessage(), t);
- }
- }
- }
-
- private static void destroyAllProtocols() {
- for (FrameworkModel frameworkModel : FrameworkModel.getAllInstances()) {
- destroyProtocols(frameworkModel);
- }
- }
-
- private void destroyServiceDiscoveries() {
- getServiceDiscoveries().forEach(serviceDiscovery -> {
- try {
- execute(serviceDiscovery::destroy);
- } catch (Throwable ignored) {
- logger.warn(ignored.getMessage(), ignored);
- }
- });
- if (logger.isDebugEnabled()) {
- logger.debug(NAME + "'s all ServiceDiscoveries have been destroyed.");
- }
- }
-
- private void destroyMetadataReports() {
- AbstractMetadataReportFactory.destroy();
- MetadataReportInstance.reset();
- }
-
- private void destroyDynamicConfigurations() {
- // DynamicConfiguration may be cached somewhere, and maybe used during destroy
- // destroy them may cause some troubles, so just clear instances cache
- // ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
- }
-
- private void clear() {
- clearConfigs();
- clearApplicationModel();
- }
-
- private void clearApplicationModel() {
-
- }
-
- private void clearConfigs() {
- configManager.destroy();
- if (logger.isDebugEnabled()) {
- logger.debug(NAME + "'s configs have been clear.");
- }
- }
-
- private void release() {
- executeMutually(() -> {
- if (awaited.compareAndSet(false, true)) {
- if (logger.isInfoEnabled()) {
- logger.info(NAME + " is about to shutdown...");
- }
- condition.signalAll();
- }
- });
- }
-
- private void shutdown() {
- if (!executorService.isShutdown()) {
- // Shutdown executorService
- try {
- executorService.shutdown();
- } catch (Throwable ignored) {
- // ignored
- logger.warn(ignored.getMessage(), ignored);
- }
- }
- }
-
- private void executeMutually(Runnable runnable) {
- try {
- lock.lock();
- runnable.run();
- } finally {
- lock.unlock();
- }
- }
-
- public ApplicationConfig getApplication() {
- return configManager.getApplicationOrElseThrow();
- }
-
- public void setTakeoverMode(BootstrapTakeoverMode takeoverMode) {
- this.started.set(false);
- this.takeoverMode = takeoverMode;
- }
-
- public BootstrapTakeoverMode getTakeoverMode() {
- return takeoverMode;
- }
-
- public Module addModule(ModuleModel moduleModel) {
- applicationModel.addModule(moduleModel);
- currentModule = new Module(moduleModel);
- return currentModule;
- }
-
- public Module addModule() {
- return this.addModule(new ModuleModel(applicationModel));
- }
-
- public DubboBootstrap endModule() {
- currentModule = new Module(applicationModel.getDefaultModule());
- return this;
- }
-
- public class Module {
- private ModuleModel moduleModel;
- private DubboBootstrap bootstrap;
-
- public Module(ModuleModel moduleModel) {
- this.moduleModel = moduleModel;
- this.bootstrap = DubboBootstrap.this;
- }
-
- public DubboBootstrap endModule() {
- return this.bootstrap.endModule();
- }
-
- // {@link ServiceConfig} correlative methods
- public <S> Module service(Consumer<ServiceBuilder<S>> consumerBuilder) {
- return service(null, consumerBuilder);
- }
-
- public <S> Module service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
- ServiceBuilder builder = createServiceBuilder(id);
- consumerBuilder.accept(builder);
- return service(builder.build());
- }
-
- public Module service(ServiceConfig<?> serviceConfig) {
- serviceConfig.setBootstrap(this.bootstrap);
- serviceConfig.setScopeModel(moduleModel);
- configManager.addService(serviceConfig);
- return this;
- }
-
- public Module services(List<ServiceConfig> serviceConfigs) {
- if (CollectionUtils.isEmpty(serviceConfigs)) {
- return this;
- }
- serviceConfigs.forEach(configManager::addService);
- return this;
- }
-
- // {@link Reference} correlative methods
- public <S> Module reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
- return reference(null, consumerBuilder);
- }
-
- public <S> Module reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
- ReferenceBuilder builder = createReferenceBuilder(id);
- consumerBuilder.accept(builder);
- return reference(builder.build());
- }
+ public <S> Module reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
+ return reference(createReferenceConfig(id, consumerBuilder));
+ }
public Module reference(ReferenceConfig<?> referenceConfig) {
- referenceConfig.setBootstrap(this.bootstrap);
- referenceConfig.setScopeModel(moduleModel);
- configManager.addReference(referenceConfig);
+ DubboBootstrap.this.reference(referenceConfig, moduleModel);
return this;
}
@@ -1886,8 +717,9 @@ public final class DubboBootstrap {
if (CollectionUtils.isEmpty(referenceConfigs)) {
return this;
}
-
- referenceConfigs.forEach(configManager::addReference);
+ for (ReferenceConfig referenceConfig : referenceConfigs) {
+ this.reference(referenceConfig);
+ }
return this;
}
@@ -1897,13 +729,12 @@ public final class DubboBootstrap {
}
public Module provider(String id, Consumer<ProviderBuilder> builderConsumer) {
- ProviderBuilder builder = createProviderBuilder(id);
- builderConsumer.accept(builder);
- return provider(builder.build());
+ return provider(createProviderConfig(id, builderConsumer));
}
public Module provider(ProviderConfig providerConfig) {
- return providers(singletonList(providerConfig));
+ DubboBootstrap.this.provider(providerConfig, moduleModel);
+ return this;
}
public Module providers(List<ProviderConfig> providerConfigs) {
@@ -1911,8 +742,7 @@ public final class DubboBootstrap {
return this;
}
for (ProviderConfig providerConfig : providerConfigs) {
- providerConfig.setScopeModel(moduleModel);
- configManager.addProvider(providerConfig);
+ DubboBootstrap.this.provider(providerConfig, moduleModel);
}
return this;
}
@@ -1923,13 +753,12 @@ public final class DubboBootstrap {
}
public Module consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
- ConsumerBuilder builder = createConsumerBuilder(id);
- builderConsumer.accept(builder);
- return consumer(builder.build());
+ return consumer(createConsumerConfig(id, builderConsumer));
}
public Module consumer(ConsumerConfig consumerConfig) {
- return consumers(singletonList(consumerConfig));
+ DubboBootstrap.this.consumer(consumerConfig, moduleModel);
+ return this;
}
public Module consumers(List<ConsumerConfig> consumerConfigs) {
@@ -1937,10 +766,10 @@ public final class DubboBootstrap {
return this;
}
for (ConsumerConfig consumerConfig : consumerConfigs) {
- consumerConfig.setScopeModel(moduleModel);
- configManager.addConsumer(consumerConfig);
+ DubboBootstrap.this.consumer(consumerConfig, moduleModel);
}
return this;
}
}
+
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/ModuleDeployListener.java
similarity index 66%
rename from dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
rename to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/ModuleDeployListener.java
index 5a78a3f..18cc9e3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelPostProcessor.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/ModuleDeployListener.java
@@ -14,21 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.rpc.model;
+package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.rpc.model.ModuleModel;
/**
- * A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel)
+ * Module deploy listener
*/
-@SPI(scope = ExtensionScope.FRAMEWORK)
-public interface ScopeModelPostProcessor {
+@SPI(scope = ExtensionScope.MODULE)
+public interface ModuleDeployListener {
/**
- * Post-process after a scope model is created.
- * @param scopeModel
+ * Notify after module is started (export/refer services)
+ * @param moduleModel
*/
- void postProcessScopeModel(ScopeModel scopeModel);
+ void onModuleStarted(ModuleModel moduleModel);
+
+ /**
+ * Notify after module is stopped
+ * @param moduleModel
+ */
+ void onModuleStopped(ModuleModel moduleModel);
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
index 6c796ad..a1d30b3 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
@@ -26,7 +26,6 @@ import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.MetadataServiceExporter;
@@ -83,7 +82,6 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
ApplicationConfig applicationConfig = getApplicationConfig();
ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
serviceConfig.setScopeModel(applicationModel.getInternalModule());
- serviceConfig.setBootstrap(applicationModel.getBeanFactory().getBean(DubboBootstrap.class));
serviceConfig.setApplication(applicationConfig);
serviceConfig.setRegistry(new RegistryConfig("N/A"));
serviceConfig.setProtocol(generateMetadataProtocol());
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/CompositeReferenceCache.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/CompositeReferenceCache.java
new file mode 100644
index 0000000..827dca2
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/CompositeReferenceCache.java
@@ -0,0 +1,109 @@
+/*
+ * 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.common.config.ReferenceCache;
+import org.apache.dubbo.config.ReferenceConfigBase;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A impl of ReferenceCache for Application
+ */
+public class CompositeReferenceCache implements ReferenceCache {
+ private ApplicationModel applicationModel;
+
+ public CompositeReferenceCache(ApplicationModel applicationModel) {
+ this.applicationModel = applicationModel;
+ }
+
+ @Override
+ public <T> T get(ReferenceConfigBase<T> referenceConfig) {
+ return referenceConfig.get();
+ }
+
+ @Override
+ public <T> T get(String key, Class<T> type) {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ T proxy = moduleModel.getDeployer().getReferenceCache().get(key, type);
+ if (proxy != null) {
+ return proxy;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public <T> T get(String key) {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ T proxy = moduleModel.getDeployer().getReferenceCache().get(key);
+ if (proxy != null) {
+ return proxy;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public <T> List<T> getAll(Class<T> type) {
+ List<T> proxies = new ArrayList<>();
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ proxies.addAll(moduleModel.getDeployer().getReferenceCache().getAll(type));
+ }
+ return proxies;
+ }
+
+ @Override
+ public <T> T get(Class<T> type) {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ T proxy = moduleModel.getDeployer().getReferenceCache().get(type);
+ if (proxy != null) {
+ return proxy;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void destroy(String key, Class<?> type) {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ moduleModel.getDeployer().getReferenceCache().destroy(key, type);
+ }
+ }
+
+ @Override
+ public void destroy(Class<?> type) {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ moduleModel.getDeployer().getReferenceCache().destroy(type);
+ }
+ }
+
+ @Override
+ public <T> void destroy(ReferenceConfigBase<T> referenceConfig) {
+ referenceConfig.getScopeModel().getDeployer().getReferenceCache().destroy(referenceConfig);
+ }
+
+ @Override
+ public void destroyAll() {
+ for (ModuleModel moduleModel : applicationModel.getModuleModels()) {
+ moduleModel.getDeployer().getReferenceCache().destroyAll();
+ }
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.java
new file mode 100644
index 0000000..69fdafa
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.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.utils;
+
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.MetricsConfig;
+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.SslConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+
+public class DefaultConfigValidator implements ConfigValidator {
+
+ @Override
+ public void validate(AbstractConfig config) {
+ if (config instanceof ProtocolConfig) {
+ ConfigValidationUtils.validateProtocolConfig((ProtocolConfig) config);
+ } else if (config instanceof RegistryConfig) {
+ ConfigValidationUtils.validateRegistryConfig((RegistryConfig) config);
+ } else if (config instanceof MetadataReportConfig) {
+ ConfigValidationUtils.validateMetadataConfig((MetadataReportConfig) config);
+ } else if (config instanceof ProviderConfig) {
+ ConfigValidationUtils.validateProviderConfig((ProviderConfig) config);
+ } else if (config instanceof ConsumerConfig) {
+ ConfigValidationUtils.validateConsumerConfig((ConsumerConfig) config);
+ } else if (config instanceof ApplicationConfig) {
+ ConfigValidationUtils.validateApplicationConfig((ApplicationConfig) config);
+ } else if (config instanceof MonitorConfig) {
+ ConfigValidationUtils.validateMonitorConfig((MonitorConfig) config);
+ } else if (config instanceof ModuleConfig) {
+ ConfigValidationUtils.validateModuleConfig((ModuleConfig) config);
+ } else if (config instanceof MetricsConfig) {
+ ConfigValidationUtils.validateMetricsConfig((MetricsConfig) config);
+ } else if (config instanceof SslConfig) {
+ ConfigValidationUtils.validateSslConfig((SslConfig) config);
+ }
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SimpleReferenceCache.java
similarity index 55%
rename from dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
rename to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SimpleReferenceCache.java
index f95e00f..c35a708 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ReferenceConfigCache.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/SimpleReferenceCache.java
@@ -16,10 +16,10 @@
*/
package org.apache.dubbo.config.utils;
+import org.apache.dubbo.common.config.ReferenceCache;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ReferenceConfigBase;
-import org.apache.dubbo.rpc.model.ScopeModelUtil;
import org.apache.dubbo.rpc.service.Destroyable;
import java.util.ArrayList;
@@ -38,7 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger;
* <p>
* You can implement and use your own {@link ReferenceConfigBase} cache if you need use complicate strategy.
*/
-public class ReferenceConfigCache {
+public class SimpleReferenceCache implements ReferenceCache {
public static final String DEFAULT_NAME = "_DEFAULT_";
/**
* Create the key with the <b>Group</b>, <b>Interface</b> and <b>version</b> attribute of {@link ReferenceConfigBase}.
@@ -68,15 +68,15 @@ public class ReferenceConfigCache {
private static final AtomicInteger nameIndex = new AtomicInteger();
- static final ConcurrentMap<String, ReferenceConfigCache> CACHE_HOLDER = new ConcurrentHashMap<String, ReferenceConfigCache>();
+ static final ConcurrentMap<String, SimpleReferenceCache> CACHE_HOLDER = new ConcurrentHashMap<>();
private final String name;
private final KeyGenerator generator;
- private final ConcurrentMap<String, ReferenceConfigBase<?>> referredReferences = new ConcurrentHashMap<>();
+ private final Map<String, List<ReferenceConfigBase<?>>> referenceKeyMap = new ConcurrentHashMap<>();
+ private final Map<Class<?>, List<ReferenceConfigBase<?>>> referenceTypeMap = new ConcurrentHashMap<>();
+ private final Map<ReferenceConfigBase<?>, Object> references = new ConcurrentHashMap<>();
- private final ConcurrentMap<Class<?>, ConcurrentMap<String, Object>> proxies = new ConcurrentHashMap<>();
-
- private ReferenceConfigCache(String name, KeyGenerator generator) {
+ protected SimpleReferenceCache(String name, KeyGenerator generator) {
this.name = name;
this.generator = generator;
}
@@ -85,11 +85,11 @@ public class ReferenceConfigCache {
* Get the cache use default name and {@link #DEFAULT_KEY_GENERATOR} to generate cache key.
* Create cache if not existed yet.
*/
- public static ReferenceConfigCache getCache() {
+ public static SimpleReferenceCache getCache() {
return getCache(DEFAULT_NAME);
}
- public static ReferenceConfigCache newCache() {
+ public static SimpleReferenceCache newCache() {
return getCache(DEFAULT_NAME + "#" + nameIndex.incrementAndGet());
}
@@ -97,7 +97,7 @@ public class ReferenceConfigCache {
* Get the cache use specified name and {@link KeyGenerator}.
* Create cache if not existed yet.
*/
- public static ReferenceConfigCache getCache(String name) {
+ public static SimpleReferenceCache getCache(String name) {
return getCache(name, DEFAULT_KEY_GENERATOR);
}
@@ -105,22 +105,26 @@ public class ReferenceConfigCache {
* Get the cache use specified {@link KeyGenerator}.
* Create cache if not existed yet.
*/
- public static ReferenceConfigCache getCache(String name, KeyGenerator keyGenerator) {
- return CACHE_HOLDER.computeIfAbsent(name, k -> new ReferenceConfigCache(k, keyGenerator));
+ public static SimpleReferenceCache getCache(String name, KeyGenerator keyGenerator) {
+ return CACHE_HOLDER.computeIfAbsent(name, k -> new SimpleReferenceCache(k, keyGenerator));
}
+ @Override
@SuppressWarnings("unchecked")
- public <T> T get(ReferenceConfigBase<T> referenceConfig) {
- String key = generator.generateKey(referenceConfig);
- Class<?> type = referenceConfig.getInterfaceClass();
-
- ConcurrentMap<String, Object> proxiesOfType = proxies.computeIfAbsent(type, _t -> new ConcurrentHashMap<>());
-
- return (T) proxiesOfType.computeIfAbsent(key, _k -> {
- Object proxy = referenceConfig.get();
- referredReferences.put(key, referenceConfig);
+ public <T> T get(ReferenceConfigBase<T> rc) {
+ String key = generator.generateKey(rc);
+ Class<?> type = rc.getInterfaceClass();
+ Object proxy = rc.get();
+
+ references.computeIfAbsent(rc, _rc -> {
+ List<ReferenceConfigBase<?>> referencesOfType = referenceTypeMap.computeIfAbsent(type, _t -> Collections.synchronizedList(new ArrayList<>()));
+ referencesOfType.add(rc);
+ List<ReferenceConfigBase<?>> referenceConfigList = referenceKeyMap.computeIfAbsent(key, _k -> Collections.synchronizedList(new ArrayList<>()));
+ referenceConfigList.add(rc);
return proxy;
});
+
+ return (T) proxy;
}
/**
@@ -133,71 +137,75 @@ public class ReferenceConfigCache {
* @return object from the cached ReferenceConfigBase
* @see KeyGenerator#generateKey(ReferenceConfigBase)
*/
+ @Override
@SuppressWarnings("unchecked")
public <T> T get(String key, Class<T> type) {
- Map<String, Object> proxiesOfType = proxies.get(type);
- if (CollectionUtils.isEmptyMap(proxiesOfType)) {
- return null;
+ List<ReferenceConfigBase<?>> referenceConfigs = referenceKeyMap.get(key);
+ if (referenceConfigs != null && referenceConfigs.size() > 0) {
+ return (T) referenceConfigs.get(0).get();
}
- return (T) proxiesOfType.get(key);
+ return null;
}
+ @Override
@SuppressWarnings("unchecked")
public <T> T get(String key) {
- ReferenceConfigBase<?> rc = referredReferences.get(key);
- if (rc == null) {
- return null;
+ List<ReferenceConfigBase<?>> referenceConfigs = referenceKeyMap.get(key);
+ if (referenceConfigs != null && referenceConfigs.size() > 0) {
+ return (T) referenceConfigs.get(0).get();
}
-
- return (T) get(key, rc.getInterfaceClass());
+ return null;
}
+ @Override
@SuppressWarnings("unchecked")
public <T> List<T> getAll(Class<T> type) {
- Map<String, Object> proxiesOfType = proxies.get(type);
- if (CollectionUtils.isEmptyMap(proxiesOfType)) {
- return Collections.emptyList();
+ List<ReferenceConfigBase<?>> referenceConfigBases = referenceTypeMap.get(type);
+ if (CollectionUtils.isEmpty(referenceConfigBases)) {
+ return Collections.EMPTY_LIST;
}
-
- List<T> proxySet = new ArrayList<>();
- proxiesOfType.values().forEach(obj -> proxySet.add((T) obj));
- return proxySet;
+ List proxiesOfType = new ArrayList(referenceConfigBases.size());
+ for (ReferenceConfigBase<?> rc : referenceConfigBases) {
+ proxiesOfType.add(rc.get());
+ }
+ return Collections.unmodifiableList(proxiesOfType);
}
+ @Override
@SuppressWarnings("unchecked")
public <T> T get(Class<T> type) {
- Map<String, Object> proxiesOfType = proxies.get(type);
- if (CollectionUtils.isEmptyMap(proxiesOfType)) {
- return null;
+ List<ReferenceConfigBase<?>> referenceConfigBases = referenceTypeMap.get(type);
+ if (referenceConfigBases != null && referenceConfigBases.size() > 0) {
+ return (T) referenceConfigBases.get(0).get();
}
-
- return (T) proxiesOfType.values().iterator().next();
+ return null;
}
+ @Override
public void destroy(String key, Class<?> type) {
- ReferenceConfigBase<?> rc = referredReferences.remove(key);
- if (rc == null) {
+ List<ReferenceConfigBase<?>> referencesOfKey = referenceKeyMap.remove(key);
+ if (CollectionUtils.isEmpty(referencesOfKey)) {
return;
}
-
- ScopeModelUtil.getApplicationModel(rc.getScopeModel()).getApplicationConfigManager().removeConfig(rc);
- rc.destroy();
-
- Map<String, Object> proxiesOftype = proxies.get(type);
- if (CollectionUtils.isNotEmptyMap(proxiesOftype)) {
- proxiesOftype.remove(key);
- if (proxiesOftype.isEmpty()) {
- proxies.remove(type);
- }
+ List<ReferenceConfigBase<?>> referencesOfType = referenceTypeMap.get(type);
+ if (CollectionUtils.isEmpty(referencesOfType)) {
+ return;
}
+ for (ReferenceConfigBase<?> rc : referencesOfKey) {
+ referencesOfType.remove(rc);
+ destroyReference(rc);
+ }
+
}
+ @Override
public void destroy(Class<?> type) {
- Map<String, Object> proxiesOfType = proxies.remove(type);
- proxiesOfType.forEach((k, v) -> {
- ReferenceConfigBase rc = referredReferences.remove(k);
- rc.destroy();
- });
+ List<ReferenceConfigBase<?>> referencesOfType = referenceTypeMap.remove(type);
+ for (ReferenceConfigBase<?> rc : referencesOfType) {
+ String key = generator.generateKey(rc);
+ referenceKeyMap.remove(key);
+ destroyReference(rc);
+ }
}
/**
@@ -205,49 +213,49 @@ public class ReferenceConfigCache {
*
* @param referenceConfig use for create key.
*/
+ @Override
public <T> void destroy(ReferenceConfigBase<T> referenceConfig) {
String key = generator.generateKey(referenceConfig);
Class<?> type = referenceConfig.getInterfaceClass();
-
destroy(key, type);
}
/**
* clear and destroy all {@link ReferenceConfigBase} in the cache.
*/
+ @Override
public void destroyAll() {
- if (CollectionUtils.isEmptyMap(referredReferences)) {
+ if (CollectionUtils.isEmptyMap(referenceKeyMap)) {
return;
}
- referredReferences.forEach((_k, referenceConfig) -> {
- referenceConfig.destroy();
- ScopeModelUtil.getApplicationModel(referenceConfig.getScopeModel()).getApplicationConfigManager().removeConfig(referenceConfig);
+ referenceKeyMap.forEach((_k, referencesOfKey) -> {
+ for (ReferenceConfigBase<?> rc : referencesOfKey) {
+ destroyReference(rc);
+ }
});
- proxies.forEach((_type, proxiesOfType) -> {
- proxiesOfType.forEach((_k, v) -> {
- Destroyable proxy = (Destroyable) v;
- proxy.$destroy();
- });
- });
+ referenceKeyMap.clear();
+ referenceTypeMap.clear();
+ }
- referredReferences.clear();
- proxies.clear();
+ private void destroyReference(ReferenceConfigBase<?> rc) {
+ Destroyable proxy = (Destroyable) rc.get();
+ proxy.$destroy();
+ rc.destroy();
}
- public ConcurrentMap<String, ReferenceConfigBase<?>> getReferredReferences() {
- return referredReferences;
+ public Map<String, List<ReferenceConfigBase<?>>> getReferenceMap() {
+ return referenceKeyMap;
}
- public ConcurrentMap<Class<?>, ConcurrentMap<String, Object>> getProxies() {
- return proxies;
+ public Map<Class<?>, List<ReferenceConfigBase<?>>> getReferenceTypeMap() {
+ return referenceTypeMap;
}
@Override
public String toString() {
- return "ReferenceConfigCache(name: " + name
- + ")";
+ return "ReferenceCache(name: " + name + ")";
}
public interface KeyGenerator {
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer
new file mode 100644
index 0000000..3122307
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer
@@ -0,0 +1 @@
+dubbo-config-api=org.apache.dubbo.config.ConfigScopeModelInitializer
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index 7f03914..4cb8d97 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -22,7 +22,6 @@ import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
index 92a7282..d563351 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigCenterConfigTest.java
@@ -21,7 +21,6 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
index 2e06f0d..3e68025 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConsumerConfigTest.java
@@ -20,7 +20,6 @@ package org.apache.dubbo.config;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -117,7 +116,7 @@ public class ConsumerConfigTest {
.consumer(consumerConfig)
.initialize();
- Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
+ Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getDefaultModule().getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
@@ -147,7 +146,7 @@ public class ConsumerConfigTest {
.consumer(consumerConfig)
.initialize();
- Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
+ Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getDefaultModule().getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
@@ -180,7 +179,7 @@ public class ConsumerConfigTest {
.consumer(consumerConfig)
.initialize();
- Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
+ Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getDefaultModule().getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(true, consumerConfig.isCheck());
@@ -209,7 +208,7 @@ public class ConsumerConfigTest {
.consumer(consumerConfig)
.initialize();
- Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getApplicationConfigManager().getConsumers();
+ Collection<ConsumerConfig> consumers = ApplicationModel.defaultModel().getDefaultModule().getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index 576b396..f75aa8a 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -16,6 +16,13 @@
*/
package org.apache.dubbo.config;
+import demo.MultiClassLoaderService;
+import demo.MultiClassLoaderServiceImpl;
+import demo.MultiClassLoaderServiceRequest;
+import demo.MultiClassLoaderServiceResult;
+import javassist.CannotCompileException;
+import javassist.CtClass;
+import javassist.NotFoundException;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.compiler.support.CtClassBuilder;
@@ -29,6 +36,7 @@ import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.registry.client.migration.MigrationInvoker;
import org.apache.dubbo.registrycenter.RegistryCenter;
@@ -43,14 +51,6 @@ import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.protocol.injvm.InjvmInvoker;
import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
-
-import demo.MultiClassLoaderService;
-import demo.MultiClassLoaderServiceImpl;
-import demo.MultiClassLoaderServiceRequest;
-import demo.MultiClassLoaderServiceResult;
-import javassist.CannotCompileException;
-import javassist.CtClass;
-import javassist.NotFoundException;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -62,6 +62,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Constructor;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
@@ -69,7 +70,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
@@ -774,6 +774,8 @@ public class ReferenceConfigTest {
@Test
public void testLargeReferences() throws InterruptedException {
int amount = 10000;
+ ModuleConfigManager configManager = DubboBootstrap.getInstance().getApplicationModel().getDefaultModule().getConfigManager();
+
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("test-app");
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
@@ -782,9 +784,9 @@ public class ReferenceConfigTest {
configCenterConfig.setAddress("diamond://");
testInitReferences(0, amount, applicationConfig, metadataReportConfig, configCenterConfig);
- ApplicationModel.defaultModel().getApplicationConfigManager().clear();
+ configManager.clear();
testInitReferences(0, 1, applicationConfig, metadataReportConfig, configCenterConfig);
- ApplicationModel.defaultModel().getApplicationConfigManager().clear();
+ configManager.clear();
long t1 = System.currentTimeMillis();
int nThreads = 8;
@@ -808,7 +810,7 @@ public class ReferenceConfigTest {
long t2 = System.currentTimeMillis();
long cost = t2 - t1;
System.out.println("Init large references cost: " + cost + "ms");
- Assertions.assertEquals(amount, DubboBootstrap.getInstance().getConfigManager().getReferences().size());
+ Assertions.assertEquals(amount, configManager.getReferences().size());
Assertions.assertTrue(cost < 1000, "Init large references too slowly: " + cost);
//test equals
@@ -818,7 +820,7 @@ public class ReferenceConfigTest {
private void testSearchReferences() {
long t1 = System.currentTimeMillis();
- Collection<ReferenceConfigBase<?>> references = DubboBootstrap.getInstance().getConfigManager().getReferences();
+ Collection<ReferenceConfigBase<?>> references = DubboBootstrap.getInstance().getApplicationModel().getDefaultModule().getConfigManager().getReferences();
List<ReferenceConfigBase<?>> results = references.stream().filter(rc -> rc.equals(references.iterator().next()))
.collect(Collectors.toList());
long t2 = System.currentTimeMillis();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
index a96e0f5..6fa0d00 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapMultiInstanceTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config.bootstrap;
+import org.apache.dubbo.common.deploy.ModuleDeployer;
import org.apache.dubbo.common.utils.NetUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ProtocolConfig;
@@ -24,11 +25,14 @@ import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.SysProps;
import org.apache.dubbo.config.api.DemoService;
+import org.apache.dubbo.config.api.Greeting;
+import org.apache.dubbo.config.mock.GreetingLocal2;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.registrycenter.RegistryCenter;
import org.apache.dubbo.registrycenter.ZookeeperSingleRegistryCenter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.FrameworkServiceRepository;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
@@ -70,8 +74,8 @@ public class DubboBootstrapMultiInstanceTest {
@Test
public void testIsolatedApplications() {
- DubboBootstrap dubboBootstrap1 = DubboBootstrap.newInstance();
- DubboBootstrap dubboBootstrap2 = DubboBootstrap.newInstance();
+ DubboBootstrap dubboBootstrap1 = DubboBootstrap.newInstance(new FrameworkModel());
+ DubboBootstrap dubboBootstrap2 = DubboBootstrap.newInstance(new FrameworkModel());
try {
ApplicationModel applicationModel1 = dubboBootstrap1.getApplicationModel();
ApplicationModel applicationModel2 = dubboBootstrap2.getApplicationModel();
@@ -160,6 +164,7 @@ public class DubboBootstrapMultiInstanceTest {
String version1 = "1.0";
String version2 = "2.0";
+ String version3 = "3.0";
DubboBootstrap providerBootstrap = null;
DubboBootstrap consumerBootstrap = null;
@@ -178,23 +183,31 @@ public class DubboBootstrapMultiInstanceTest {
serviceConfig2.setRef(new DemoServiceImpl());
serviceConfig2.setVersion(version2);
+ ServiceConfig serviceConfig3 = new ServiceConfig();
+ serviceConfig3.setInterface(DemoService.class);
+ serviceConfig3.setRef(new DemoServiceImpl());
+ serviceConfig3.setVersion(version3);
+
providerBootstrap
.application("provider-app")
.registry(registryConfig)
- .protocol(new ProtocolConfig("dubbo", 2002))
- .addModule()
+ .protocol(new ProtocolConfig("dubbo", -1))
.service(serviceConfig1)
- .endModule()
- .addModule()
+ .newModule()
.service(serviceConfig2)
+ .endModule()
+ .newModule()
+ .service(serviceConfig3)
.endModule();
ApplicationModel applicationModel = providerBootstrap.getApplicationModel();
List<ModuleModel> moduleModels = applicationModel.getModuleModels();
- Assertions.assertEquals(3, moduleModels.size());
+ Assertions.assertEquals(4, moduleModels.size());
Assertions.assertSame(moduleModels.get(0), applicationModel.getInternalModule());
- Assertions.assertSame(moduleModels.get(1), serviceConfig1.getScopeModel());
+ Assertions.assertSame(moduleModels.get(1), applicationModel.getDefaultModule());
+ Assertions.assertSame(applicationModel.getDefaultModule(), serviceConfig1.getScopeModel());
Assertions.assertSame(moduleModels.get(2), serviceConfig2.getScopeModel());
+ Assertions.assertSame(moduleModels.get(3), serviceConfig3.getScopeModel());
Assertions.assertNotSame(applicationModel.getDefaultModule(), applicationModel.getInternalModule());
providerBootstrap.start();
@@ -208,7 +221,7 @@ public class DubboBootstrapMultiInstanceTest {
.interfaceClass(DemoService.class)
.version(version1)
.injvm(false))
- .addModule()
+ .newModule()
.reference(builder -> builder
.interfaceClass(DemoService.class)
.version(version2)
@@ -232,6 +245,149 @@ public class DubboBootstrapMultiInstanceTest {
}
+ @Test
+ public void testMultiModuleDeployAndReload() throws Exception {
+
+ String version1 = "1.0";
+ String version2 = "2.0";
+ String version3 = "3.0";
+
+ String serviceKey1 = DemoService.class.getName() + ":" + version1;
+ String serviceKey2 = DemoService.class.getName() + ":" + version2;
+ String serviceKey3 = DemoService.class.getName() + ":" + version3;
+
+ DubboBootstrap providerBootstrap = null;
+ DubboBootstrap consumerBootstrap = null;
+
+ try {
+ // provider app
+ providerBootstrap = DubboBootstrap.newInstance();
+
+ ServiceConfig serviceConfig1 = new ServiceConfig();
+ serviceConfig1.setInterface(DemoService.class);
+ serviceConfig1.setRef(new DemoServiceImpl());
+ serviceConfig1.setVersion(version1);
+
+ //provider module 1
+ providerBootstrap
+ .application("provider-app")
+ .registry(registryConfig)
+ .protocol(new ProtocolConfig("dubbo", -1))
+ .service(builder -> builder
+ .interfaceClass(Greeting.class)
+ .ref(new GreetingLocal2()))
+ .newModule()
+ .service(serviceConfig1)
+ .endModule();
+
+ ApplicationModel applicationModel = providerBootstrap.getApplicationModel();
+ List<ModuleModel> moduleModels = applicationModel.getModuleModels();
+ Assertions.assertEquals(3, moduleModels.size());
+ Assertions.assertSame(moduleModels.get(0), applicationModel.getInternalModule());
+ Assertions.assertSame(moduleModels.get(1), applicationModel.getDefaultModule());
+ Assertions.assertSame(moduleModels.get(2), serviceConfig1.getScopeModel());
+
+ ModuleDeployer moduleDeployer1 = serviceConfig1.getScopeModel().getDeployer();
+ moduleDeployer1.start().get();
+ Assertions.assertTrue(moduleDeployer1.isStartup());
+ ModuleDeployer internalModuleDeployer = applicationModel.getInternalModule().getDeployer();
+ Assertions.assertTrue(internalModuleDeployer.isStartup());
+
+ FrameworkServiceRepository frameworkServiceRepository = applicationModel.getFrameworkModel().getServiceRepository();
+ Assertions.assertNotNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey1));
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey2));
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey3));
+
+ // consumer module 1
+ consumerBootstrap = DubboBootstrap.newInstance();
+ consumerBootstrap.application("consumer-app")
+ .registry(registryConfig)
+ .reference(builder -> builder
+ .interfaceClass(DemoService.class)
+ .version(version1)
+ .injvm(false));
+ consumerBootstrap.start();
+
+ DemoService referProxy1 = consumerBootstrap.getCache().get(serviceKey1);
+ String result1 = referProxy1.sayName("dubbo");
+ Assertions.assertEquals("say:dubbo", result1);
+
+ // destroy provider module 1
+ serviceConfig1.getScopeModel().destroy();
+
+ // provider module 2
+ ServiceConfig serviceConfig2 = new ServiceConfig();
+ serviceConfig2.setInterface(DemoService.class);
+ serviceConfig2.setRef(new DemoServiceImpl());
+ serviceConfig2.setVersion(version2);
+
+ providerBootstrap.newModule()
+ .service(serviceConfig2)
+ .endModule();
+
+ serviceConfig2.getScopeModel().getDeployer().start();
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey1));
+ Assertions.assertNotNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey2));
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey3));
+
+ // consumer module2
+ ModuleModel consumerModule2 = consumerBootstrap.newModule()
+ .reference(builder -> builder
+ .interfaceClass(DemoService.class)
+ .version(version2)
+ .injvm(false))
+ .getModuleModel();
+
+ ModuleDeployer moduleDeployer2 = consumerModule2.getDeployer();
+ moduleDeployer2.start().get();
+
+ DemoService referProxy2 = moduleDeployer2.getReferenceCache().get(serviceKey2);
+ String result2 = referProxy2.sayName("dubbo2");
+ Assertions.assertEquals("say:dubbo2", result2);
+
+ // destroy provider module 2
+ serviceConfig2.getScopeModel().destroy();
+
+ // provider module 3
+ ServiceConfig serviceConfig3 = new ServiceConfig();
+ serviceConfig3.setInterface(DemoService.class);
+ serviceConfig3.setRef(new DemoServiceImpl());
+ serviceConfig3.setVersion(version3);
+
+ providerBootstrap.newModule()
+ .service(serviceConfig3)
+ .endModule();
+
+ serviceConfig3.getScopeModel().getDeployer().start().get();
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey1));
+ Assertions.assertNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey2));
+ Assertions.assertNotNull(frameworkServiceRepository.lookupExportedServiceWithoutGroup(serviceKey3));
+
+ // consumer module3
+ ModuleModel consumerModule3 = consumerBootstrap.newModule()
+ .reference(builder -> builder
+ .interfaceClass(DemoService.class)
+ .version(version3)
+ .injvm(false))
+ .getModuleModel();
+
+ consumerBootstrap.start();
+
+ DemoService referProxy3 = consumerModule3.getDeployer().getReferenceCache().get(serviceKey3);
+ String result3 = referProxy3.sayName("dubbo3");
+ Assertions.assertEquals("say:dubbo3", result3);
+
+ } finally {
+ if (providerBootstrap != null) {
+ providerBootstrap.destroy();
+ }
+ if (consumerBootstrap != null) {
+ consumerBootstrap.destroy();
+ }
+ }
+ }
+
+
private DubboBootstrap configConsumerApp(DubboBootstrap dubboBootstrap) {
ReferenceConfig<DemoService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(DemoService.class);
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
index 0abaa22..b1c1b03 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config.bootstrap;
+import org.apache.curator.test.TestingServer;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
@@ -39,8 +40,6 @@ import org.apache.dubbo.registry.RegistryService;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
-
-import org.apache.curator.test.TestingServer;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -153,7 +152,7 @@ public class DubboBootstrapTest {
// load configs from props
DubboBootstrap.getInstance()
- .initialize();
+ .initialize();
serviceConfig.refresh();
@@ -258,9 +257,15 @@ public class DubboBootstrapTest {
Assertions.assertTrue(bootstrap.isStarted());
Assertions.assertFalse(bootstrap.isShutdown());
- Assertions.assertNotNull(bootstrap.serviceInstance);
- Assertions.assertTrue(bootstrap.exportedServices.size() > 0);
- Assertions.assertNotNull(bootstrap.asyncMetadataFuture);
+ ApplicationModel applicationModel = bootstrap.getApplicationModel();
+ DefaultApplicationDeployer applicationDeployer = getApplicationDeployer(applicationModel);
+ Assertions.assertNotNull(applicationDeployer.serviceInstance);
+ Assertions.assertNotNull(applicationDeployer.asyncMetadataFuture);
+ Assertions.assertTrue(applicationModel.getDefaultModule().getServiceRepository().getExportedServices().size() > 0);
+ }
+
+ private DefaultApplicationDeployer getApplicationDeployer(ApplicationModel applicationModel) {
+ return (DefaultApplicationDeployer) DefaultApplicationDeployer.get(applicationModel);
}
@Test
@@ -327,7 +332,8 @@ public class DubboBootstrapTest {
}
private void assertMetadataService(DubboBootstrap bootstrap, int availablePort, boolean shouldReport) {
- Assertions.assertTrue(bootstrap.metadataServiceExporter.isExported());
+ DefaultApplicationDeployer applicationDeployer = getApplicationDeployer(bootstrap.getApplicationModel());
+ Assertions.assertTrue(applicationDeployer.metadataServiceExporter.isExported());
DubboProtocol protocol = DubboProtocol.getDubboProtocol(bootstrap.getApplicationModel());
Map<String, Exporter<?>> exporters = protocol.getExporterMap();
Assertions.assertEquals(2, exporters.size());
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
index 1dab33e..17da2f4 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ServiceInstanceHostPortCustomizerTest.java
@@ -23,7 +23,6 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance;
import org.apache.dubbo.registry.client.ServiceInstance;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
-
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java
index 464356f..f6d0967 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/MockReferenceConfig.java
@@ -54,6 +54,7 @@ public class MockReferenceConfig extends ReferenceConfig<FooService> {
@Override
public synchronized void destroy() {
+ super.destroy();
destroyMethodRun = true;
}
}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceCacheTest.java
similarity index 84%
rename from dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceCacheTest.java
index 6797e60..2a74228 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceConfigCacheTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ReferenceCacheTest.java
@@ -16,30 +16,29 @@
*/
package org.apache.dubbo.config.utils;
+import org.apache.dubbo.common.config.ReferenceCache;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.utils.service.FooService;
-
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
-public class ReferenceConfigCacheTest {
+public class ReferenceCacheTest {
@BeforeEach
public void setUp() throws Exception {
DubboBootstrap.reset();
MockReferenceConfig.setCounter(0);
- ReferenceConfigCache.CACHE_HOLDER.clear();
+ SimpleReferenceCache.CACHE_HOLDER.clear();
}
@Test
public void testGetCacheSameReference() throws Exception {
- ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+ ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
assertEquals(0L, config.getCounter());
cache.get(config);
@@ -48,15 +47,15 @@ public class ReferenceConfigCacheTest {
MockReferenceConfig configCopy = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
assertEquals(1L, configCopy.getCounter());
cache.get(configCopy);
- assertFalse(configCopy.isGetMethodRun());
+ assertTrue(configCopy.isGetMethodRun());
- assertEquals(1L, config.getCounter());
- assertEquals(1L, configCopy.getCounter());
+ assertEquals(2L, config.getCounter());
+ assertEquals(2L, configCopy.getCounter());
}
@Test
public void testGetCacheDiffReference() throws Exception {
- ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+ ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
assertEquals(0L, config.getCounter());
cache.get(config);
@@ -74,7 +73,7 @@ public class ReferenceConfigCacheTest {
@Test
public void testGetCacheWithKey() throws Exception {
- ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+ ReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
FooService value = cache.get(config);
assertEquals(value, cache.get("group1/org.apache.dubbo.config.utils.service.FooService:1.0.0", FooService.class));
@@ -82,14 +81,14 @@ public class ReferenceConfigCacheTest {
// @Test
// public void testGetCacheDiffName() throws Exception {
-// ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+// ReferenceCache cache = ReferenceCache.getCache();
// MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
// assertEquals(0L, config.getCounter());
// cache.get(config);
// assertTrue(config.isGetMethodRun());
// assertEquals(1L, config.getCounter());
//
-// cache = ReferenceConfigCache.getCache("foo");
+// cache = ReferenceCache.getCache("foo");
// config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
// assertEquals(1L, config.getCounter());
// cache.get(config);
@@ -100,32 +99,32 @@ public class ReferenceConfigCacheTest {
@Test
public void testDestroy() throws Exception {
- ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+ SimpleReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
cache.get(config);
XxxMockReferenceConfig configCopy = buildXxxMockReferenceConfig("org.apache.dubbo.config.utils.service.XxxService", "group1", "1.0.0");
cache.get(configCopy);
- assertEquals(2, cache.getReferredReferences().size());
+ assertEquals(2, cache.getReferenceMap().size());
cache.destroy(config);
assertTrue(config.isDestroyMethodRun());
- assertEquals(1, cache.getReferredReferences().size());
+ assertEquals(1, cache.getReferenceMap().size());
cache.destroy(configCopy);
assertTrue(configCopy.isDestroyMethodRun());
- assertEquals(0, cache.getReferredReferences().size());
+ assertEquals(0, cache.getReferenceMap().size());
}
@Test
public void testDestroyAll() throws Exception {
- ReferenceConfigCache cache = ReferenceConfigCache.getCache();
+ SimpleReferenceCache cache = SimpleReferenceCache.getCache();
MockReferenceConfig config = buildMockReferenceConfig("org.apache.dubbo.config.utils.service.FooService", "group1", "1.0.0");
cache.get(config);
XxxMockReferenceConfig configCopy = buildXxxMockReferenceConfig("org.apache.dubbo.config.utils.service.XxxService", "group1", "1.0.0");
cache.get(configCopy);
- assertEquals(2, cache.getReferredReferences().size());
+ assertEquals(2, cache.getReferenceMap().size());
cache.destroyAll();
assertTrue(config.isDestroyMethodRun());
assertTrue(configCopy.isDestroyMethodRun());
- assertEquals(0, cache.getReferredReferences().size());
+ assertEquals(0, cache.getReferenceMap().size());
}
private MockReferenceConfig buildMockReferenceConfig(String service, String group, String version) {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/XxxMockReferenceConfig.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/XxxMockReferenceConfig.java
index 56667b6..fbddd6d 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/XxxMockReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/XxxMockReferenceConfig.java
@@ -54,6 +54,7 @@ public class XxxMockReferenceConfig extends ReferenceConfig<XxxService> {
@Override
public synchronized void destroy() {
+ super.destroy();
destroyMethodRun = true;
}
}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
index 322d6da..7b80c23 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/exportprovider/MultipleRegistryCenterExportProviderIntegrationTest.java
@@ -35,7 +35,6 @@ import org.apache.dubbo.registrycenter.ZookeeperMultipleRegistryCenter;
import org.apache.dubbo.rpc.ExporterListener;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -173,7 +172,6 @@ public class MultipleRegistryCenterExportProviderIntegrationTest implements Inte
afterExport();
ReferenceConfig<MultipleRegistryCenterExportProviderService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(MultipleRegistryCenterExportProviderService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
referenceConfig.get().hello(PROVIDER_APPLICATION_NAME);
afterInvoke();
}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/injvm/MultipleRegistryCenterInjvmIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/injvm/MultipleRegistryCenterInjvmIntegrationTest.java
index b67c65b..0c7cf66 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/injvm/MultipleRegistryCenterInjvmIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/injvm/MultipleRegistryCenterInjvmIntegrationTest.java
@@ -17,12 +17,12 @@
package org.apache.dubbo.integration.multiple.injvm;
import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ReferenceConfig;
-import org.apache.dubbo.config.ServiceListener;
import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.ServiceListener;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.integration.IntegrationTest;
import org.apache.dubbo.registrycenter.RegistryCenter;
@@ -145,7 +145,6 @@ public class MultipleRegistryCenterInjvmIntegrationTest implements IntegrationTe
afterExport();
ReferenceConfig<MultipleRegistryCenterInjvmService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(MultipleRegistryCenterInjvmService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
referenceConfig.setScope(SCOPE_LOCAL);
referenceConfig.get().hello("Dubbo in multiple registry center");
afterInvoke();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest.java
index acb4aa0..fed2bae 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/multiple/servicediscoveryregistry/MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest.java
@@ -18,11 +18,11 @@ package org.apache.dubbo.integration.multiple.servicediscoveryregistry;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.integration.IntegrationTest;
import org.apache.dubbo.registry.RegistryServiceListener;
@@ -156,7 +156,6 @@ public class MultipleRegistryCenterServiceDiscoveryRegistryIntegrationTest imple
afterExport();
ReferenceConfig<MultipleRegistryCenterServiceDiscoveryRegistryService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(MultipleRegistryCenterServiceDiscoveryRegistryService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
referenceConfig.get().hello("Dubbo in multiple registry center");
afterInvoke();
}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
index cfb9df8..3516bbc 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/SingleRegistryCenterDubboProtocolIntegrationTest.java
@@ -41,7 +41,6 @@ import org.apache.dubbo.registry.zookeeper.ZookeeperServiceDiscovery;
import org.apache.dubbo.registrycenter.RegistryCenter;
import org.apache.dubbo.registrycenter.ZookeeperSingleRegistryCenter;
import org.apache.dubbo.rpc.cluster.Directory;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -310,7 +309,6 @@ public class SingleRegistryCenterDubboProtocolIntegrationTest implements Integra
private void initConsumer() {
referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(SingleRegistryCenterIntegrationService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
DubboBootstrap.getInstance().reference(referenceConfig);
referenceConfig.setRegistry(registryConfig);
referenceConfig.setScope(SCOPE_REMOTE);
@@ -326,7 +324,7 @@ public class SingleRegistryCenterDubboProtocolIntegrationTest implements Integra
*/
private void beforeRefer() {
// ReferenceConfig has integrated into DubboBootstrap or not
- Assertions.assertEquals(referenceConfig.getBootstrap(), DubboBootstrap.getInstance());
+ Assertions.assertEquals(referenceConfig.getScopeModel(), DubboBootstrap.getInstance().getApplicationModel().getDefaultModule());
}
/**
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
index ec806b9..bb511cc 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/exportprovider/SingleRegistryCenterExportProviderIntegrationTest.java
@@ -35,7 +35,6 @@ import org.apache.dubbo.registrycenter.ZookeeperMultipleRegistryCenter;
import org.apache.dubbo.rpc.ExporterListener;
import org.apache.dubbo.rpc.Filter;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -176,7 +175,6 @@ public class SingleRegistryCenterExportProviderIntegrationTest implements Integr
afterExport();
ReferenceConfig<SingleRegistryCenterExportProviderService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(SingleRegistryCenterExportProviderService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
referenceConfig.setScope(SCOPE_LOCAL);
referenceConfig.get().hello(PROVIDER_APPLICATION_NAME);
afterInvoke();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/injvm/SingleRegistryCenterInjvmIntegrationTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/injvm/SingleRegistryCenterInjvmIntegrationTest.java
index 0c5cc47..c13fcab 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/injvm/SingleRegistryCenterInjvmIntegrationTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/integration/single/injvm/SingleRegistryCenterInjvmIntegrationTest.java
@@ -18,12 +18,12 @@ package org.apache.dubbo.integration.single.injvm;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.ReferenceConfig;
-import org.apache.dubbo.config.ServiceListener;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.ServiceListener;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.integration.IntegrationTest;
import org.apache.dubbo.registrycenter.RegistryCenter;
@@ -144,7 +144,6 @@ public class SingleRegistryCenterInjvmIntegrationTest implements IntegrationTest
afterExport();
ReferenceConfig<SingleRegistryCenterInjvmService> referenceConfig = new ReferenceConfig<>();
referenceConfig.setInterface(SingleRegistryCenterInjvmService.class);
- referenceConfig.setBootstrap(DubboBootstrap.getInstance());
referenceConfig.setScope(SCOPE_LOCAL);
referenceConfig.get().hello("Dubbo");
afterInvoke();
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
index 6374cdb..d0f1263 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -19,8 +19,6 @@ package org.apache.dubbo.config.spring;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
-
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -46,7 +44,6 @@ public class ConfigCenterBean extends ConfigCenterConfig implements ApplicationC
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
- SpringExtensionInjector.addApplicationContext(applicationContext);
}
@Override
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 d07128e..71add7b 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
@@ -21,9 +21,10 @@ import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer;
+import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
import org.apache.dubbo.config.spring.reference.ReferenceBeanSupport;
-import org.apache.dubbo.config.spring.reference.ReferenceAttributes;
+import org.apache.dubbo.config.spring.schema.DubboBeanDefinitionParser;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.proxy.AbstractProxyFactory;
import org.springframework.aop.framework.ProxyFactory;
@@ -158,9 +159,15 @@ public class ReferenceBean<T> implements FactoryBean<T>,
/**
* Create bean instance.
+ *
+ * <p></p>
+ * Why we need a lazy proxy?
+ *
* <p/>
* When Spring searches beans by type, if Spring cannot determine the type of a factory bean, it may try to initialize it.
* The ReferenceBean is also a FactoryBean.
+ * <br/>
+ * (This has already been resolved by decorating the BeanDefinition: {@link DubboBeanDefinitionParser#configReferenceBean})
*
* <p/>
* In addition, if some ReferenceBeans are dependent on beans that are initialized very early,
@@ -172,13 +179,10 @@ public class ReferenceBean<T> implements FactoryBean<T>,
* <br/>
* In this way, the influence of Spring is eliminated, and the dubbo configuration initialization is controllable.
*
- * <p/>
- * Dubbo config beans are initialized in DubboConfigBeanInitializer.
- * <br/>
- * The actual references will be processing in DubboBootstrap.referServices().
*
* @see DubboConfigBeanInitializer
- * @see org.apache.dubbo.config.bootstrap.DubboBootstrap
+ * @see ReferenceBeanManager#initReferenceBean(ReferenceBean)
+ * @see DubboBeanDefinitionParser#configReferenceBean
*/
@Override
public T getObject() {
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 94af84a..6d7158f 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
@@ -19,11 +19,10 @@ package org.apache.dubbo.config.spring;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.annotation.Service;
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializationContext;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
-import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.config.support.Parameter;
-
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
@@ -65,8 +64,6 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
- //TODO remove SpringExtensionInjector.addApplicationContext();
- SpringExtensionInjector.addApplicationContext(applicationContext);
}
@Override
@@ -91,7 +88,8 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
}
}
//register service bean and set bootstrap
- DubboBootstrap.getInstance().service(this);
+ DubboSpringInitializationContext dubboContext = DubboBeanUtils.getInitializationContext(applicationContext);
+ dubboContext.getDubboBootstrap().service(this, dubboContext.getModuleModel());
}
/**
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
index ffb1335..4192949 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java
@@ -21,8 +21,8 @@ import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.config.DubboShutdownHook;
import org.apache.dubbo.config.bootstrap.BootstrapTakeoverMode;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
-
import org.apache.dubbo.config.spring.context.event.DubboAnnotationInitedEvent;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -52,25 +52,23 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
private final Log logger = LogFactory.getLog(getClass());
- private final DubboBootstrap dubboBootstrap;
private ApplicationContext applicationContext;
+ private DubboBootstrap bootstrap;
private boolean shouldInitConfigBeans;
public DubboBootstrapApplicationListener() {
- this.dubboBootstrap = initBootstrap();
}
public DubboBootstrapApplicationListener(boolean shouldInitConfigBeans) {
- this.dubboBootstrap = initBootstrap();
+ // maybe register DubboBootstrapApplicationListener manual during spring context starting
this.shouldInitConfigBeans = shouldInitConfigBeans;
}
- private DubboBootstrap initBootstrap() {
- DubboBootstrap dubboBootstrap = DubboBootstrap.getInstance();
- if (dubboBootstrap.getTakeoverMode() != BootstrapTakeoverMode.MANUAL) {
- dubboBootstrap.setTakeoverMode(BootstrapTakeoverMode.SPRING);
+ private void setBootstrap(DubboBootstrap bootstrap) {
+ this.bootstrap = bootstrap;
+ if (bootstrap.getTakeoverMode() != BootstrapTakeoverMode.MANUAL) {
+ bootstrap.setTakeoverMode(BootstrapTakeoverMode.SPRING);
}
- return dubboBootstrap;
}
@Override
@@ -95,7 +93,7 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
}
// All infrastructure config beans are loaded, initialize dubbo here
- DubboBootstrap.getInstance().initialize();
+ bootstrap.initialize();
}
private void onApplicationContextEvent(ApplicationContextEvent event) {
@@ -111,15 +109,15 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
}
private void onContextRefreshedEvent(ContextRefreshedEvent event) {
- if (dubboBootstrap.getTakeoverMode() == BootstrapTakeoverMode.SPRING) {
- dubboBootstrap.start();
+ if (bootstrap.getTakeoverMode() == BootstrapTakeoverMode.SPRING) {
+ bootstrap.start();
}
}
private void onContextClosedEvent(ContextClosedEvent event) {
- if (dubboBootstrap.getTakeoverMode() == BootstrapTakeoverMode.SPRING) {
+ if (bootstrap.getTakeoverMode() == BootstrapTakeoverMode.SPRING) {
// will call dubboBootstrap.stop() through shutdown callback.
- DubboShutdownHook.getDubboShutdownHook().run();
+ bootstrap.getApplicationModel().getBeanFactory().getBean(DubboShutdownHook.class).run();
}
}
@@ -147,7 +145,7 @@ public class DubboBootstrapApplicationListener implements ApplicationListener, A
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
-
+ this.setBootstrap(DubboBeanUtils.getBootstrap(applicationContext));
if (shouldInitConfigBeans) {
checkCallStackAndInit();
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapServletContextListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapServletContextListener.java
deleted file mode 100644
index c270b8b..0000000
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapServletContextListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config.spring.context;
-
-import org.apache.dubbo.config.DubboShutdownHook;
-import org.apache.dubbo.config.bootstrap.BootstrapTakeoverMode;
-import org.apache.dubbo.config.bootstrap.DubboBootstrap;
-
-import javax.servlet.ServletContextEvent;
-import javax.servlet.ServletContextListener;
-import javax.servlet.annotation.WebListener;
-
-/**
- * DubboBootstrap lifecycle controller for Servlet container.
- *
- * @see DubboBootstrapApplicationListener
- */
-@WebListener
-public class DubboBootstrapServletContextListener implements ServletContextListener {
-
- public DubboBootstrapServletContextListener() {
- // Set takeover mode when servlet container is starting
- if (DubboBootstrap.getInstance().getTakeoverMode() == BootstrapTakeoverMode.AUTO) {
- DubboBootstrap.getInstance().setTakeoverMode(BootstrapTakeoverMode.SERVLET);
- }
- }
-
- @Override
- public void contextInitialized(ServletContextEvent servletContextEvent) {
- // If takeover mode is not changed on servlet container is initialized, it means dubbo does not running in Spring context.
- // Otherwise, the takeover mode will be changed if dubbo is loaded by Spring.
- if (DubboBootstrap.getInstance().getTakeoverMode() == BootstrapTakeoverMode.SERVLET) {
- DubboBootstrap.getInstance().start();
- }
- }
-
- @Override
- public void contextDestroyed(ServletContextEvent servletContextEvent) {
- if (DubboBootstrap.getInstance().getTakeoverMode() == BootstrapTakeoverMode.SERVLET) {
- DubboShutdownHook.getDubboShutdownHook().run();
- }
- }
-
-}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
index f51bb35..bd8714c 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboConfigBeanInitializer.java
@@ -16,6 +16,8 @@
*/
package org.apache.dubbo.config.spring.context;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConsumerConfig;
@@ -27,18 +29,17 @@ import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.SslConfig;
+import org.apache.dubbo.config.context.AbstractConfigManager;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.spring.ConfigCenterBean;
import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.dubbo.rpc.model.ModuleModel;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -60,8 +61,13 @@ public class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin
private AtomicBoolean initialized = new AtomicBoolean(false);
private ConfigurableListableBeanFactory beanFactory;
private ReferenceBeanManager referenceBeanManager;
+
+ @Autowired
private ConfigManager configManager;
+ @Autowired
+ private ModuleModel moduleModel;
+
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
@@ -74,7 +80,6 @@ public class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin
private void init() {
if (initialized.compareAndSet(false, true)) {
- configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
try {
prepareDubboConfigBeans();
@@ -92,22 +97,25 @@ public class DubboConfigBeanInitializer implements BeanFactoryAware, Initializin
logger.info("loading dubbo config beans ...");
//Make sure all these config beans are inited and registered to ConfigManager
- loadConfigBeansOfType(ApplicationConfig.class);
- loadConfigBeansOfType(ModuleConfig.class);
- loadConfigBeansOfType(RegistryConfig.class);
- loadConfigBeansOfType(ProtocolConfig.class);
- loadConfigBeansOfType(MonitorConfig.class);
- loadConfigBeansOfType(ProviderConfig.class);
- loadConfigBeansOfType(ConsumerConfig.class);
- loadConfigBeansOfType(ConfigCenterBean.class);
- loadConfigBeansOfType(MetadataReportConfig.class);
- loadConfigBeansOfType(MetricsConfig.class);
- loadConfigBeansOfType(SslConfig.class);
+ // load application configs
+ loadConfigBeansOfType(ApplicationConfig.class, configManager);
+ loadConfigBeansOfType(ModuleConfig.class, configManager);
+ loadConfigBeansOfType(RegistryConfig.class, configManager);
+ loadConfigBeansOfType(ProtocolConfig.class, configManager);
+ loadConfigBeansOfType(MonitorConfig.class, configManager);
+ loadConfigBeansOfType(ConfigCenterBean.class, configManager);
+ loadConfigBeansOfType(MetadataReportConfig.class, configManager);
+ loadConfigBeansOfType(MetricsConfig.class, configManager);
+ loadConfigBeansOfType(SslConfig.class, configManager);
+
+ // load module configs
+ loadConfigBeansOfType(ProviderConfig.class, moduleModel.getConfigManager());
+ loadConfigBeansOfType(ConsumerConfig.class, moduleModel.getConfigManager());
logger.info("dubbo config beans are loaded.");
}
- private void loadConfigBeansOfType(Class<? extends AbstractConfig> configClass) {
+ private void loadConfigBeansOfType(Class<? extends AbstractConfig> configClass, AbstractConfigManager configManager) {
String[] beanNames = beanFactory.getBeanNamesForType(configClass, true, false);
for (String beanName : beanNames) {
AbstractConfig configBean = beanFactory.getBean(beanName, configClass);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
index 0f79d22..4818fe0 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboInfraBeanRegisterPostProcessor.java
@@ -22,7 +22,6 @@ import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.config.spring.util.EnvironmentUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -71,19 +70,23 @@ public class DubboInfraBeanRegisterPostProcessor implements BeanDefinitionRegist
DubboBeanUtils.registerPlaceholderConfigurerBeanIfNotExists(beanFactory, registry);
}
+ ApplicationModel applicationModel = DubboBeanUtils.getApplicationModel(beanFactory);
+
+ // Initialize SpringExtensionInjector
+ SpringExtensionInjector.get(applicationModel).init(applicationContext);
+
// Initialize dubbo Environment before ConfigManager
// Extract dubbo props from Spring env and put them to app config
ConfigurableEnvironment environment = (ConfigurableEnvironment) applicationContext.getEnvironment();
SortedMap<String, String> dubboProperties = EnvironmentUtils.filterDubboProperties(environment);
- ApplicationModel.defaultModel().getApplicationEnvironment().setAppConfigMap(dubboProperties);
+ applicationModel.getApplicationEnvironment().setAppConfigMap(dubboProperties);
// register ConfigManager singleton
- beanFactory.registerSingleton(ConfigManager.BEAN_NAME, ApplicationModel.defaultModel().getApplicationConfigManager());
+ beanFactory.registerSingleton(ConfigManager.BEAN_NAME, applicationModel.getApplicationConfigManager());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
- SpringExtensionInjector.addApplicationContext(applicationContext);
}
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
index 08a5e09..1bca441 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationContext.java
@@ -16,7 +16,12 @@
*/
package org.apache.dubbo.config.spring.context;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.context.ApplicationContext;
/**
* Dubbo spring initialization context object
@@ -25,6 +30,20 @@ public class DubboSpringInitializationContext {
private BeanDefinitionRegistry registry;
+ private ConfigurableListableBeanFactory beanFactory;
+
+ private ApplicationContext applicationContext;
+
+ private ModuleModel moduleModel;
+
+ private DubboBootstrap dubboBootstrap;
+
+ private volatile boolean bound;
+
+ public void markAsBound() {
+ bound = true;
+ }
+
public BeanDefinitionRegistry getRegistry() {
return registry;
}
@@ -33,4 +52,59 @@ public class DubboSpringInitializationContext {
this.registry = registry;
}
+ public ConfigurableListableBeanFactory getBeanFactory() {
+ return beanFactory;
+ }
+
+ void setBeanFactory(ConfigurableListableBeanFactory beanFactory) {
+ this.beanFactory = beanFactory;
+ }
+
+ public ApplicationContext getApplicationContext() {
+ return applicationContext;
+ }
+
+ void setApplicationContext(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
+ public ApplicationModel getApplicationModel() {
+ return (moduleModel == null) ? null : moduleModel.getApplicationModel();
+ }
+
+ public ModuleModel getModuleModel() {
+ return moduleModel;
+ }
+
+ /**
+ * Change the binding ModuleModel, the ModuleModel and DubboBootstrap must be matched.
+ *
+ * @see #setDubboBootstrap(DubboBootstrap)
+ * @param moduleModel
+ */
+ public void setModuleModel(ModuleModel moduleModel) {
+ if (bound) {
+ throw new IllegalStateException("Cannot change ModuleModel after bound context");
+ }
+ this.moduleModel = moduleModel;
+ }
+
+ public DubboBootstrap getDubboBootstrap() {
+ return dubboBootstrap;
+ }
+
+ /**
+ * Change the binding DubboBootstrap instance, the ModuleModel and DubboBootstrap must be matched.
+ * <p></p>
+ * By default, DubboBoostrap is created using the ApplicationModel in which the ModuleModel resides.
+ *
+ * @see #setModuleModel(ModuleModel)
+ * @param dubboBootstrap
+ */
+ public void setDubboBootstrap(DubboBootstrap dubboBootstrap) {
+ if (bound) {
+ throw new IllegalStateException("Cannot change DubboBootstrap after bound context");
+ }
+ this.dubboBootstrap = dubboBootstrap;
+ }
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java
index 9637996..223307a 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializationCustomizer.java
@@ -17,18 +17,22 @@
package org.apache.dubbo.config.spring.context;
import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.rpc.model.ModuleModel;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
+import static org.apache.dubbo.common.extension.ExtensionScope.FRAMEWORK;
+
/**
* Custom dubbo spring initialization
*/
-@SPI
+@SPI(scope = FRAMEWORK)
public interface DubboSpringInitializationCustomizer {
/**
* <p>Customize dubbo spring initialization on bean registry processing phase.</p>
* <p>You can register a {@link BeanFactoryPostProcessor} or {@link BeanPostProcessor} for custom processing.</p>
+ * <p>Or change the bind module model via {@link DubboSpringInitializationContext#setModuleModel(ModuleModel)}.</p>
*
* <p><b>Note:</b></p>
* <p>1. The bean factory may be not ready yet when triggered by parsing dubbo xml definition.</p>
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java
index 2ae3d37..4272e3b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboSpringInitializer.java
@@ -16,9 +16,18 @@
*/
package org.apache.dubbo.config.spring.context;
-import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
+import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
import org.apache.dubbo.config.spring.util.DubboBeanUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.apache.dubbo.rpc.model.ModuleModel;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.support.GenericApplicationContext;
import java.util.Map;
import java.util.Set;
@@ -31,28 +40,128 @@ public class DubboSpringInitializer {
private static Map<BeanDefinitionRegistry, DubboSpringInitializationContext> contextMap = new ConcurrentHashMap<>();
+ private DubboSpringInitializer() {
+ }
+
public static void initialize(BeanDefinitionRegistry registry) {
if (contextMap.putIfAbsent(registry, new DubboSpringInitializationContext()) != null) {
return;
}
- // register common beans
- DubboBeanUtils.registerCommonBeans(registry);
-
// prepare context and do customize
DubboSpringInitializationContext context = contextMap.get(registry);
+
+ // find beanFactory and applicationContext
+ ConfigurableListableBeanFactory beanFactory = findBeanFactory(registry);
+ ApplicationContext applicationContext = findApplicationContext(registry, beanFactory);
+
+ // init dubbo context
+ initContext(context, registry, beanFactory, applicationContext);
+ }
+
+
+ private static void initContext(DubboSpringInitializationContext context, BeanDefinitionRegistry registry,
+ ConfigurableListableBeanFactory beanFactory, ApplicationContext applicationContext) {
context.setRegistry(registry);
+ context.setApplicationContext(applicationContext);
+
+ // customize context, you can change the bind module model via DubboSpringInitializationCustomizer SPI
customize(context);
+
+ // init ApplicationModel
+ ApplicationModel applicationModel = context.getApplicationModel();
+ if (applicationModel == null) {
+ if (findContextForApplication(ApplicationModel.defaultModel()) == null) {
+ // first spring context use default application instance
+ applicationModel = ApplicationModel.defaultModel();
+ } else {
+ // create an new application instance for later spring context
+ applicationModel = FrameworkModel.defaultModel().newApplication();
+ }
+
+ // init ModuleModel
+ ModuleModel moduleModel = applicationModel.getDefaultModule();
+ context.setModuleModel(moduleModel);
+ }
+
+ // Init SpringExtensionInjector
+ // Maybe the applicationContext is null, that means the Spring ApplicationContext is not completely created, so can not retrieve bean from it.
+ // We will reinitialize it again in DubboInfraBeanRegisterPostProcessor
+ if (applicationContext != null) {
+ SpringExtensionInjector.get(context.getApplicationModel()).init(applicationContext);
+ }
+
+ // create DubboBootstrap
+ DubboBootstrap bootstrap = context.getDubboBootstrap();
+ if (bootstrap == null) {
+ if (applicationModel == ApplicationModel.defaultModel()) {
+ bootstrap = DubboBootstrap.getInstance();
+ } else {
+ bootstrap = DubboBootstrap.newInstance(applicationModel);
+ }
+ context.setDubboBootstrap(bootstrap);
+ }
+
+ // bind dubbo initialization context to spring context
+ registerContextBeans(beanFactory, context);
+
+ // mark context as bound
+ context.markAsBound();
+
+ // register common beans
+ DubboBeanUtils.registerCommonBeans(registry);
}
- private DubboSpringInitializer() {
+ private static ConfigurableListableBeanFactory findBeanFactory(BeanDefinitionRegistry registry) {
+ ConfigurableListableBeanFactory beanFactory = null;
+ if (registry instanceof ConfigurableListableBeanFactory) {
+ beanFactory = (ConfigurableListableBeanFactory) registry;
+ } else if (registry instanceof GenericApplicationContext) {
+ GenericApplicationContext genericApplicationContext = (GenericApplicationContext) registry;
+ beanFactory = genericApplicationContext.getBeanFactory();
+ } else {
+ throw new IllegalStateException("Can not find Spring BeanFactory from registry: " + registry.getClass().getName());
+ }
+ return beanFactory;
+ }
+
+ private static ApplicationContext findApplicationContext(BeanDefinitionRegistry registry, ConfigurableListableBeanFactory beanFactory) {
+ // GenericApplicationContext
+ if (registry instanceof ApplicationContext) {
+ return (ApplicationContext) registry;
+ }
+ // find by ApplicationContextAware
+ ApplicationContextAwareBean contextBean = new ApplicationContextAwareBean();
+ beanFactory.initializeBean(contextBean, ApplicationContextAwareBean.class.getSimpleName());
+ return contextBean.applicationContext;
+ }
+
+ private static void registerContextBeans(ConfigurableListableBeanFactory beanFactory, DubboSpringInitializationContext context) {
+ // register singleton
+ registerSingleton(beanFactory, context);
+ registerSingleton(beanFactory, context.getApplicationModel());
+ registerSingleton(beanFactory, context.getModuleModel());
+ registerSingleton(beanFactory, context.getDubboBootstrap());
+ }
+
+ private static void registerSingleton(ConfigurableListableBeanFactory beanFactory, Object bean) {
+ beanFactory.registerSingleton(bean.getClass().getName(), bean);
+ }
+
+ private static DubboSpringInitializationContext findContextForApplication(ApplicationModel applicationModel) {
+ for (DubboSpringInitializationContext initializationContext : contextMap.values()) {
+ if (initializationContext.getApplicationModel() == applicationModel) {
+ return initializationContext;
+ }
+ }
+ return null;
}
private static void customize(DubboSpringInitializationContext context) {
// find initialization customizers
- Set<DubboSpringInitializationCustomizer> customizers = ExtensionLoader
+ Set<DubboSpringInitializationCustomizer> customizers = FrameworkModel.defaultModel()
.getExtensionLoader(DubboSpringInitializationCustomizer.class)
.getSupportedExtensionInstances();
@@ -60,4 +169,14 @@ public class DubboSpringInitializer {
customizer.customize(context);
}
}
+
+ static class ApplicationContextAwareBean implements ApplicationContextAware {
+
+ private ApplicationContext applicationContext;
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+ this.applicationContext = applicationContext;
+ }
+ }
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboAnnotationInitedEvent.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboAnnotationInitedEvent.java
index 1295f04..b53e730 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboAnnotationInitedEvent.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/event/DubboAnnotationInitedEvent.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.config.spring.context.event;
import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
/**
@@ -31,7 +32,15 @@ public class DubboAnnotationInitedEvent extends ApplicationEvent {
* @param source the object on which the event initially occurred or with
* which the event is associated (never {@code null})
*/
- public DubboAnnotationInitedEvent(Object source) {
+ public DubboAnnotationInitedEvent(ApplicationContext source) {
super(source);
}
+
+ /**
+ * Get the {@code ApplicationContext} that the event was raised for.
+ */
+ public final ApplicationContext getApplicationContext() {
+ return (ApplicationContext) getSource();
+ }
+
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
index c580ab2..6e6a1a8 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjector.java
@@ -17,18 +17,16 @@
package org.apache.dubbo.config.spring.extension;
import org.apache.dubbo.common.context.Lifecycle;
+import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionInjector;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ConcurrentHashSet;
-import org.apache.dubbo.config.DubboShutdownHook;
-
-import com.alibaba.spring.util.BeanFactoryUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.ApplicationContext;
-import org.springframework.context.ConfigurableApplicationContext;
-import java.util.Set;
+import java.util.Arrays;
/**
* SpringExtensionInjector
@@ -36,50 +34,87 @@ import java.util.Set;
public class SpringExtensionInjector implements ExtensionInjector, Lifecycle {
private static final Logger logger = LoggerFactory.getLogger(SpringExtensionInjector.class);
- private static final Set<ApplicationContext> CONTEXTS = new ConcurrentHashSet<ApplicationContext>();
+ public static final String NAME = "spring";
+
+ private ApplicationContext context;
+ @Deprecated
public static void addApplicationContext(ApplicationContext context) {
- CONTEXTS.add(context);
- if (context instanceof ConfigurableApplicationContext) {
- ((ConfigurableApplicationContext) context).registerShutdownHook();
- // see https://github.com/apache/dubbo/issues/7093
- DubboShutdownHook.getDubboShutdownHook().unregister();
- }
+// CONTEXTS.add(context);
+// if (context instanceof ConfigurableApplicationContext) {
+// ((ConfigurableApplicationContext) context).registerShutdownHook();
+// // see https://github.com/apache/dubbo/issues/7093
+// DubboShutdownHook.getDubboShutdownHook().unregister();
+// }
+ }
+
+// @Deprecated
+// public static Set<ApplicationContext> getContexts() {
+// // return contexts;
+// return Collections.emptySet();
+// }
+
+// @Deprecated
+// public static void clearContexts() {
+// //contexts.clear();
+// }
+
+ public static SpringExtensionInjector get(ExtensionAccessor extensionAccessor) {
+ return (SpringExtensionInjector) extensionAccessor.getExtension(ExtensionInjector.class, NAME);
}
- public static Set<ApplicationContext> getContexts() {
- return CONTEXTS;
+ public ApplicationContext getContext() {
+ return context;
}
- // currently for test purpose
- public static void clearContexts() {
- CONTEXTS.clear();
+ public void init(ApplicationContext context) {
+ this.context = context;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getInstance(Class<T> type, String name) {
- //SPI should be get from SpiExtensionInjector
+ if (context == null) {
+ // ignore if spring context is not bound
+ return null;
+ }
+
+ //check @SPI annotation
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
return null;
}
- for (ApplicationContext context : CONTEXTS) {
- T bean = BeanFactoryUtils.getOptionalBean(context, name, type);
- if (bean != null) {
- return bean;
- }
+ T bean = getOptionalBean(context, name, type);
+ if (bean != null) {
+ return bean;
}
//logger.warn("No spring extension (bean) named:" + name + ", try to find an extension (bean) of type " + type.getName());
+ return null;
+ }
+ private <T> T getOptionalBean(ListableBeanFactory beanFactory, String name, Class<T> type) {
+ if (StringUtils.isEmpty(name)) {
+ String[] beanNamesForType = beanFactory.getBeanNamesForType(type, true, false);
+ if (beanNamesForType != null) {
+ if (beanNamesForType.length == 1) {
+ return beanFactory.getBean(beanNamesForType[0], type);
+ } else if (beanNamesForType.length > 1) {
+ throw new IllegalStateException("Expect single but found " + beanNamesForType.length + " beans in spring context: " +
+ Arrays.toString(beanNamesForType));
+ }
+ }
+ } else {
+ if (beanFactory.containsBean(name)) {
+ return beanFactory.getBean(name, type);
+ }
+ }
return null;
}
@Override
public void initialize() throws IllegalStateException {
- clearContexts();
}
@Override
@@ -89,6 +124,5 @@ public class SpringExtensionInjector implements ExtensionInjector, Lifecycle {
@Override
public void destroy() {
- clearContexts();
}
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
index c87a068..ce5d42b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/reference/ReferenceBeanManager.java
@@ -22,6 +22,8 @@ import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializationContext;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@@ -52,7 +54,9 @@ public class ReferenceBeanManager implements ApplicationContextAware {
private Map<String, ReferenceConfig> referenceConfigMap = new ConcurrentHashMap<>();
private ApplicationContext applicationContext;
+ private DubboBootstrap dubboBootstrap;
private volatile boolean initialized = false;
+ private DubboSpringInitializationContext initializationContext;
public void addReference(ReferenceBean referenceBean) throws Exception {
String referenceBeanName = referenceBean.getId();
@@ -115,6 +119,8 @@ public class ReferenceBeanManager implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
+ this.dubboBootstrap = DubboBeanUtils.getBootstrap(applicationContext);
+ initializationContext = DubboBeanUtils.getInitializationContext(applicationContext);
}
/**
@@ -169,7 +175,7 @@ public class ReferenceBeanManager implements ApplicationContextAware {
referenceConfigMap.put(referenceKey, referenceConfig);
// register ReferenceConfig
- DubboBootstrap.getInstance().reference(referenceConfig);
+ dubboBootstrap.reference(referenceConfig, initializationContext.getModuleModel());
}
// associate referenceConfig to referenceBean
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 7993feb..200e57c 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
@@ -31,7 +31,6 @@ import org.apache.dubbo.config.spring.ConfigCenterBean;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.beans.factory.config.ConfigurableSourceBeanMetadataElement;
-
import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
@@ -83,7 +82,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport implements Co
registerAnnotationConfigProcessors(registry);
// initialize dubbo beans
- DubboSpringInitializer.initialize(registry);
+ DubboSpringInitializer.initialize(parserContext.getRegistry());
BeanDefinition beanDefinition = super.parse(element, parserContext);
setSource(beanDefinition);
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
index c28db37..c9cd8b6 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/DataSourceStatusChecker.java
@@ -23,7 +23,7 @@ import org.apache.dubbo.common.status.Status;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
-
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
@@ -31,8 +31,6 @@ import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
/**
* DataSourceStatusChecker
@@ -42,17 +40,31 @@ public class DataSourceStatusChecker implements StatusChecker {
private static final Logger logger = LoggerFactory.getLogger(DataSourceStatusChecker.class);
+ private ApplicationModel applicationModel;
+
+ private ApplicationContext applicationContext;
+
+ public DataSourceStatusChecker(ApplicationModel applicationModel) {
+ this.applicationModel = applicationModel;
+ }
+
+ public DataSourceStatusChecker(ApplicationContext context) {
+ this.applicationContext = context;
+ }
+
@Override
public Status check() {
- Optional<ApplicationContext> context =
- SpringExtensionInjector.getContexts().stream().filter(Objects::nonNull).findFirst();
+ if (applicationContext == null) {
+ SpringExtensionInjector springExtensionInjector = SpringExtensionInjector.get(applicationModel);
+ applicationContext = springExtensionInjector.getContext();
+ }
- if (!context.isPresent()) {
+ if (applicationContext == null) {
return new Status(Status.Level.UNKNOWN);
}
Map<String, DataSource> dataSources =
- context.get().getBeansOfType(DataSource.class, false, false);
+ applicationContext.getBeansOfType(DataSource.class, false, false);
if (CollectionUtils.isEmptyMap(dataSources)) {
return new Status(Status.Level.UNKNOWN);
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
index cae9260..fad4121 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/status/SpringStatusChecker.java
@@ -22,10 +22,9 @@ import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.status.Status;
import org.apache.dubbo.common.status.StatusChecker;
import org.apache.dubbo.config.spring.extension.SpringExtensionInjector;
-
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
-import org.springframework.web.context.support.GenericWebApplicationContext;
import java.lang.reflect.Method;
@@ -37,29 +36,47 @@ public class SpringStatusChecker implements StatusChecker {
private static final Logger logger = LoggerFactory.getLogger(SpringStatusChecker.class);
+ private ApplicationModel applicationModel;
+
+ private ApplicationContext applicationContext;
+
+ public SpringStatusChecker(ApplicationModel applicationModel) {
+ this.applicationModel = applicationModel;
+ }
+
+ public SpringStatusChecker(ApplicationContext applicationContext) {
+ this.applicationContext = applicationContext;
+ }
+
@Override
public Status check() {
- ApplicationContext context = null;
- for (ApplicationContext c : SpringExtensionInjector.getContexts()) {
- // [Issue] SpringStatusChecker execute errors on non-XML Spring configuration
- // issue : https://github.com/apache/dubbo/issues/3615
- if(c instanceof GenericWebApplicationContext) { // ignore GenericXmlApplicationContext
- continue;
- }
+ // TODO It seems to be ok with GenericWebApplicationContext, need further confirmation
+// ApplicationContext context = null;
+// for (ApplicationContext c : SpringExtensionInjector.getContexts()) {
+// // [Issue] SpringStatusChecker execute errors on non-XML Spring configuration
+// // issue : https://github.com/apache/dubbo/issues/3615
+// if(c instanceof GenericWebApplicationContext) { // ignore GenericXmlApplicationContext
+// continue;
+// }
+//
+// if (c != null) {
+// context = c;
+// break;
+// }
+// }
- if (c != null) {
- context = c;
- break;
- }
+ if (applicationContext == null && applicationModel != null) {
+ SpringExtensionInjector springExtensionInjector = SpringExtensionInjector.get(applicationModel);
+ applicationContext = springExtensionInjector.getContext();
}
- if (context == null) {
+ if (applicationContext == null) {
return new Status(Status.Level.UNKNOWN);
}
Status.Level level;
- if (context instanceof Lifecycle) {
- if (((Lifecycle) context).isRunning()) {
+ if (applicationContext instanceof Lifecycle) {
+ if (((Lifecycle) applicationContext).isRunning()) {
level = Status.Level.OK;
} else {
level = Status.Level.ERROR;
@@ -69,7 +86,7 @@ public class SpringStatusChecker implements StatusChecker {
}
StringBuilder buf = new StringBuilder();
try {
- Class<?> cls = context.getClass();
+ Class<?> cls = applicationContext.getClass();
Method method = null;
while (cls != null && method == null) {
try {
@@ -82,7 +99,7 @@ public class SpringStatusChecker implements StatusChecker {
if (!method.isAccessible()) {
method.setAccessible(true);
}
- String[] configs = (String[]) method.invoke(context, new Object[0]);
+ String[] configs = (String[]) method.invoke(applicationContext, new Object[0]);
if (configs != null && configs.length > 0) {
for (String config : configs) {
if (buf.length() > 0) {
@@ -92,6 +109,8 @@ public class SpringStatusChecker implements StatusChecker {
}
}
}
+ } catch (UnsupportedOperationException t) {
+ logger.debug(t.getMessage(), t);
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
index 72f2177..2cc878b 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/DubboBeanUtils.java
@@ -18,14 +18,18 @@ package org.apache.dubbo.config.spring.util;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.apache.dubbo.config.spring.beans.factory.annotation.ServicePackagesHolder;
-import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer;
-import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
+import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigAliasPostProcessor;
import org.apache.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
+import org.apache.dubbo.config.spring.beans.factory.annotation.ServicePackagesHolder;
import org.apache.dubbo.config.spring.beans.factory.config.DubboConfigDefaultPropertyValueBeanPostProcessor;
import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener;
+import org.apache.dubbo.config.spring.context.DubboConfigBeanInitializer;
import org.apache.dubbo.config.spring.context.DubboInfraBeanRegisterPostProcessor;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializationContext;
+import org.apache.dubbo.config.spring.reference.ReferenceBeanManager;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
@@ -65,20 +69,20 @@ public interface DubboBeanUtils {
// Since 2.5.7 Register @Reference Annotation Bean Processor as an infrastructure Bean
registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME,
- ReferenceAnnotationBeanPostProcessor.class);
+ ReferenceAnnotationBeanPostProcessor.class);
// TODO Whether DubboConfigAliasPostProcessor can be removed ?
// Since 2.7.4 [Feature] https://github.com/apache/dubbo/issues/5093
registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME,
- DubboConfigAliasPostProcessor.class);
+ DubboConfigAliasPostProcessor.class);
// Since 2.7.4 Register DubboBootstrapApplicationListener as an infrastructure Bean
registerInfrastructureBean(registry, DubboBootstrapApplicationListener.BEAN_NAME,
- DubboBootstrapApplicationListener.class);
+ DubboBootstrapApplicationListener.class);
// Since 2.7.6 Register DubboConfigDefaultPropertyValueBeanPostProcessor as an infrastructure Bean
registerInfrastructureBean(registry, DubboConfigDefaultPropertyValueBeanPostProcessor.BEAN_NAME,
- DubboConfigDefaultPropertyValueBeanPostProcessor.class);
+ DubboConfigDefaultPropertyValueBeanPostProcessor.class);
// Dubbo config initializer
registerInfrastructureBean(registry, DubboConfigBeanInitializer.BEAN_NAME, DubboConfigBeanInitializer.class);
@@ -96,8 +100,8 @@ public interface DubboBeanUtils {
* @return if it's a first time to register, return <code>true</code>, or <code>false</code>
*/
static boolean registerInfrastructureBean(BeanDefinitionRegistry beanDefinitionRegistry,
- String beanName,
- Class<?> beanType) {
+ String beanName,
+ Class<?> beanType) {
boolean registered = false;
@@ -109,7 +113,7 @@ public interface DubboBeanUtils {
if (log.isDebugEnabled()) {
log.debug("The Infrastructure bean definition [" + beanDefinition
- + "with name [" + beanName + "] has been registered.");
+ + "with name [" + beanName + "] has been registered.");
}
}
@@ -120,10 +124,11 @@ public interface DubboBeanUtils {
* Register a placeholder configurer beans if not exists.
* Call this method in BeanDefinitionRegistryPostProcessor,
* in order to enable the registered BeanFactoryPostProcessor bean to be loaded and executed.
- * @see DubboInfraBeanRegisterPostProcessor
- * @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)
+ *
* @param beanFactory
* @param registry
+ * @see DubboInfraBeanRegisterPostProcessor
+ * @see org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List)
*/
static void registerPlaceholderConfigurerBeanIfNotExists(ConfigurableListableBeanFactory beanFactory, BeanDefinitionRegistry registry) {
// Auto register a PropertyPlaceholderConfigurer bean to resolve placeholders with Spring Environment PropertySources
@@ -133,12 +138,12 @@ public interface DubboBeanUtils {
propertySourcesPlaceholderPropertyValues.put("ignoreUnresolvablePlaceholders", true);
registerBeanDefinition(registry, PropertySourcesPlaceholderConfigurer.class.getName(),
- PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues);
+ PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues);
}
}
static boolean registerBeanDefinition(BeanDefinitionRegistry registry, String beanName,
- Class<?> beanClass, Map<String, Object> extraPropertyValues) {
+ Class<?> beanClass, Map<String, Object> extraPropertyValues) {
if (registry.containsBeanDefinition(beanName)) {
return false;
}
@@ -172,4 +177,29 @@ public interface DubboBeanUtils {
static ReferenceAnnotationBeanPostProcessor getReferenceAnnotationBeanPostProcessor(ApplicationContext applicationContext) {
return getReferenceAnnotationBeanPostProcessor((AbstractBeanFactory) applicationContext.getAutowireCapableBeanFactory());
}
+
+ static DubboSpringInitializationContext getInitializationContext(BeanFactory beanFactory) {
+ String beanName = DubboSpringInitializationContext.class.getName();
+ if (beanFactory.containsBean(beanName)) {
+ return beanFactory.getBean(beanName, DubboSpringInitializationContext.class);
+ }
+ return null;
+ }
+
+ static DubboBootstrap getBootstrap(BeanFactory beanFactory) {
+ String beanName = DubboBootstrap.class.getName();
+ if (beanFactory.containsBean(beanName)) {
+ return beanFactory.getBean(beanName, DubboBootstrap.class);
+ }
+ return null;
+ }
+
+ static ApplicationModel getApplicationModel(BeanFactory beanFactory) {
+ String beanName = ApplicationModel.class.getName();
+ if (beanFactory.containsBean(beanName)) {
+ return beanFactory.getBean(beanName, ApplicationModel.class);
+ }
+ return null;
+ }
+
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
index a320f36..5fd0ad6 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/ConfigTest.java
@@ -30,6 +30,7 @@ import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.spring.action.DemoActionByAnnotation;
import org.apache.dubbo.config.spring.action.DemoActionBySetter;
import org.apache.dubbo.config.spring.annotation.consumer.AnnotationAction;
@@ -52,7 +53,6 @@ import org.apache.dubbo.rpc.RpcContext;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericService;
-
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -133,9 +133,6 @@ public class ConfigTest {
try {
ctx.start();
- // clear config manager
- ApplicationModel.defaultModel().getApplicationConfigManager().destroy();
-
DemoService demoService = refer("dubbo://127.0.0.1:20887");
String hello = demoService.sayName("hello");
assertEquals("welcome:hello", hello);
@@ -158,7 +155,7 @@ public class ConfigTest {
reference.setInterface(HelloService.class);
reference.setUrl("dubbo://127.0.0.1:12345");
- DubboBootstrap bootstrap = DubboBootstrap.getInstance()
+ DubboBootstrap bootstrap = DubboBootstrap.newInstance()
.application(new ApplicationConfig("consumer"))
.reference(reference)
.start();
@@ -197,7 +194,7 @@ public class ConfigTest {
reference.setInterface(DemoService.class);
reference.setUrl(url);
- DubboBootstrap bootstrap = DubboBootstrap.getInstance()
+ DubboBootstrap bootstrap = DubboBootstrap.newInstance()
.application(new ApplicationConfig("consumer"))
.reference(reference)
.start();
@@ -241,9 +238,6 @@ public class ConfigTest {
try {
ctx.start();
- // clear config manager
- ApplicationModel.defaultModel().getApplicationConfigManager().destroy();
-
DemoService demoService = refer("dubbo://127.0.0.1:20881");
String hello = demoService.sayName("hello");
assertEquals("say:hello", hello);
@@ -481,18 +475,16 @@ public class ConfigTest {
try {
providerContext.start();
- // clear config manager
- ApplicationModel.defaultModel().getApplicationConfigManager().destroy();
-
- ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(resourcePath + "/init-reference.xml",
+ // consumer app
+ ClassPathXmlApplicationContext consumerContext = new ClassPathXmlApplicationContext(resourcePath + "/init-reference.xml",
resourcePath + "/init-reference-properties.xml");
try {
- ctx.start();
+ consumerContext.start();
- NotifyService notifyService = ctx.getBean(NotifyService.class);
+ NotifyService notifyService = consumerContext.getBean(NotifyService.class);
// check reference bean
- Map<String, ReferenceBean> referenceBeanMap = ctx.getBeansOfType(ReferenceBean.class);
+ Map<String, ReferenceBean> referenceBeanMap = consumerContext.getBeansOfType(ReferenceBean.class);
Assertions.assertEquals(2, referenceBeanMap.size());
ReferenceBean referenceBean = referenceBeanMap.get("&demoService");
Assertions.assertNotNull(referenceBean);
@@ -524,15 +516,15 @@ public class ConfigTest {
// do call
- DemoService demoService = (DemoService) ctx.getBean("demoService");
+ DemoService demoService = (DemoService) consumerContext.getBean("demoService");
assertEquals("say:world", demoService.sayName("world"));
- GenericService demoService2 = (GenericService) ctx.getBean("demoService2");
+ GenericService demoService2 = (GenericService) consumerContext.getBean("demoService2");
assertEquals("say:world", demoService2.$invoke("sayName", new String[]{"java.lang.String"}, new Object[]{"world"}));
} finally {
- ctx.stop();
- ctx.close();
+ consumerContext.stop();
+ consumerContext.close();
}
} finally {
providerContext.stop();
@@ -833,7 +825,8 @@ public class ConfigTest {
// set default value of check
assertEquals(false, reference.shouldCheck());
- ConsumerConfig defaultConsumer = ApplicationModel.defaultModel().getApplicationConfigManager().getDefaultConsumer().get();
+ ModuleConfigManager moduleConfigManager = ApplicationModel.defaultModel().getDefaultModule().getConfigManager();
+ ConsumerConfig defaultConsumer = moduleConfigManager.getDefaultConsumer().get();
assertEquals(1234, defaultConsumer.getTimeout());
assertEquals(false, defaultConsumer.isCheck());
} finally {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
index 2f216c0..abc20c3 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/JavaConfigBeanTest.java
@@ -25,6 +25,7 @@ import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.impl.DemoServiceImpl;
@@ -32,7 +33,6 @@ import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
import org.apache.dubbo.rpc.Constants;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -104,7 +104,9 @@ public class JavaConfigBeanTest {
Assertions.assertEquals(2346, protocolConfig.getPort());
Assertions.assertEquals(MY_PROTOCOL_ID, protocolConfig.getId());
- ConsumerConfig consumerConfig = configManager.getDefaultConsumer().get();
+ ApplicationModel applicationModel = consumerContext.getBean(ApplicationModel.class);
+ ModuleConfigManager moduleConfigManager = applicationModel.getDefaultModule().getConfigManager();
+ ConsumerConfig consumerConfig = moduleConfigManager.getDefaultConsumer().get();
Assertions.assertEquals(1000, consumerConfig.getTimeout());
Assertions.assertEquals("demo", consumerConfig.getGroup());
Assertions.assertEquals(false, consumerConfig.isCheck());
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MethodConfigCallbackTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MethodConfigCallbackTest.java
index f6895f5..0290f42 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MethodConfigCallbackTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/MethodConfigCallbackTest.java
@@ -23,11 +23,11 @@ import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.config.spring.api.MethodCallback;
import org.apache.dubbo.config.spring.context.annotation.provider.ProviderConfiguration;
import org.apache.dubbo.config.spring.impl.MethodCallbackImpl;
-import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
+import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
+import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootConfigPropsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootConfigPropsTest.java
index a97ee3b..945eaa7 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootConfigPropsTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootConfigPropsTest.java
@@ -28,9 +28,11 @@ import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.ZookeeperMultipleRegistryCenter;
+import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -87,6 +89,9 @@ public class SpringBootConfigPropsTest {
@Autowired
private ConfigManager configManager;
+ @Autowired
+ private ModuleModel moduleModel;
+
@Test
public void testConfigProps() {
@@ -126,10 +131,11 @@ public class SpringBootConfigPropsTest {
Assertions.assertEquals("zookeeper://127.0.0.1:2182", reportConfig.getAddress());
Assertions.assertEquals("User", reportConfig.getUsername());
- ProviderConfig providerConfig = configManager.getDefaultProvider().get();
+ ModuleConfigManager moduleConfigManager = moduleModel.getConfigManager();
+ ProviderConfig providerConfig = moduleConfigManager.getDefaultProvider().get();
Assertions.assertEquals("127.0.0.1", providerConfig.getHost());
- ConsumerConfig consumerConfig = configManager.getDefaultConsumer().get();
+ ConsumerConfig consumerConfig = moduleConfigManager.getDefaultConsumer().get();
Assertions.assertEquals("netty", consumerConfig.getClient());
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
index 3e96c94..6aa8f65 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/boot/configprops/SpringBootMultipleConfigPropsTest.java
@@ -28,9 +28,11 @@ import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.context.ModuleConfigManager;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.ZookeeperMultipleRegistryCenter;
+import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -86,6 +88,9 @@ public class SpringBootMultipleConfigPropsTest {
@Autowired
private ConfigManager configManager;
+ @Autowired
+ private ModuleModel moduleModel;
+
@Test
public void testConfigProps() {
@@ -125,10 +130,11 @@ public class SpringBootMultipleConfigPropsTest {
Assertions.assertEquals("zookeeper://127.0.0.1:2182", reportConfig.getAddress());
Assertions.assertEquals("User", reportConfig.getUsername());
- ProviderConfig providerConfig = configManager.getDefaultProvider().get();
+ ModuleConfigManager moduleConfigManager = moduleModel.getConfigManager();
+ ProviderConfig providerConfig = moduleConfigManager.getDefaultProvider().get();
Assertions.assertEquals("127.0.0.1", providerConfig.getHost());
- ConsumerConfig consumerConfig = configManager.getDefaultConsumer().get();
+ ConsumerConfig consumerConfig = moduleConfigManager.getDefaultConsumer().get();
Assertions.assertEquals("netty", consumerConfig.getClient());
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
index 08cb345..7522ba6 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
@@ -21,8 +21,6 @@ import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.context.annotation.consumer.ConsumerConfiguration;
import org.apache.dubbo.config.spring.context.annotation.provider.DemoServiceImpl;
import org.apache.dubbo.config.spring.context.annotation.provider.ProviderConfiguration;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -72,9 +70,8 @@ public class DubboComponentScanRegistrarTest {
// Test @Transactional is present or not
Assertions.assertNotNull(findAnnotation(beanClass, Transactional.class));
- // reset ConfigManager of provider context
- ApplicationModel.defaultModel().getApplicationConfigManager().destroy();
+ // consumer app
AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
consumerContext.register(ConsumerConfiguration.class);
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
index 71e98d7..2589b1d 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/extension/SpringExtensionInjectorTest.java
@@ -16,15 +16,14 @@
*/
package org.apache.dubbo.config.spring.extension;
-import org.apache.dubbo.common.extension.ExtensionInjector;
-import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.api.HelloService;
+import org.apache.dubbo.config.spring.context.DubboSpringInitializer;
import org.apache.dubbo.config.spring.impl.DemoServiceImpl;
import org.apache.dubbo.config.spring.impl.HelloServiceImpl;
+import org.apache.dubbo.config.spring.util.DubboBeanUtils;
import org.apache.dubbo.rpc.Protocol;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -36,48 +35,38 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class SpringExtensionInjectorTest {
- private SpringExtensionInjector springExtensionFactory = new SpringExtensionInjector();
- private AnnotationConfigApplicationContext context1;
- private AnnotationConfigApplicationContext context2;
@BeforeEach
public void init() {
DubboBootstrap.reset();
-
- // init SpringExtensionInjector
- ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getExtension("spring");
-
- context1 = new AnnotationConfigApplicationContext();
- context1.setDisplayName("Context1");
- context1.register(getClass());
- context1.refresh();
- context2 = new AnnotationConfigApplicationContext();
- context2.setDisplayName("Context2");
- context2.register(BeanForContext2.class);
- context2.refresh();
- SpringExtensionInjector.addApplicationContext(context1);
- SpringExtensionInjector.addApplicationContext(context2);
}
@AfterEach
public void destroy() {
- context1.close();
- context2.close();
- SpringExtensionInjector.clearContexts();
}
@Test
- public void testGetExtensionBySPI() {
- Protocol protocol = springExtensionFactory.getInstance(Protocol.class, "protocol");
- Assertions.assertNull(protocol);
- }
+ public void testSpringInjector() {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
+ try {
+ context.setDisplayName("Context1");
+ context.register(getClass());
+ context.refresh();
- @Test
- public void testGetExtensionByName() {
- DemoService bean = springExtensionFactory.getInstance(DemoService.class, "bean1");
- Assertions.assertNotNull(bean);
- HelloService hello = springExtensionFactory.getInstance(HelloService.class, "hello");
- Assertions.assertNotNull(hello);
+ // mock dubbo spring initialize
+ DubboSpringInitializer.initialize(context);
+
+ SpringExtensionInjector springExtensionInjector = SpringExtensionInjector.get(DubboBeanUtils.getApplicationModel(context));
+ Protocol protocol = springExtensionInjector.getInstance(Protocol.class, "protocol");
+ Assertions.assertNull(protocol);
+
+ DemoService bean = springExtensionInjector.getInstance(DemoService.class, "bean1");
+ Assertions.assertNotNull(bean);
+ HelloService hello = springExtensionInjector.getInstance(HelloService.class, "hello");
+ Assertions.assertNotNull(hello);
+ } finally {
+ context.close();
+ }
}
@Bean("bean1")
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/MethodCallbackImpl.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/MethodCallbackImpl.java
index a23923e..7f9a454 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/MethodCallbackImpl.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/impl/MethodCallbackImpl.java
@@ -23,9 +23,8 @@ import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;
-import java.util.concurrent.atomic.AtomicInteger;
-
import javax.annotation.PostConstruct;
+import java.util.concurrent.atomic.AtomicInteger;
public class MethodCallbackImpl implements MethodCallback {
private String onInvoke1 = "";
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
index 75d6b7a..0da499e 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/issue7003/Issue7003Test.java
@@ -25,7 +25,6 @@ import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
import org.apache.dubbo.rpc.model.ApplicationModel;
-
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@@ -73,7 +72,7 @@ public class Issue7003Test {
Map<String, ReferenceBean> referenceBeanMap = context.getBeansOfType(ReferenceBean.class);
Assertions.assertEquals(1, referenceBeanMap.size());
- Collection<ReferenceConfigBase<?>> references = ApplicationModel.defaultModel().getApplicationConfigManager().getReferences();
+ Collection<ReferenceConfigBase<?>> references = ApplicationModel.defaultModel().getDefaultModule().getConfigManager().getReferences();
Assertions.assertEquals(1, references.size());
} finally {
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
index c2ba2c4..571c8cd 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/propertyconfigurer/consumer/PropertyConfigurerTest.java
@@ -21,8 +21,6 @@ import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.apache.dubbo.config.spring.registrycenter.RegistryCenter;
import org.apache.dubbo.config.spring.registrycenter.ZookeeperSingleRegistryCenter;
... 1898 lines suppressed ...