From 1dfb1147344e012f0e070f67aed2d95a1d8d9377 Mon Sep 17 00:00:00 2001 From: Albumen Kevin Date: Fri, 10 Sep 2021 14:43:34 +0800 Subject: [PATCH] [3.0] Multi Instances Related Refactor (#8737) * Refactor some ExtensionLoader usage * Fix ut * Refactor some ExtensionLoader usage * Introduce Initializer for ScopeModel * Fix ut * Fix ut * Add TCCL Changer * remove some default model usage * remove some default model usage * Fix NPE * Remove Hessian2 TL * Fix NPE * Fix NPE * Fix Shade * Fix DubboBootstrap init * Fix Metadata Serialize * Fix not support multi classloader * Add Multi ClassLoader Test case * Fix UT * add ant * Fix UT * Fix Merge Directory --- .../org/apache/dubbo/rpc/cluster/Cluster.java | 11 +- .../cluster/ClusterScopeModelInitializer.java | 44 ++++ .../dubbo/rpc/cluster/Configurator.java | 3 +- .../apache/dubbo/rpc/cluster/RouterChain.java | 12 +- .../cluster/directory/AbstractDirectory.java | 6 +- .../filter/support/ConsumerContextFilter.java | 9 +- .../filter/support/ZoneAwareFilter.java | 9 +- .../rpc/cluster/merger/MergerFactory.java | 22 +- .../rpc/cluster/router/AbstractRouter.java | 3 +- .../router/state/AbstractStateRouter.java | 11 +- .../support/AbstractClusterInvoker.java | 8 +- .../rpc/cluster/support/ClusterUtils.java | 23 +- .../support/MergeableClusterInvoker.java | 9 +- .../support/wrapper/AbstractCluster.java | 8 +- ...ache.dubbo.rpc.model.ScopeModelInitializer | 1 + .../rpc/cluster/merger/ResultMergerTest.java | 80 +++---- .../rpc/cluster/support/ClusterUtilsTest.java | 20 +- .../common/CommonScopeModelInitializer.java | 42 ++++ .../java/org/apache/dubbo/common/URL.java | 16 ++ .../dubbo/common/bytecode/ClassGenerator.java | 11 +- .../compiler/support/AdaptiveCompiler.java | 12 +- .../common/extension/ExtensionLoader.java | 6 +- .../extension/support/ActivateComparator.java | 9 +- .../dubbo/common/logger/LoggerFactory.java | 6 +- .../apache/dubbo/common/utils/ClassUtils.java | 85 ++++---- .../dubbo/config/ApplicationConfig.java | 2 +- .../dubbo/config/ReferenceConfigBase.java | 4 +- .../dubbo/config/ServiceConfigBase.java | 4 +- .../dubbo/rpc/model/ApplicationModel.java | 6 + .../dubbo/rpc/model/FrameworkModel.java | 9 + .../apache/dubbo/rpc/model/ModuleModel.java | 9 + .../rpc/model/ScopeModelInitializer.java | 30 +++ .../apache/dubbo/rpc/model/ServiceModel.java | 15 +- ...ache.dubbo.rpc.model.ScopeModelInitializer | 1 + .../support/AdaptiveCompilerTest.java | 3 + .../support/ActivateComparatorTest.java | 16 +- .../common/logger/LoggerFactoryTest.java | 4 +- .../apache/dubbo/config/ReferenceConfig.java | 13 +- .../apache/dubbo/config/ServiceConfig.java | 7 +- .../config/bootstrap/DubboBootstrap.java | 15 -- .../config/utils/ConfigValidationUtils.java | 63 +++--- .../java/demo/MultiClassLoaderService.java | 22 ++ .../demo/MultiClassLoaderServiceImpl.java | 35 ++++ .../demo/MultiClassLoaderServiceRequest.java | 22 ++ .../demo/MultiClassLoaderServiceResult.java | 22 ++ .../dubbo/config/AbstractConfigTest.java | 6 +- .../dubbo/config/ReferenceConfigTest.java | 196 +++++++++++++++++- dubbo-distribution/dubbo-all/pom.xml | 6 + .../apache/dubbo/metadata/MetadataInfo.java | 4 +- .../metadata/MetadataServiceExporter.java | 10 +- .../dubbo/metadata/ServiceNameMapping.java | 12 +- .../report/MetadataScopeModelInitializer.java | 41 ++++ ...ache.dubbo.rpc.model.ScopeModelInitializer | 1 + .../dubbo/auth/AccessKeyAuthenticator.java | 10 +- .../dubbo/auth/filter/ConsumerSignFilter.java | 9 +- .../dubbo/auth/filter/ProviderAuthFilter.java | 9 +- .../auth/AccessKeyAuthenticatorTest.java | 9 +- .../auth/filter/ConsumerSignFilterTest.java | 5 +- .../auth/filter/ProviderAuthFilterTest.java | 15 +- .../registry/RegistryFactoryWrapper.java | 3 +- .../dubbo/registry/RegistryNotifier.java | 10 +- .../RegistryScopeModelInitializer.java | 42 ++++ .../DefaultServiceDiscoveryFactory.java | 4 +- .../client/DefaultServiceInstance.java | 1 + .../client/ServiceDiscoveryFactory.java | 4 +- .../client/ServiceDiscoveryRegistry.java | 2 +- .../ServiceDiscoveryRegistryDirectory.java | 9 +- .../registry/client/ServiceInstance.java | 7 + .../ServiceInstancesChangedListener.java | 6 +- .../metadata/MetadataServiceNameMapping.java | 13 +- .../client/metadata/MetadataUtils.java | 6 +- .../ServiceInstanceMetadataUtils.java | 2 +- .../client/migration/MigrationInvoker.java | 11 +- .../AbstractConfiguratorListener.java | 5 +- .../integration/DynamicDirectory.java | 10 +- .../integration/RegistryDirectory.java | 12 +- .../integration/RegistryProtocol.java | 4 +- .../support/CacheableFailbackRegistry.java | 6 +- ...ache.dubbo.rpc.model.ScopeModelInitializer | 1 + .../client/ServiceDiscoveryRegistryTest.java | 102 +++++---- .../MetadataServiceNameMappingTest.java | 2 +- .../migration/model/MigrationRuleTest.java | 3 +- .../registry/dns/DNSServiceDiscoveryTest.java | 2 +- .../registry/multiple/MultipleRegistry.java | 6 +- .../dubbo/registry/nacos/NacosRegistry.java | 2 +- .../dubbo/registry/xds/util/XdsChannel.java | 3 +- .../registry/zookeeper/ZookeeperRegistry.java | 2 +- ...ookeeperServiceDiscoveryChangeWatcher.java | 2 +- .../apache/dubbo/remoting/Transporters.java | 9 +- .../MultiplexProtocolConnectionManager.java | 10 +- .../dubbo/remoting/api/SslContexts.java | 5 +- .../dubbo/remoting/exchange/Exchangers.java | 7 +- .../remoting/transport/AbstractClient.java | 4 +- .../remoting/transport/AbstractServer.java | 4 +- .../remoting/transport/CodecSupport.java | 2 +- .../transport/dispatcher/ChannelHandlers.java | 3 +- .../java/org/apache/dubbo/rpc/Invocation.java | 11 +- .../dubbo/rpc/filter/GenericFilter.java | 9 +- .../dubbo/rpc/protocol/AbstractInvoker.java | 4 +- .../apache/dubbo/rpc/support/MockInvoker.java | 13 +- .../dubbo/rpc/support/MockInvokerTest.java | 11 +- .../protocol/dubbo/CallbackServiceCodec.java | 3 +- .../dubbo/DecodeableRpcInvocation.java | 28 +++ .../protocol/dubbo/DecodeableRpcResult.java | 4 + .../dubbo/rpc/protocol/dubbo/DubboCodec.java | 4 - .../rpc/protocol/dubbo/DubboCodecSupport.java | 5 +- .../rpc/protocol/dubbo/DubboProtocol.java | 12 +- .../dubbo/decode/DubboTelnetDecodeTest.java | 9 +- .../rpc/protocol/grpc/GrpcOptionsUtils.java | 13 +- .../rpc/protocol/injvm/InjvmInvoker.java | 4 +- .../protocol/tri/AbstractServerStream.java | 2 +- .../DefaultMultipleSerialization.java | 5 +- .../hessian2/Hessian2ObjectInput.java | 21 +- .../hessian2/Hessian2ObjectOutput.java | 11 +- .../hessian2/Hessian2SerializerFactory.java | 5 - .../AbstractHessian2FactoryInitializer.java | 21 +- 116 files changed, 1148 insertions(+), 474 deletions(-) create mode 100644 dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterScopeModelInitializer.java create mode 100644 dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java create mode 100644 dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelInitializer.java create mode 100644 dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer create mode 100644 dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderService.java create mode 100644 dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceImpl.java create mode 100644 dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceRequest.java create mode 100644 dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceResult.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataScopeModelInitializer.java create mode 100644 dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer create mode 100644 dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java create mode 100644 dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java index 04cc57339f..d6d4d5e6ce 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Cluster.java @@ -17,11 +17,12 @@ package org.apache.dubbo.rpc.cluster; import org.apache.dubbo.common.extension.Adaptive; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; /** * Cluster. (SPI, Singleton, ThreadSafe) @@ -46,14 +47,14 @@ public interface Cluster { @Adaptive Invoker join(Directory directory) throws RpcException; - static Cluster getCluster(String name) { - return getCluster(name, true); + static Cluster getCluster(ScopeModel scopeModel, String name) { + return getCluster(scopeModel, name, true); } - static Cluster getCluster(String name, boolean wrap) { + static Cluster getCluster(ScopeModel scopeModel, String name, boolean wrap) { if (StringUtils.isEmpty(name)) { name = Cluster.DEFAULT; } - return ExtensionLoader.getExtensionLoader(Cluster.class).getExtension(name, wrap); + return ScopeModelUtil.getApplicationModel(scopeModel).getExtensionLoader(Cluster.class).getExtension(name, wrap); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterScopeModelInitializer.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterScopeModelInitializer.java new file mode 100644 index 0000000000..8e39fa5311 --- /dev/null +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/ClusterScopeModelInitializer.java @@ -0,0 +1,44 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.cluster; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.rpc.cluster.merger.MergerFactory; +import org.apache.dubbo.rpc.cluster.support.ClusterUtils; +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 ClusterScopeModelInitializer implements ScopeModelInitializer { + @Override + public void initializeFrameworkModel(FrameworkModel frameworkModel) { + + } + + @Override + public void initializeApplicationModel(ApplicationModel applicationModel) { + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + beanFactory.registerBean(MergerFactory.class); + beanFactory.registerBean(ClusterUtils.class); + } + + @Override + public void initializeModuleModel(ModuleModel moduleModel) { + + } +} diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java index 3b1d25e5c3..1f1df9c200 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.cluster; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.CollectionUtils; import java.util.ArrayList; @@ -74,7 +73,7 @@ public interface Configurator extends Comparable { return Optional.empty(); } - ConfiguratorFactory configuratorFactory = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class) + ConfiguratorFactory configuratorFactory = urls.get(0).getOrDefaultApplicationModel().getExtensionLoader(ConfiguratorFactory.class) .getAdaptiveExtension(); List configurators = new ArrayList<>(urls.size()); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java index 3500ac29a5..c2adc63482 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/RouterChain.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; -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; @@ -71,8 +70,7 @@ public class RouterChain { private List builtinStateRouters = Collections.emptyList(); private List stateRouters = Collections.emptyList(); - private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class) - .getDefaultExtension(); + private final ExecutorRepository executorRepository; protected URL url; @@ -90,8 +88,10 @@ public class RouterChain { } private RouterChain(URL url) { + executorRepository = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class) + .getDefaultExtension(); loopPool = executorRepository.nextExecutorExecutor(); - List extensionFactories = ExtensionLoader.getExtensionLoader(RouterFactory.class) + List extensionFactories = url.getOrDefaultApplicationModel().getExtensionLoader(RouterFactory.class) .getActivateExtension(url, ROUTER_KEY); List routers = extensionFactories.stream() @@ -101,8 +101,8 @@ public class RouterChain { initWithRouters(routers); - List extensionStateRouterFactories = ExtensionLoader.getExtensionLoader( - StateRouterFactory.class) + List extensionStateRouterFactories = url.getOrDefaultApplicationModel() + .getExtensionLoader(StateRouterFactory.class) .getActivateExtension(url, STATE_ROUTER_KEY); List stateRouters = extensionStateRouterFactories.stream() diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java index b8cb39a555..6f87362ba6 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java @@ -27,6 +27,7 @@ import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.cluster.Router; import org.apache.dubbo.rpc.cluster.RouterChain; import org.apache.dubbo.rpc.cluster.support.ClusterUtils; +import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.Collections; import java.util.List; @@ -84,7 +85,8 @@ public abstract class AbstractDirectory implements Directory { } // remove some local only parameters - this.queryMap = ClusterUtils.mergeLocalParams(queryMap); + ApplicationModel applicationModel = url.getOrDefaultApplicationModel(); + this.queryMap = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeLocalParams(queryMap); if (consumerUrl == null) { String host = StringUtils.isNotEmpty(queryMap.get("register.ip")) ? queryMap.get("register.ip") : this.url.getHost(); @@ -98,7 +100,7 @@ public abstract class AbstractDirectory implements Directory { .setPath(path == null ? queryMap.get(INTERFACE_KEY) : path); if (isUrlFromRegistry) { // reserve parameters if url is already a consumer url - consumerUrlFrom = consumerUrlFrom.clearParameters(); + consumerUrlFrom = consumerUrlFrom.clearParameters().setServiceModel(url.getServiceModel()).setScopeModel(url.getScopeModel()); } this.consumerUrl = consumerUrlFrom.addParameters(queryMap).removeAttribute(MONITOR_KEY); } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java index a931e480eb..c74b9a4250 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ConsumerContextFilter.java @@ -31,6 +31,7 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.RpcInvocation; import org.apache.dubbo.rpc.TimeoutCountDown; import org.apache.dubbo.rpc.cluster.filter.ClusterFilter; +import org.apache.dubbo.rpc.model.ApplicationModel; import java.util.Map; import java.util.Set; @@ -49,6 +50,12 @@ import static org.apache.dubbo.common.constants.CommonConstants.TIME_COUNTDOWN_K @Activate(group = CONSUMER, order = -10000) public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Listener { + private ApplicationModel applicationModel; + + public ConsumerContextFilter(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } + @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { RpcContext.getServiceContext() @@ -61,7 +68,7 @@ public class ConsumerContextFilter implements ClusterFilter, ClusterFilter.Liste ((RpcInvocation) invocation).setInvoker(invoker); } - ExtensionLoader selectorExtensionLoader = ExtensionLoader.getExtensionLoader(PenetrateAttachmentSelector.class); + ExtensionLoader selectorExtensionLoader = applicationModel.getExtensionLoader(PenetrateAttachmentSelector.class); Set supportedSelectors = selectorExtensionLoader.getSupportedExtensions(); if (CollectionUtils.isNotEmpty(supportedSelectors)) { for (String supportedSelector : supportedSelectors) { diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ZoneAwareFilter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ZoneAwareFilter.java index c31f01c69f..9465af5b67 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ZoneAwareFilter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/filter/support/ZoneAwareFilter.java @@ -27,6 +27,7 @@ import org.apache.dubbo.rpc.RpcContext; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.ZoneDetector; import org.apache.dubbo.rpc.cluster.filter.ClusterFilter; +import org.apache.dubbo.rpc.model.ApplicationModel; import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE; import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_FORCE; @@ -39,12 +40,18 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_ZONE_ @Activate(group = CommonConstants.CONSUMER, value = "cluster:zone-aware") public class ZoneAwareFilter implements ClusterFilter { + private ApplicationModel applicationModel; + + public ZoneAwareFilter(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } + @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { RpcContext rpcContext = RpcContext.getClientAttachment(); String zone = (String) rpcContext.getAttachment(REGISTRY_ZONE); String force = (String) rpcContext.getAttachment(REGISTRY_ZONE_FORCE); - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(ZoneDetector.class); + ExtensionLoader loader = applicationModel.getExtensionLoader(ZoneDetector.class); if (StringUtils.isEmpty(zone) && loader.hasExtension("default")) { ZoneDetector detector = loader.getExtension("default"); zone = detector.getZoneOfCurrentRequest(invocation); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/merger/MergerFactory.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/merger/MergerFactory.java index 74789bbe91..0784ae0709 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/merger/MergerFactory.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/merger/MergerFactory.java @@ -17,18 +17,24 @@ package org.apache.dubbo.rpc.cluster.merger; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.rpc.cluster.Merger; +import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; -public class MergerFactory { +public class MergerFactory implements ScopeModelAware { - private static final ConcurrentMap, Merger> MERGER_CACHE = - new ConcurrentHashMap, Merger>(); + private ConcurrentMap, Merger> MERGER_CACHE = new ConcurrentHashMap, Merger>(); + private ScopeModel scopeModel; + + @Override + public void setScopeModel(ScopeModel scopeModel) { + this.scopeModel = scopeModel; + } /** * Find the merger according to the returnType class, the merger will @@ -38,7 +44,7 @@ public class MergerFactory { * @return the merger which merges an array of returnType into one, return null if not exist * @throws IllegalArgumentException if returnType is null */ - public static Merger getMerger(Class returnType) { + public Merger getMerger(Class returnType) { if (returnType == null) { throw new IllegalArgumentException("returnType is null"); } @@ -64,11 +70,11 @@ public class MergerFactory { return result; } - static void loadMergers() { - Set names = ExtensionLoader.getExtensionLoader(Merger.class) + private void loadMergers() { + Set names = scopeModel.getExtensionLoader(Merger.class) .getSupportedExtensions(); for (String name : names) { - Merger m = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(name); + Merger m = scopeModel.getExtensionLoader(Merger.class).getExtension(name); MERGER_CACHE.putIfAbsent(ReflectUtils.getGenericClass(m.getClass()), m); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java index 1e3eb08c45..c9a326710b 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/AbstractRouter.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.cluster.router; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.cluster.Router; import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository; @@ -29,7 +28,7 @@ public abstract class AbstractRouter implements Router { private GovernanceRuleRepository ruleRepository; public AbstractRouter(URL url) { - this.ruleRepository = ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension(); + this.ruleRepository = url.getOrDefaultApplicationModel().getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension(); this.url = url; } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/AbstractStateRouter.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/AbstractStateRouter.java index fc5e3624ff..5dffccc449 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/AbstractStateRouter.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/state/AbstractStateRouter.java @@ -16,18 +16,17 @@ */ package org.apache.dubbo.rpc.cluster.router.state; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.atomic.AtomicReference; - import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.cluster.RouterChain; import org.apache.dubbo.rpc.cluster.governance.GovernanceRuleRepository; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicReference; + /*** * The abstract class of StateRoute. * @since 3.0 @@ -42,7 +41,7 @@ public abstract class AbstractStateRouter implements StateRouter { protected GovernanceRuleRepository ruleRepository; public AbstractStateRouter(URL url, RouterChain chain) { - this.ruleRepository = ExtensionLoader.getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension(); + this.ruleRepository = url.getOrDefaultApplicationModel().getExtensionLoader(GovernanceRuleRepository.class).getDefaultExtension(); this.chain = chain; this.url = url; } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java index 2e80670bd0..0c0d404209 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java @@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster.support; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; @@ -32,6 +31,8 @@ import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.cluster.ClusterInvoker; import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.cluster.LoadBalance; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.support.RpcUtils; import java.util.ArrayList; @@ -338,14 +339,15 @@ public abstract class AbstractClusterInvoker implements ClusterInvoker { * @return LoadBalance instance. if not need init, return null. */ protected LoadBalance initLoadBalance(List> invokers, Invocation invocation) { + ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(invocation.getModuleModel()); if (CollectionUtils.isNotEmpty(invokers)) { - return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension( + return applicationModel.getExtensionLoader(LoadBalance.class).getExtension( invokers.get(0).getUrl().getMethodParameter( RpcUtils.getMethodName(invocation), LOADBALANCE_KEY, DEFAULT_LOADBALANCE ) ); } else { - return ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE); + return applicationModel.getExtensionLoader(LoadBalance.class).getExtension(DEFAULT_LOADBALANCE); } } diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java index e2aa61586c..845020ef20 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/ClusterUtils.java @@ -17,9 +17,10 @@ package org.apache.dubbo.rpc.cluster.support; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.cluster.ProviderURLMergeProcessor; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.Map; @@ -29,33 +30,37 @@ import static org.apache.dubbo.common.constants.CommonConstants.URL_MERGE_PROCES /** * ClusterUtils */ -public class ClusterUtils { +public class ClusterUtils implements ScopeModelAware { - private ClusterUtils() { + private ApplicationModel applicationModel; + + @Override + public void setApplicationModel(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; } - public static URL mergeUrl(URL remoteUrl, Map localMap) { + public URL mergeUrl(URL remoteUrl, Map localMap) { String ump = localMap.get(URL_MERGE_PROCESSOR_KEY); ProviderURLMergeProcessor providerURLMergeProcessor; if (StringUtils.isNotEmpty(ump)) { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); + providerURLMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); } else { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); + providerURLMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); } return providerURLMergeProcessor.mergeUrl(remoteUrl, localMap); } - public static Map mergeLocalParams(Map localMap) { + public Map mergeLocalParams(Map localMap) { String ump = localMap.get(URL_MERGE_PROCESSOR_KEY); ProviderURLMergeProcessor providerURLMergeProcessor; if (StringUtils.isNotEmpty(ump)) { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); + providerURLMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension(ump); } else { - providerURLMergeProcessor = ExtensionLoader.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); + providerURLMergeProcessor = applicationModel.getExtensionLoader(ProviderURLMergeProcessor.class).getExtension("default"); } return providerURLMergeProcessor.mergeLocalParams(localMap); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java index 4c78ba8e07..3ef72a3884 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/MergeableClusterInvoker.java @@ -16,7 +16,6 @@ */ package org.apache.dubbo.rpc.cluster.support; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ConfigUtils; @@ -30,6 +29,8 @@ import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.cluster.LoadBalance; import org.apache.dubbo.rpc.cluster.Merger; import org.apache.dubbo.rpc.cluster.merger.MergerFactory; +import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.lang.reflect.Array; import java.lang.reflect.Method; @@ -150,10 +151,12 @@ public class MergeableClusterInvoker extends AbstractClusterInvoker { } } else { Merger resultMerger; + ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(invocation.getModuleModel().getApplicationModel()); + if (ConfigUtils.isDefault(merger)) { - resultMerger = MergerFactory.getMerger(returnType); + resultMerger = applicationModel.getBeanFactory().getBean(MergerFactory.class).getMerger(returnType); } else { - resultMerger = ExtensionLoader.getExtensionLoader(Merger.class).getExtension(merger); + resultMerger = applicationModel.getExtensionLoader(Merger.class).getExtension(merger); } if (resultMerger != null) { List rets = new ArrayList(resultList.size()); diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java index fe08884600..923ca4e8c2 100644 --- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java +++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/wrapper/AbstractCluster.java @@ -19,7 +19,6 @@ package org.apache.dubbo.rpc.cluster.support.wrapper; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; @@ -34,6 +33,7 @@ import org.apache.dubbo.rpc.cluster.filter.FilterChainBuilder; import org.apache.dubbo.rpc.cluster.filter.InvocationInterceptorBuilder; import org.apache.dubbo.rpc.cluster.interceptor.ClusterInterceptor; import org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.List; @@ -62,7 +62,7 @@ public abstract class AbstractCluster implements Cluster { } private AbstractClusterInvoker buildInterceptorInvoker(AbstractClusterInvoker invoker) { - List builders = ExtensionLoader.getExtensionLoader(InvocationInterceptorBuilder.class).getActivateExtensions(); + List builders = ScopeModelUtil.getApplicationModel(invoker.getUrl().getScopeModel()).getExtensionLoader(InvocationInterceptorBuilder.class).getActivateExtensions(); if (CollectionUtils.isEmpty(builders)) { return invoker; } @@ -75,7 +75,7 @@ public abstract class AbstractCluster implements Cluster { private ClusterInvoker filterInvoker; public ClusterFilterInvoker(AbstractClusterInvoker invoker) { - List builders = ExtensionLoader.getExtensionLoader(FilterChainBuilder.class).getActivateExtensions(); + List builders = ScopeModelUtil.getApplicationModel(invoker.getUrl().getScopeModel()).getExtensionLoader(FilterChainBuilder.class).getActivateExtensions(); if (CollectionUtils.isEmpty(builders)) { filterInvoker = invoker; } else { @@ -176,7 +176,7 @@ public abstract class AbstractCluster implements Cluster { @Deprecated private ClusterInvoker build27xCompatibleClusterInterceptors(AbstractClusterInvoker clusterInvoker, AbstractClusterInvoker last) { - List interceptors = ExtensionLoader.getExtensionLoader(ClusterInterceptor.class).getActivateExtensions(); + List interceptors = ScopeModelUtil.getApplicationModel(clusterInvoker.getUrl().getScopeModel()).getExtensionLoader(ClusterInterceptor.class).getActivateExtensions(); if (!interceptors.isEmpty()) { for (int i = interceptors.size() - 1; i >= 0; i--) { diff --git a/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer new file mode 100644 index 0000000000..1718c117cb --- /dev/null +++ b/dubbo-cluster/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer @@ -0,0 +1 @@ +dubbo-cluster=org.apache.dubbo.rpc.cluster.ClusterScopeModelInitializer 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 815ad57ceb..ef921bbdc7 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 @@ -16,7 +16,10 @@ */ 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; import java.lang.reflect.Array; @@ -28,6 +31,13 @@ import java.util.Map; import java.util.Set; public class ResultMergerTest { + private MergerFactory mergerFactory; + + @BeforeEach + public void setup() { + mergerFactory = new MergerFactory(); + mergerFactory.setScopeModel(ApplicationModel.defaultModel()); + } /** * MergerFactory test @@ -35,7 +45,7 @@ public class ResultMergerTest { @Test public void testMergerFactoryIllegalArgumentException() { try { - MergerFactory.getMerger(null); + mergerFactory.getMerger(null); Assertions.fail("expected IllegalArgumentException for null argument"); } catch (IllegalArgumentException exception) { Assertions.assertEquals("returnType is null", exception.getMessage()); @@ -78,7 +88,7 @@ public class ResultMergerTest { Integer[] intArray2 = {4, 5, 6}; Integer[] intArray3 = {7}; // trigger ArrayMerger - result = MergerFactory.getMerger(Integer[].class).merge(intArray1, intArray2, intArray3, null); + result = mergerFactory.getMerger(Integer[].class).merge(intArray1, intArray2, intArray3, null); Assertions.assertTrue(result.getClass().isArray()); Assertions.assertEquals(7, Array.getLength(result)); Assertions.assertSame(Integer.class, result.getClass().getComponentType()); @@ -103,17 +113,17 @@ public class ResultMergerTest { public void testBooleanArrayMerger() { boolean[] arrayOne = {true, false}; boolean[] arrayTwo = {false}; - boolean[] result = MergerFactory.getMerger(boolean[].class).merge(arrayOne, arrayTwo, null); + boolean[] result = mergerFactory.getMerger(boolean[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(3, result.length); boolean[] mergedResult = {true, false, false}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i]); } - result = MergerFactory.getMerger(boolean[].class).merge(null); + result = mergerFactory.getMerger(boolean[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(boolean[].class).merge(null, null); + result = mergerFactory.getMerger(boolean[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -124,17 +134,17 @@ public class ResultMergerTest { public void testByteArrayMerger() { byte[] arrayOne = {1, 2}; byte[] arrayTwo = {1, 32}; - byte[] result = MergerFactory.getMerger(byte[].class).merge(arrayOne, arrayTwo, null); + byte[] result = mergerFactory.getMerger(byte[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); byte[] mergedResult = {1, 2, 1, 32}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i]); } - result = MergerFactory.getMerger(byte[].class).merge(null); + result = mergerFactory.getMerger(byte[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(byte[].class).merge(null, null); + result = mergerFactory.getMerger(byte[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -145,17 +155,17 @@ public class ResultMergerTest { public void testCharArrayMerger() { char[] arrayOne = "hello".toCharArray(); char[] arrayTwo = "world".toCharArray(); - char[] result = MergerFactory.getMerger(char[].class).merge(arrayOne, arrayTwo, null); + char[] result = mergerFactory.getMerger(char[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(10, result.length); char[] mergedResult = "helloworld".toCharArray(); for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i]); } - result = MergerFactory.getMerger(char[].class).merge(null); + result = mergerFactory.getMerger(char[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(char[].class).merge(null, null); + result = mergerFactory.getMerger(char[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -166,17 +176,17 @@ public class ResultMergerTest { public void testDoubleArrayMerger() { double[] arrayOne = {1.2d, 3.5d}; double[] arrayTwo = {2d, 34d}; - double[] result = MergerFactory.getMerger(double[].class).merge(arrayOne, arrayTwo, null); + double[] result = mergerFactory.getMerger(double[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); double[] mergedResult = {1.2d, 3.5d, 2d, 34d}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i], 0.0); } - result = MergerFactory.getMerger(double[].class).merge(null); + result = mergerFactory.getMerger(double[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(double[].class).merge(null, null); + result = mergerFactory.getMerger(double[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -187,17 +197,17 @@ public class ResultMergerTest { public void testFloatArrayMerger() { float[] arrayOne = {1.2f, 3.5f}; float[] arrayTwo = {2f, 34f}; - float[] result = MergerFactory.getMerger(float[].class).merge(arrayOne, arrayTwo, null); + float[] result = mergerFactory.getMerger(float[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); double[] mergedResult = {1.2f, 3.5f, 2f, 34f}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i], 0.0); } - result = MergerFactory.getMerger(float[].class).merge(null); + result = mergerFactory.getMerger(float[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(float[].class).merge(null, null); + result = mergerFactory.getMerger(float[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -208,17 +218,17 @@ public class ResultMergerTest { public void testIntArrayMerger() { int[] arrayOne = {1, 2}; int[] arrayTwo = {2, 34}; - int[] result = MergerFactory.getMerger(int[].class).merge(arrayOne, arrayTwo, null); + int[] result = mergerFactory.getMerger(int[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); double[] mergedResult = {1, 2, 2, 34}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i], 0.0); } - result = MergerFactory.getMerger(int[].class).merge(null); + result = mergerFactory.getMerger(int[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(int[].class).merge(null, null); + result = mergerFactory.getMerger(int[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -237,7 +247,7 @@ public class ResultMergerTest { add("4"); }}; - List result = MergerFactory.getMerger(List.class).merge(list1, list2, null); + List result = mergerFactory.getMerger(List.class).merge(list1, list2, null); Assertions.assertEquals(5, result.size()); ArrayList expected = new ArrayList() {{ add(null); @@ -248,10 +258,10 @@ public class ResultMergerTest { }}; Assertions.assertEquals(expected, result); - result = MergerFactory.getMerger(List.class).merge(null); + result = mergerFactory.getMerger(List.class).merge(null); Assertions.assertEquals(0, result.size()); - result = MergerFactory.getMerger(List.class).merge(null, null); + result = mergerFactory.getMerger(List.class).merge(null, null); Assertions.assertEquals(0, result.size()); } @@ -268,7 +278,7 @@ public class ResultMergerTest { put("3333", 3232); put("444", 2323); }}; - Map result = MergerFactory.getMerger(Map.class).merge(mapOne, mapTwo, null); + Map result = mergerFactory.getMerger(Map.class).merge(mapOne, mapTwo, null); Assertions.assertEquals(4, result.size()); Map mergedResult = new HashMap() {{ put("11", 222); @@ -278,10 +288,10 @@ public class ResultMergerTest { }}; Assertions.assertEquals(mergedResult, result); - result = MergerFactory.getMerger(Map.class).merge(null); + result = mergerFactory.getMerger(Map.class).merge(null); Assertions.assertEquals(0, result.size()); - result = MergerFactory.getMerger(Map.class).merge(null, null); + result = mergerFactory.getMerger(Map.class).merge(null, null); Assertions.assertEquals(0, result.size()); } @@ -292,17 +302,17 @@ public class ResultMergerTest { public void testLongArrayMerger() { long[] arrayOne = {1L, 2L}; long[] arrayTwo = {2L, 34L}; - long[] result = MergerFactory.getMerger(long[].class).merge(arrayOne, arrayTwo, null); + long[] result = mergerFactory.getMerger(long[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); double[] mergedResult = {1L, 2L, 2L, 34L}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i], 0.0); } - result = MergerFactory.getMerger(long[].class).merge(null); + result = mergerFactory.getMerger(long[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(long[].class).merge(null, null); + result = mergerFactory.getMerger(long[].class).merge(null, null); Assertions.assertEquals(0, result.length); } @@ -322,7 +332,7 @@ public class ResultMergerTest { add("3"); }}; - Set result = MergerFactory.getMerger(Set.class).merge(set1, set2, null); + Set result = mergerFactory.getMerger(Set.class).merge(set1, set2, null); Assertions.assertEquals(4, result.size()); Assertions.assertEquals(new HashSet() { @@ -334,10 +344,10 @@ public class ResultMergerTest { } }, result); - result = MergerFactory.getMerger(Set.class).merge(null); + result = mergerFactory.getMerger(Set.class).merge(null); Assertions.assertEquals(0, result.size()); - result = MergerFactory.getMerger(Set.class).merge(null, null); + result = mergerFactory.getMerger(Set.class).merge(null, null); Assertions.assertEquals(0, result.size()); } @@ -348,17 +358,17 @@ public class ResultMergerTest { public void testShortArrayMerger() { short[] arrayOne = {1, 2}; short[] arrayTwo = {2, 34}; - short[] result = MergerFactory.getMerger(short[].class).merge(arrayOne, arrayTwo, null); + short[] result = mergerFactory.getMerger(short[].class).merge(arrayOne, arrayTwo, null); Assertions.assertEquals(4, result.length); double[] mergedResult = {1, 2, 2, 34}; for (int i = 0; i < mergedResult.length; i++) { Assertions.assertEquals(mergedResult[i], result[i], 0.0); } - result = MergerFactory.getMerger(short[].class).merge(null); + result = mergerFactory.getMerger(short[].class).merge(null); Assertions.assertEquals(0, result.length); - result = MergerFactory.getMerger(short[].class).merge(null, null); + result = mergerFactory.getMerger(short[].class).merge(null, null); Assertions.assertEquals(0, result.length); } } 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 19c8b714db..8e897dfa79 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 @@ -18,8 +18,10 @@ 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; import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY; @@ -46,6 +48,14 @@ import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY; public class ClusterUtilsTest { + private ClusterUtils clusterUtils; + + @BeforeEach + public void setup() { + clusterUtils = new ClusterUtils(); + clusterUtils.setApplicationModel(ApplicationModel.defaultModel()); + } + @Test public void testMergeUrl() throws Exception { URL providerURL = URL.valueOf("dubbo://localhost:55555"); @@ -82,7 +92,7 @@ public class ClusterUtilsTest { .addParameter(TAG_KEY,"UUU") .build(); - URL url = ClusterUtils.mergeUrl(providerURL, consumerURL.getParameters()); + URL url = clusterUtils.mergeUrl(providerURL, consumerURL.getParameters()); Assertions.assertFalse(url.hasParameter(THREADS_KEY)); Assertions.assertFalse(url.hasParameter(DEFAULT_KEY_PREFIX + THREADS_KEY)); @@ -120,7 +130,7 @@ public class ClusterUtilsTest { "&methods=local&tag=local×tamp=local"); URL remoteURL = URL.valueOf("dubbo://localhost:20880/DemoService?version=remote&group=remote&dubbo=remote&release=remote" + "&methods=remote&tag=remote×tamp=remote"); - URL mergedUrl = ClusterUtils.mergeUrl(remoteURL, localURL.getParameters()); + URL mergedUrl = clusterUtils.mergeUrl(remoteURL, localURL.getParameters()); Assertions.assertEquals(remoteURL.getVersion(), mergedUrl.getVersion()); Assertions.assertEquals(remoteURL.getGroup(), mergedUrl.getGroup()); @@ -134,7 +144,7 @@ public class ClusterUtilsTest { localURL = URL.valueOf("dubbo://localhost:20880/DemoService?version=local&group=local&dubbo=local&release=local" + "&methods=local&tag=local×tamp=local"); remoteURL = URL.valueOf("dubbo://localhost:20880/DemoService"); - mergedUrl = ClusterUtils.mergeUrl(remoteURL, localURL.getParameters()); + mergedUrl = clusterUtils.mergeUrl(remoteURL, localURL.getParameters()); Assertions.assertEquals(mergedUrl.getVersion(),localURL.getVersion()); Assertions.assertEquals(mergedUrl.getGroup(),localURL.getGroup()); @@ -148,7 +158,7 @@ public class ClusterUtilsTest { localURL = URL.valueOf("dubbo://localhost:20880/DemoService?version=local&group=local&dubbo=local&release=local" + "&methods=local&tag=local×tamp=local"); remoteURL = URL.valueOf("dubbo://localhost:20880/DemoService?key=value"); - mergedUrl = ClusterUtils.mergeUrl(remoteURL, localURL.getParameters()); + mergedUrl = clusterUtils.mergeUrl(remoteURL, localURL.getParameters()); Assertions.assertEquals(mergedUrl.getVersion(),localURL.getVersion()); Assertions.assertEquals(mergedUrl.getGroup(),localURL.getGroup()); @@ -161,7 +171,7 @@ public class ClusterUtilsTest { // present in both local and remote, uses local url params localURL = URL.valueOf("dubbo://localhost:20880/DemoService?loadbalance=local&timeout=1000&cluster=local"); remoteURL = URL.valueOf("dubbo://localhost:20880/DemoService?loadbalance=remote&timeout=2000&cluster=remote"); - mergedUrl = ClusterUtils.mergeUrl(remoteURL, localURL.getParameters()); + mergedUrl = clusterUtils.mergeUrl(remoteURL, localURL.getParameters()); Assertions.assertEquals(localURL.getParameter(CLUSTER_KEY), mergedUrl.getParameter(CLUSTER_KEY)); Assertions.assertEquals(localURL.getParameter(TIMEOUT_KEY), mergedUrl.getParameter(TIMEOUT_KEY)); 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 new file mode 100644 index 0000000000..8caab8188d --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/CommonScopeModelInitializer.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.common; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService; +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 { + @Override + public void initializeFrameworkModel(FrameworkModel frameworkModel) { + + } + + @Override + public void initializeApplicationModel(ApplicationModel applicationModel) { + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + beanFactory.registerBean(FrameworkStatusReportService.class); + } + + @Override + public void initializeModuleModel(ModuleModel moduleModel) { + + } +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java index dd40e7649d..2a4cdd08df 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java @@ -30,7 +30,11 @@ import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.common.utils.LRUCache; import org.apache.dubbo.common.utils.NetUtils; import org.apache.dubbo.common.utils.StringUtils; +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 org.apache.dubbo.rpc.model.ServiceModel; import java.io.Serializable; @@ -556,6 +560,18 @@ class URL implements Serializable { return (ScopeModel) getAttribute(CommonConstants.SCOPE_MODEL); } + public FrameworkModel getOrDefaultFrameworkModel() { + return ScopeModelUtil.getFrameworkModel(getScopeModel()); + } + + public ApplicationModel getOrDefaultApplicationModel() { + return ScopeModelUtil.getApplicationModel(getScopeModel()); + } + + public ModuleModel getOrDefaultModuleModel() { + return ScopeModelUtil.getModuleModel(getScopeModel()); + } + public URL setServiceModel(ServiceModel serviceModel) { return putAttribute(CommonConstants.SERVICE_MODEL, serviceModel); } 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 48a1c56cb8..ed2ff6bdc8 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 @@ -17,7 +17,6 @@ package org.apache.dubbo.common.bytecode; import org.apache.dubbo.common.utils.ArrayUtils; -import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.ReflectUtils; import org.apache.dubbo.common.utils.StringUtils; @@ -60,6 +59,7 @@ public final class ClassGenerator { private List mFields; private List mConstructors; private List mMethods; + private ClassLoader mClassLoader; private Map mCopyMethods; // private Map> mCopyConstructors; // private boolean mDefaultConstructor = false; @@ -67,16 +67,17 @@ public final class ClassGenerator { private ClassGenerator() { } - private ClassGenerator(ClassPool pool) { + private ClassGenerator(ClassLoader classLoader, ClassPool pool) { + mClassLoader = classLoader; mPool = pool; } public static ClassGenerator newInstance() { - return new ClassGenerator(getClassPool(Thread.currentThread().getContextClassLoader())); + return new ClassGenerator(Thread.currentThread().getContextClassLoader(), getClassPool(Thread.currentThread().getContextClassLoader())); } public static ClassGenerator newInstance(ClassLoader loader) { - return new ClassGenerator(getClassPool(loader)); + return new ClassGenerator(loader, getClassPool(loader)); } public static boolean isDynamicClass(Class cl) { @@ -282,7 +283,7 @@ public final class ClassGenerator { } public Class toClass() { - return toClass(ClassUtils.getClassLoader(ClassGenerator.class), + return toClass(mClassLoader, getClass().getProtectionDomain()); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java index ccc8db5402..9e6771d033 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/compiler/support/AdaptiveCompiler.java @@ -19,12 +19,20 @@ package org.apache.dubbo.common.compiler.support; import org.apache.dubbo.common.compiler.Compiler; import org.apache.dubbo.common.extension.Adaptive; import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.rpc.model.FrameworkModel; +import org.apache.dubbo.rpc.model.ScopeModelAware; /** * AdaptiveCompiler. (SPI, Singleton, ThreadSafe) */ @Adaptive -public class AdaptiveCompiler implements Compiler { +public class AdaptiveCompiler implements Compiler, ScopeModelAware { + private FrameworkModel frameworkModel; + + @Override + public void setFrameworkModel(FrameworkModel frameworkModel) { + this.frameworkModel = frameworkModel; + } private static volatile String DEFAULT_COMPILER; @@ -35,7 +43,7 @@ public class AdaptiveCompiler implements Compiler { @Override public Class compile(String code, ClassLoader classLoader) { Compiler compiler; - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(Compiler.class); + ExtensionLoader loader = frameworkModel.getExtensionLoader(Compiler.class); String name = DEFAULT_COMPILER; // copy reference if (name != null && name.length() > 0) { compiler = loader.getExtension(name); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java index 41349daf6c..c77ea58722 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/ExtensionLoader.java @@ -129,6 +129,7 @@ public class ExtensionLoader { private List extensionPostProcessors; private InstantiationStrategy instantiationStrategy; private Environment environment; + private ActivateComparator activateComparator; public static void setLoadingStrategies(LoadingStrategy... strategies) { if (ArrayUtils.isNotEmpty(strategies)) { @@ -167,6 +168,7 @@ public class ExtensionLoader { initInstantiationStrategy(); this.injector = (type == ExtensionInjector.class ? null : extensionDirector.getExtensionLoader(ExtensionInjector.class) .getAdaptiveExtension()); + this.activateComparator = new ActivateComparator(extensionDirector); } private void initInstantiationStrategy() { @@ -285,7 +287,7 @@ public class ExtensionLoader { */ public List getActivateExtension(URL url, String[] values, String group) { // solve the bug of using @SPI's wrapper method to report a null pointer exception. - Map, T> activateExtensionsMap = new TreeMap<>(ActivateComparator.COMPARATOR); + Map, T> activateExtensionsMap = new TreeMap<>(activateComparator); List names = values == null ? new ArrayList<>(0) : asList(values); if (!names.contains(REMOVE_VALUE_PREFIX + DEFAULT_KEY)) { if (cachedActivateGroups.size() == 0) { @@ -364,7 +366,7 @@ public class ExtensionLoader { public List getActivateExtensions() { List activateExtensions = new ArrayList<>(); - TreeMap, T> activateExtensionsMap = new TreeMap<>(ActivateComparator.COMPARATOR); + TreeMap, T> activateExtensionsMap = new TreeMap<>(activateComparator); getExtensionClasses(); for (Map.Entry entry : cachedActivates.entrySet()) { String name = entry.getKey(); diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java index 3c6ebab3cc..675fa71399 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/extension/support/ActivateComparator.java @@ -17,6 +17,7 @@ package org.apache.dubbo.common.extension.support; import org.apache.dubbo.common.extension.Activate; +import org.apache.dubbo.common.extension.ExtensionDirector; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.utils.ArrayUtils; @@ -29,7 +30,11 @@ import java.util.Comparator; */ public class ActivateComparator implements Comparator> { - public static final Comparator> COMPARATOR = new ActivateComparator(); + private ExtensionDirector extensionDirector; + + public ActivateComparator(ExtensionDirector extensionDirector) { + this.extensionDirector = extensionDirector; + } @Override public int compare(Class o1, Class o2) { @@ -52,7 +57,7 @@ public class ActivateComparator implements Comparator> { ActivateInfo a2 = parseActivate(o2); if ((a1.applicableToCompare() || a2.applicableToCompare()) && inf != null) { - ExtensionLoader extensionLoader = ExtensionLoader.getExtensionLoader(inf); + ExtensionLoader extensionLoader = extensionDirector.getExtensionLoader(inf); if (a1.applicableToCompare()) { String n2 = extensionLoader.getExtensionName(o2); if (a1.isLess(n2)) { diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java index 06c75e82f6..8622e3368d 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/logger/LoggerFactory.java @@ -16,13 +16,13 @@ */ package org.apache.dubbo.common.logger; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.jcl.JclLoggerAdapter; import org.apache.dubbo.common.logger.jdk.JdkLoggerAdapter; import org.apache.dubbo.common.logger.log4j.Log4jLoggerAdapter; import org.apache.dubbo.common.logger.log4j2.Log4j2LoggerAdapter; import org.apache.dubbo.common.logger.slf4j.Slf4jLoggerAdapter; import org.apache.dubbo.common.logger.support.FailsafeLogger; +import org.apache.dubbo.rpc.model.FrameworkModel; import java.io.File; import java.util.Arrays; @@ -79,9 +79,9 @@ public class LoggerFactory { private LoggerFactory() { } - public static void setLoggerAdapter(String loggerAdapter) { + public static void setLoggerAdapter(FrameworkModel frameworkModel, String loggerAdapter) { if (loggerAdapter != null && loggerAdapter.length() > 0) { - setLoggerAdapter(ExtensionLoader.getExtensionLoader(LoggerAdapter.class).getExtension(loggerAdapter)); + setLoggerAdapter(frameworkModel.getExtensionLoader(LoggerAdapter.class).getExtension(loggerAdapter)); } } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java index a437a7d6a7..a01fe592af 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ClassUtils.java @@ -64,20 +64,20 @@ public class ClassUtils { * @since 2.7.6 */ public static final Set> SIMPLE_TYPES = ofSet( - Void.class, - Boolean.class, - Character.class, - Byte.class, - Short.class, - Integer.class, - Long.class, - Float.class, - Double.class, - String.class, - BigDecimal.class, - BigInteger.class, - Date.class, - Object.class + Void.class, + Boolean.class, + Character.class, + Byte.class, + Short.class, + Integer.class, + Long.class, + Float.class, + Double.class, + String.class, + BigDecimal.class, + BigInteger.class, + Date.class, + Object.class ); /** * Prefix for internal array class names: "[L" @@ -108,20 +108,20 @@ public class ClassUtils { Set> primitiveTypeNames = new HashSet<>(32); primitiveTypeNames.addAll(PRIMITIVE_WRAPPER_TYPE_MAP.values()); primitiveTypeNames.addAll(Arrays - .asList(boolean[].class, byte[].class, char[].class, double[].class, - float[].class, int[].class, long[].class, short[].class)); + .asList(boolean[].class, byte[].class, char[].class, double[].class, + float[].class, int[].class, long[].class, short[].class)); for (Class primitiveTypeName : primitiveTypeNames) { PRIMITIVE_TYPE_NAME_MAP.put(primitiveTypeName.getName(), primitiveTypeName); } } public static Class forNameWithThreadContextClassLoader(String name) - throws ClassNotFoundException { + throws ClassNotFoundException { return forName(name, Thread.currentThread().getContextClassLoader()); } public static Class forNameWithCallerClassLoader(String name, Class caller) - throws ClassNotFoundException { + throws ClassNotFoundException { return forName(name, caller.getClassLoader()); } @@ -137,20 +137,25 @@ public class ClassUtils { */ public static ClassLoader getClassLoader(Class clazz) { ClassLoader cl = null; - try { - cl = Thread.currentThread().getContextClassLoader(); - } catch (Throwable ex) { - // Cannot access thread context ClassLoader - falling back to system class loader... + if (!clazz.getName().startsWith("org.apache.dubbo")) { + cl = clazz.getClassLoader(); } if (cl == null) { - // No thread context class loader -> use class loader of this class. - cl = clazz.getClassLoader(); + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (Throwable ex) { + // Cannot access thread context ClassLoader - falling back to system class loader... + } if (cl == null) { - // getClassLoader() returning null indicates the bootstrap ClassLoader - try { - cl = ClassLoader.getSystemClassLoader(); - } catch (Throwable ex) { - // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + // No thread context class loader -> use class loader of this class. + cl = clazz.getClassLoader(); + if (cl == null) { + // getClassLoader() returning null indicates the bootstrap ClassLoader + try { + cl = ClassLoader.getSystemClassLoader(); + } catch (Throwable ex) { + // Cannot access system ClassLoader - oh well, maybe the caller can live with null... + } } } } @@ -198,7 +203,7 @@ public class ClassUtils { * @see Class#forName(String, boolean, ClassLoader) */ public static Class forName(String name, ClassLoader classLoader) - throws ClassNotFoundException, LinkageError { + throws ClassNotFoundException, LinkageError { Class clazz = resolvePrimitiveClassName(name); if (clazz != null) { @@ -218,7 +223,7 @@ public class ClassUtils { String elementClassName = null; if (internalArrayMarker == 0) { elementClassName = name - .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); + .substring(INTERNAL_ARRAY_PREFIX.length(), name.length() - 1); } else if (name.startsWith("[")) { elementClassName = name.substring(1); } @@ -338,7 +343,7 @@ public class ClassUtils { */ public static boolean isTypeMatch(Class type, String value) { if ((type == boolean.class || type == Boolean.class) - && !("true".equals(value) || "false".equals(value))) { + && !("true".equals(value) || "false".equals(value))) { return false; } return true; @@ -392,18 +397,18 @@ public class ClassUtils { if (isNotEmpty(interfaces)) { // add current interfaces Arrays.stream(interfaces) - .filter(resolved::add) - .forEach(cls -> { - allInterfaces.add(cls); - waitResolve.add(cls); - }); + .filter(resolved::add) + .forEach(cls -> { + allInterfaces.add(cls); + waitResolve.add(cls); + }); } // add all super classes to waitResolve getAllSuperClasses(clazz) - .stream() - .filter(resolved::add) - .forEach(waitResolve::add); + .stream() + .filter(resolved::add) + .forEach(waitResolve::add); clazz = waitResolve.poll(); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java index d990ddb263..5ff23d1edd 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ApplicationConfig.java @@ -331,7 +331,7 @@ public class ApplicationConfig extends AbstractConfig { public void setLogger(String logger) { this.logger = logger; - LoggerFactory.setLoggerAdapter(logger); + LoggerFactory.setLoggerAdapter(getApplicationModel().getFrameworkModel(), logger); } @Parameter(key = DUMP_DIRECTORY) 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 bb31edc2e4..b573b021bd 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 @@ -233,7 +233,9 @@ public abstract class ReferenceConfigBase extends AbstractReferenceConfig { throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!"); } setInterface(interfaceClass == null ? null : interfaceClass.getName()); - setInterfaceClassLoader(interfaceClass == null ? null : interfaceClass.getClassLoader()); + if (getInterfaceClassLoader() == null) { + setInterfaceClassLoader(interfaceClass == null ? null : interfaceClass.getClassLoader()); + } } public String getClient() { 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 130c2e731e..cbce529be4 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 @@ -319,7 +319,9 @@ public abstract class ServiceConfigBase extends AbstractServiceConfig { } this.interfaceClass = interfaceClass; setInterface(interfaceClass == null ? null : interfaceClass.getName()); - setInterfaceClassLoader(interfaceClass == null ? null : interfaceClass.getClassLoader()); + if (getInterfaceClassLoader() == null) { + setInterfaceClassLoader(interfaceClass == null ? null : interfaceClass.getClassLoader()); + } } public T getRef() { 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 dfcde213d9..9ec18fb8e8 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 @@ -169,6 +169,12 @@ public class ApplicationModel extends ScopeModel { initFrameworkExts(); + ExtensionLoader initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class); + Set initializers = initializerExtensionLoader.getSupportedExtensionInstances(); + for (ScopeModelInitializer initializer : initializers) { + initializer.initializeApplicationModel(this); + } + postProcessAfterCreated(); } 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 a5ff09d4a1..1948298bb8 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 @@ -16,6 +16,7 @@ */ package org.apache.dubbo.rpc.model; +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; @@ -23,6 +24,7 @@ import org.apache.dubbo.common.logger.LoggerFactory; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.Set; /** * Model of dubbo framework, it can be shared with multiple applications. @@ -51,6 +53,13 @@ public class FrameworkModel extends ScopeModel { serviceRepository = new FrameworkServiceRepository(this); allInstances.add(this); + ExtensionLoader initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class); + Set initializers = initializerExtensionLoader.getSupportedExtensionInstances(); + for (ScopeModelInitializer initializer : initializers) { + initializer.initializeFrameworkModel(this); + } + + postProcessAfterCreated(); } 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 aee8b5cdfa..5067589fc1 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,11 +16,13 @@ */ package org.apache.dubbo.rpc.model; +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 java.util.List; +import java.util.Set; /** * Model of a service module @@ -43,6 +45,13 @@ public class ModuleModel extends ScopeModel { protected void initialize() { super.initialize(); this.serviceRepository = new ModuleServiceRepository(this); + + ExtensionLoader initializerExtensionLoader = this.getExtensionLoader(ScopeModelInitializer.class); + Set initializers = initializerExtensionLoader.getSupportedExtensionInstances(); + for (ScopeModelInitializer initializer : initializers) { + initializer.initializeModuleModel(this); + } + postProcessAfterCreated(); } diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelInitializer.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelInitializer.java new file mode 100644 index 0000000000..26c70ee0e8 --- /dev/null +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ScopeModelInitializer.java @@ -0,0 +1,30 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.rpc.model; + +import org.apache.dubbo.common.extension.ExtensionScope; +import org.apache.dubbo.common.extension.SPI; + +@SPI(scope = ExtensionScope.SELF) +public interface ScopeModelInitializer { + + void initializeFrameworkModel(FrameworkModel frameworkModel); + + void initializeApplicationModel(ApplicationModel applicationModel); + + void initializeModuleModel(ModuleModel moduleModel); +} diff --git a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java index 5941b9c939..1d5ad15430 100644 --- a/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java +++ b/dubbo-common/src/main/java/org/apache/dubbo/rpc/model/ServiceModel.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.model; import org.apache.dubbo.common.BaseServiceMetadata; -import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.config.AbstractInterfaceConfig; import org.apache.dubbo.config.ReferenceConfigBase; import org.apache.dubbo.config.ServiceConfigBase; @@ -30,6 +29,7 @@ public class ServiceModel { private String serviceKey; private Object proxyObject; private Callable destroyCaller; + private ClassLoader classLoader; private final ModuleModel moduleModel; private final ServiceDescriptor serviceModel; private final AbstractInterfaceConfig config; @@ -51,6 +51,12 @@ public class ServiceModel { this.moduleModel = moduleModel; this.config = config; this.serviceMetadata = serviceMetadata; + if (config != null) { + this.classLoader = config.getInterfaceClassLoader(); + } + if (this.classLoader == null) { + this.classLoader = Thread.currentThread().getContextClassLoader(); + } } public String getServiceKey() { @@ -69,9 +75,12 @@ public class ServiceModel { return serviceModel; } + public void setClassLoader(ClassLoader classLoader) { + this.classLoader = classLoader; + } + public ClassLoader getClassLoader() { - Class serviceType = serviceMetadata.getServiceType(); - return serviceType != null ? serviceType.getClassLoader() : ClassUtils.getClassLoader(); + return classLoader; } /** diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer new file mode 100644 index 0000000000..fdd8f8be8a --- /dev/null +++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer @@ -0,0 +1 @@ +dubbo-common=org.apache.dubbo.common.CommonScopeModelInitializer 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 6e6e5848aa..82524703c0 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 @@ -16,6 +16,8 @@ */ 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; @@ -25,6 +27,7 @@ public class AdaptiveCompilerTest extends JavaCodeTest { public void testAvailableCompiler() throws Exception { AdaptiveCompiler.setDefaultCompiler("jdk"); AdaptiveCompiler compiler = new AdaptiveCompiler(); + compiler.setFrameworkModel(FrameworkModel.defaultModel()); Class clazz = compiler.compile(getSimpleCode(), AdaptiveCompiler.class.getClassLoader()); HelloService helloService = (HelloService) clazz.newInstance(); Assertions.assertEquals("Hello world!", helloService.sayHello()); 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 f871d6d234..29d8b1c611 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 @@ -16,7 +16,10 @@ */ 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; import java.util.ArrayList; @@ -25,6 +28,13 @@ import java.util.List; public class ActivateComparatorTest { + private ActivateComparator activateComparator; + + @BeforeEach + public void setup() { + activateComparator = new ActivateComparator(ApplicationModel.defaultModel().getExtensionDirector()); + } + @Test public void testActivateComparator(){ Filter1 f1 = new Filter1(); @@ -39,7 +49,7 @@ public class ActivateComparatorTest { filters.add(f4.getClass()); filters.add(f5.getClass()); - Collections.sort(filters, ActivateComparator.COMPARATOR); + Collections.sort(filters, activateComparator); Assertions.assertEquals(f4.getClass(), filters.get(0)); Assertions.assertEquals(f5.getClass(), filters.get(1)); @@ -59,7 +69,7 @@ public class ActivateComparatorTest { filters = new ArrayList<>(); filters.add(order0Filter1.getClass()); filters.add(order0Filter2.getClass()); - filters.sort(ActivateComparator.COMPARATOR); + filters.sort(activateComparator); Assertions.assertEquals(order0Filter1.getClass(), filters.get(0)); Assertions.assertEquals(order0Filter2.getClass(), filters.get(1)); } @@ -68,7 +78,7 @@ public class ActivateComparatorTest { filters = new ArrayList<>(); filters.add(order0Filter2.getClass()); filters.add(order0Filter1.getClass()); - filters.sort(ActivateComparator.COMPARATOR); + filters.sort(activateComparator); Assertions.assertEquals(order0Filter1.getClass(), filters.get(0)); Assertions.assertEquals(order0Filter2.getClass(), filters.get(1)); } 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 25fce0ebdf..c83765f444 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 @@ -16,6 +16,8 @@ */ package org.apache.dubbo.common.logger; +import org.apache.dubbo.rpc.model.FrameworkModel; + import org.junit.jupiter.api.Test; import java.io.File; @@ -35,7 +37,7 @@ public class LoggerFactoryTest { @Test public void testGetLogFile() { - LoggerFactory.setLoggerAdapter("slf4j"); + LoggerFactory.setLoggerAdapter(FrameworkModel.defaultModel(), "slf4j"); File file = LoggerFactory.getFile(); assertThat(file, is(nullValue())); 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 c915cee8be..0dade4dce9 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 @@ -43,6 +43,7 @@ import org.apache.dubbo.rpc.cluster.support.registry.ZoneAwareCluster; import org.apache.dubbo.rpc.model.AsyncMethodInfo; import org.apache.dubbo.rpc.model.ConsumerModel; import org.apache.dubbo.rpc.model.ModuleServiceRepository; +import org.apache.dubbo.rpc.model.ScopeModel; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol; import org.apache.dubbo.rpc.service.GenericService; @@ -430,7 +431,7 @@ public class ReferenceConfig extends ReferenceConfigBase { if (UrlUtils.isRegistry(url)) { urls.add(url.putAttribute(REFER_KEY, referenceParameters)); } else { - URL peerUrl = ClusterUtils.mergeUrl(url, referenceParameters); + URL peerUrl = getScopeModel().getApplicationModel().getBeanFactory().getBean(ClusterUtils.class).mergeUrl(url, referenceParameters); peerUrl = peerUrl.putAttribute(PEER_KEY, true); urls.add(peerUrl); } @@ -490,15 +491,17 @@ public class ReferenceConfig extends ReferenceConfigBase { // for multi-subscription scenario, use 'zone-aware' policy by default String cluster = registryUrl.getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME); // The invoker wrap sequence would be: ZoneAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, routing happens here) -> Invoker - invoker = Cluster.getCluster(cluster, false).join(new StaticDirectory(registryUrl, invokers)); + invoker = Cluster.getCluster(registryUrl.getScopeModel(), cluster, false).join(new StaticDirectory(registryUrl, invokers)); } else { // not a registry url, must be direct invoke. - String cluster = CollectionUtils.isNotEmpty(invokers) - ? + String cluster = CollectionUtils.isNotEmpty(invokers) ? (invokers.get(0).getUrl() != null ? invokers.get(0).getUrl().getParameter(CLUSTER_KEY, ZoneAwareCluster.NAME) : Cluster.DEFAULT) : Cluster.DEFAULT; - invoker = Cluster.getCluster(cluster).join(new StaticDirectory(invokers)); + ScopeModel scopeModel = CollectionUtils.isNotEmpty(invokers) ? + (invokers.get(0).getUrl() != null ? invokers.get(0).getUrl().getScopeModel() : null) + : null; + invoker = Cluster.getCluster(scopeModel, cluster).join(new StaticDirectory(invokers)); } } } 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 fdf6c91eff..b1f4cacf56 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 @@ -303,8 +303,11 @@ public class ServiceConfig extends ServiceConfigBase { } } else { try { - interfaceClass = Class.forName(interfaceName, true, Thread.currentThread() - .getContextClassLoader()); + if (getInterfaceClassLoader() != null) { + interfaceClass = Class.forName(interfaceName, true, getInterfaceClassLoader()); + } else { + interfaceClass = Class.forName(interfaceName, true, Thread.currentThread().getContextClassLoader()); + } } catch (ClassNotFoundException e) { throw new IllegalStateException(e.getMessage(), e); } 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 87331c0c05..5c71923ce6 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 @@ -17,7 +17,6 @@ package org.apache.dubbo.config.bootstrap; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; import org.apache.dubbo.common.config.ConfigurationUtils; import org.apache.dubbo.common.config.Environment; import org.apache.dubbo.common.config.configcenter.DynamicConfiguration; @@ -29,7 +28,6 @@ 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.status.reporter.FrameworkStatusReportService; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.CollectionUtils; @@ -282,19 +280,6 @@ public final class DubboBootstrap { DubboShutdownHook.getDubboShutdownHook().register(); ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy); cache = ReferenceConfigCache.newCache(); - - initInternalBeans(); - } - - /** - * TODO init beans module-self - */ - private void initInternalBeans() { - ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); - beanFactory.registerBean(this); - beanFactory.registerBean(MetadataReportInstance.class); - beanFactory.registerBean(RemoteMetadataServiceImpl.class); - beanFactory.registerBean(FrameworkStatusReportService.class); } public ApplicationModel getApplicationModel() { diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java index fa5476e1e3..b361957c2e 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java @@ -19,7 +19,6 @@ package org.apache.dubbo.config.utils; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.common.config.ConfigurationUtils; -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.serialize.Serialization; @@ -63,6 +62,7 @@ import org.apache.dubbo.rpc.cluster.Cluster; import org.apache.dubbo.rpc.cluster.LoadBalance; import org.apache.dubbo.rpc.cluster.filter.ClusterFilter; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModel; import org.apache.dubbo.rpc.support.MockInvoker; import java.net.InetAddress; @@ -108,7 +108,6 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTO import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL; import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; import static org.apache.dubbo.config.Constants.ARCHITECTURE; import static org.apache.dubbo.config.Constants.CONTEXTPATH_KEY; import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY; @@ -325,7 +324,7 @@ public class ConfigValidationUtils { .build(); } else if (ConfigUtils.isNotEmpty(address) || ConfigUtils.isNotEmpty(protocol)) { if (!map.containsKey(PROTOCOL_KEY)) { - if (getExtensionLoader(MonitorFactory.class).hasExtension(LOGSTAT_PROTOCOL)) { + if (interfaceConfig.getScopeModel().getExtensionLoader(MonitorFactory.class).hasExtension(LOGSTAT_PROTOCOL)) { map.put(PROTOCOL_KEY, LOGSTAT_PROTOCOL); } else if (ConfigUtils.isNotEmpty(protocol)) { map.put(PROTOCOL_KEY, protocol); @@ -377,7 +376,7 @@ public class ConfigValidationUtils { } } else { //Check whether the mock class is a implementation of the interfaceClass, and if it has a default constructor - MockInvoker.getMockObject(normalizedMock, interfaceClass); + MockInvoker.getMockObject(config.getScopeModel().getExtensionDirector(), normalizedMock, interfaceClass); } } @@ -386,9 +385,9 @@ public class ConfigValidationUtils { checkName("stub", config.getStub()); checkMultiName("owner", config.getOwner()); - checkExtension(ProxyFactory.class, PROXY_KEY, config.getProxy()); - checkExtension(Cluster.class, CLUSTER_KEY, config.getCluster()); - checkMultiExtension(Arrays.asList(Filter.class, ClusterFilter.class), FILTER_KEY, config.getFilter()); + checkExtension(config.getScopeModel(), ProxyFactory.class, PROXY_KEY, config.getProxy()); + checkExtension(config.getScopeModel(), Cluster.class, CLUSTER_KEY, config.getCluster()); + checkMultiExtension(config.getScopeModel(), Arrays.asList(Filter.class, ClusterFilter.class), FILTER_KEY, config.getFilter()); checkNameHasSymbol(LAYER_KEY, config.getLayer()); List methods = config.getMethods(); @@ -403,7 +402,7 @@ public class ConfigValidationUtils { checkName(TOKEN_KEY, config.getToken()); checkPathName(PATH_KEY, config.getPath()); - checkMultiExtension(ExporterListener.class, "listener", config.getListener()); + checkMultiExtension(config.getScopeModel(), ExporterListener.class, "listener", config.getListener()); validateAbstractInterfaceConfig(config); @@ -428,7 +427,7 @@ public class ConfigValidationUtils { } public static void validateReferenceConfig(ReferenceConfig config) { - checkMultiExtension(InvokerListener.class, "listener", config.getListener()); + checkMultiExtension(config.getScopeModel(), InvokerListener.class, "listener", config.getListener()); checkKey(VERSION_KEY, config.getVersion()); checkKey(GROUP_KEY, config.getGroup()); checkName(CLIENT_KEY, config.getClient()); @@ -529,29 +528,29 @@ public class ConfigValidationUtils { if (DUBBO_PROTOCOL.equals(name)) { - checkMultiExtension(Codec2.class, CODEC_KEY, config.getCodec()); - checkMultiExtension(Serialization.class, SERIALIZATION_KEY, config.getSerialization()); - checkMultiExtension(Transporter.class, SERVER_KEY, config.getServer()); - checkMultiExtension(Transporter.class, CLIENT_KEY, config.getClient()); + checkMultiExtension(config.getScopeModel(), Codec2.class, CODEC_KEY, config.getCodec()); + checkMultiExtension(config.getScopeModel(), Serialization.class, SERIALIZATION_KEY, config.getSerialization()); + checkMultiExtension(config.getScopeModel(), Transporter.class, SERVER_KEY, config.getServer()); + checkMultiExtension(config.getScopeModel(), Transporter.class, CLIENT_KEY, config.getClient()); } - checkMultiExtension(TelnetHandler.class, TELNET, config.getTelnet()); - checkMultiExtension(StatusChecker.class, "status", config.getStatus()); - checkExtension(Transporter.class, TRANSPORTER_KEY, config.getTransporter()); - checkExtension(Exchanger.class, EXCHANGER_KEY, config.getExchanger()); - checkExtension(Dispatcher.class, DISPATCHER_KEY, config.getDispatcher()); - checkExtension(Dispatcher.class, "dispather", config.getDispather()); - checkExtension(ThreadPool.class, THREADPOOL_KEY, config.getThreadpool()); + checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET, config.getTelnet()); + checkMultiExtension(config.getScopeModel(), StatusChecker.class, "status", config.getStatus()); + checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter()); + checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger()); + checkExtension(config.getScopeModel(), Dispatcher.class, DISPATCHER_KEY, config.getDispatcher()); + checkExtension(config.getScopeModel(), Dispatcher.class, "dispather", config.getDispather()); + checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool()); } } public static void validateProviderConfig(ProviderConfig config) { checkPathName(CONTEXTPATH_KEY, config.getContextpath()); - checkExtension(ThreadPool.class, THREADPOOL_KEY, config.getThreadpool()); - checkMultiExtension(TelnetHandler.class, TELNET, config.getTelnet()); - checkMultiExtension(StatusChecker.class, STATUS_KEY, config.getStatus()); - checkExtension(Transporter.class, TRANSPORTER_KEY, config.getTransporter()); - checkExtension(Exchanger.class, EXCHANGER_KEY, config.getExchanger()); + checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool()); + checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET, config.getTelnet()); + checkMultiExtension(config.getScopeModel(), StatusChecker.class, STATUS_KEY, config.getStatus()); + checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter()); + checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger()); } public static void validateConsumerConfig(ConsumerConfig config) { @@ -572,7 +571,7 @@ public class ConfigValidationUtils { } public static void validateMethodConfig(MethodConfig config) { - checkExtension(LoadBalance.class, LOADBALANCE_KEY, config.getLoadbalance()); + checkExtension(config.getScopeModel(), LoadBalance.class, LOADBALANCE_KEY, config.getLoadbalance()); checkParameterName(config.getParameters()); checkMethodName("name", config.getName()); @@ -597,10 +596,10 @@ public class ConfigValidationUtils { return StringUtils.isNotEmpty(registryProtocol) ? registryProtocol : REGISTRY_PROTOCOL; } - public static void checkExtension(Class type, String property, String value) { + public static void checkExtension(ScopeModel scopeModel, Class type, String property, String value) { checkName(property, value); if (StringUtils.isNotEmpty(value) - && !ExtensionLoader.getExtensionLoader(type).hasExtension(value)) { + && !scopeModel.getExtensionLoader(type).hasExtension(value)) { throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName()); } } @@ -613,11 +612,11 @@ public class ConfigValidationUtils { * @param property The extension key * @param value The Extension name */ - public static void checkMultiExtension(Class type, String property, String value) { - checkMultiExtension(Collections.singletonList(type), property, value); + public static void checkMultiExtension(ScopeModel scopeModel, Class type, String property, String value) { + checkMultiExtension(scopeModel,Collections.singletonList(type), property, value); } - public static void checkMultiExtension(List> types, String property, String value) { + public static void checkMultiExtension(ScopeModel scopeModel, List> types, String property, String value) { checkMultiName(property, value); if (StringUtils.isNotEmpty(value)) { String[] values = value.split("\\s*[,]+\\s*"); @@ -630,7 +629,7 @@ public class ConfigValidationUtils { } boolean match = false; for (Class type : types) { - if (ExtensionLoader.getExtensionLoader(type).hasExtension(v)) { + if (scopeModel.getExtensionLoader(type).hasExtension(v)) { match = true; } } diff --git a/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderService.java b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderService.java new file mode 100644 index 0000000000..5f77227316 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderService.java @@ -0,0 +1,22 @@ +/* + * 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 demo; + +public interface MultiClassLoaderService { + + Object call(MultiClassLoaderServiceRequest innerRequest); +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceImpl.java b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceImpl.java new file mode 100644 index 0000000000..b315aa2e4e --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceImpl.java @@ -0,0 +1,35 @@ +/* + * 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 demo; + +import java.util.concurrent.atomic.AtomicReference; + +public class MultiClassLoaderServiceImpl implements MultiClassLoaderService { + private AtomicReference innerRequestReference; + private AtomicReference innerResultReference; + + public MultiClassLoaderServiceImpl(AtomicReference innerRequestReference, AtomicReference innerResultReference) { + this.innerRequestReference = innerRequestReference; + this.innerResultReference = innerResultReference; + } + + @Override + public MultiClassLoaderServiceResult call(MultiClassLoaderServiceRequest innerRequest) { + innerRequestReference.set(innerRequest); + return innerResultReference.get(); + } +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceRequest.java b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceRequest.java new file mode 100644 index 0000000000..9dd67ca5a5 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceRequest.java @@ -0,0 +1,22 @@ +/* + * 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 demo; + +import java.io.Serializable; + +public class MultiClassLoaderServiceRequest implements Serializable { +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceResult.java b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceResult.java new file mode 100644 index 0000000000..c4ed2aa702 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/test/java/demo/MultiClassLoaderServiceResult.java @@ -0,0 +1,22 @@ +/* + * 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 demo; + +import java.io.Serializable; + +public class MultiClassLoaderServiceResult implements Serializable { +} 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 8278220628..32864f20d0 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 @@ -192,19 +192,19 @@ public class AbstractConfigTest { @Test public void checkExtension() throws Exception { - Assertions.assertThrows(IllegalStateException.class, () -> ConfigValidationUtils.checkExtension(Greeting.class, "hello", "world")); + Assertions.assertThrows(IllegalStateException.class, () -> ConfigValidationUtils.checkExtension(ApplicationModel.defaultModel(), Greeting.class, "hello", "world")); } @Test public void checkMultiExtension1() throws Exception { Assertions.assertThrows(IllegalStateException.class, - () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,world")); + () -> ConfigValidationUtils.checkMultiExtension(ApplicationModel.defaultModel(), Greeting.class, "hello", "default,world")); } @Test public void checkMultiExtension2() throws Exception { Assertions.assertThrows(IllegalStateException.class, - () -> ConfigValidationUtils.checkMultiExtension(Greeting.class, "hello", "default,-world")); + () -> ConfigValidationUtils.checkMultiExtension(ApplicationModel.defaultModel(), Greeting.class, "hello", "default,-world")); } @Test 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 a3cd67084d..e29f75a1db 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 @@ -18,6 +18,8 @@ package org.apache.dubbo.config; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; +import org.apache.dubbo.common.compiler.support.CtClassBuilder; +import org.apache.dubbo.common.compiler.support.JavassistCompiler; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.NetUtils; @@ -41,6 +43,13 @@ 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; @@ -51,15 +60,18 @@ import org.mockito.Mockito; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY; @@ -865,6 +877,80 @@ public class ReferenceConfigTest { applicationModel.destroy(); } + @Test + public void testDifferentClassLoaderRequest() throws Exception { + String basePath = DemoService.class.getProtectionDomain().getCodeSource().getLocation().getFile(); + basePath = java.net.URLDecoder.decode(basePath, "UTF-8"); + TestClassLoader1 classLoader1 = new TestClassLoader1(basePath); + TestClassLoader1 classLoader2 = new TestClassLoader1(basePath); + TestClassLoader2 classLoader3 = new TestClassLoader2(classLoader2, basePath); + + ApplicationConfig applicationConfig = new ApplicationConfig("TestApp"); + ApplicationModel applicationModel = new ApplicationModel(FrameworkModel.defaultModel()); + applicationModel.getApplicationConfigManager().setApplication(applicationConfig); + ModuleModel moduleModel = new ModuleModel(applicationModel); + + Class clazz1 = classLoader1.loadClass(MultiClassLoaderService.class.getName(), false); + Class clazz1impl = classLoader1.loadClass(MultiClassLoaderServiceImpl.class.getName(), false); + Class requestClazzCustom1 = compileCustomRequest(classLoader1); + Class resultClazzCustom1 = compileCustomResult(classLoader1); + classLoader1.loadedClass.put(requestClazzCustom1.getName(), requestClazzCustom1); + classLoader1.loadedClass.put(resultClazzCustom1.getName(), resultClazzCustom1); + AtomicReference innerRequestReference = new AtomicReference(); + AtomicReference innerResultReference = new AtomicReference(); + innerResultReference.set(resultClazzCustom1.newInstance()); + Constructor declaredConstructor = clazz1impl.getDeclaredConstructor(AtomicReference.class, AtomicReference.class); + + ServiceConfig serviceConfig = new ServiceConfig<>(); + serviceConfig.setInterfaceClassLoader(classLoader1); + serviceConfig.setInterface(clazz1); + serviceConfig.setRegistry(new RegistryConfig(zkUrl)); + serviceConfig.setScopeModel(moduleModel); + serviceConfig.setRef(declaredConstructor.newInstance(innerRequestReference, innerResultReference)); + serviceConfig.export(); + + Class clazz2 = classLoader2.loadClass(MultiClassLoaderService.class.getName(), false); + Class requestClazzOrigin = classLoader2.loadClass(MultiClassLoaderServiceRequest.class.getName(), false); + Class requestClazzCustom2 = compileCustomRequest(classLoader2); + Class resultClazzCustom3 = compileCustomResult(classLoader3); + classLoader2.loadedClass.put(requestClazzCustom2.getName(), requestClazzCustom2); + classLoader3.loadedClass.put(resultClazzCustom3.getName(), resultClazzCustom3); + + ReferenceConfig referenceConfig1 = new ReferenceConfig<>(); + referenceConfig1.setInterface(clazz2); + referenceConfig1.setInterfaceClassLoader(classLoader3); + referenceConfig1.setRegistry(new RegistryConfig(zkUrl)); + referenceConfig1.setScopeModel(moduleModel); + referenceConfig1.setScope("remote"); + Object object1 = referenceConfig1.get(); + + java.lang.reflect.Method callBean1 = object1.getClass().getDeclaredMethod("call", requestClazzOrigin); + callBean1.setAccessible(true); + Object result1 = callBean1.invoke(object1, requestClazzCustom2.newInstance()); + + Assertions.assertEquals(resultClazzCustom3, result1.getClass()); + Assertions.assertNotEquals(classLoader2, result1.getClass().getClassLoader()); + Assertions.assertEquals(classLoader1, innerRequestReference.get().getClass().getClassLoader()); + + applicationModel.destroy(); + } + + private Class compileCustomRequest(ClassLoader classLoader) throws NotFoundException, CannotCompileException { + CtClassBuilder builder = new CtClassBuilder(); + builder.setClassName(MultiClassLoaderServiceRequest.class.getName() + "A"); + builder.setSuperClassName(MultiClassLoaderServiceRequest.class.getName()); + CtClass cls = builder.build(classLoader); + return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); + } + + private Class compileCustomResult(ClassLoader classLoader) throws NotFoundException, CannotCompileException { + CtClassBuilder builder = new CtClassBuilder(); + builder.setClassName(MultiClassLoaderServiceResult.class.getName() + "A"); + builder.setSuperClassName(MultiClassLoaderServiceResult.class.getName()); + CtClass cls = builder.build(classLoader); + return cls.toClass(classLoader, JavassistCompiler.class.getProtectionDomain()); + } + @Reference(methods = {@Method(name = "sayHello", timeout = 1300, retries = 4, loadbalance = "random", async = true, actives = 3, executes = 5, deprecated = true, sticky = true, oninvoke = "instance.i", onthrow = "instance.t", onreturn = "instance.r", cache = "c", validation = "v", arguments = {@Argument(index = 24, callback = true, type = "sss")})}) @@ -873,7 +959,6 @@ public class ReferenceConfigTest { private class InnerTest { } - private static class TestClassLoader extends ClassLoader { private String basePath; @@ -914,6 +999,115 @@ public class ReferenceConfigTest { } + public byte[] loadClassData(String className) throws IOException { + className = className.replaceAll("\\.", "/"); + String path = basePath + File.separator + className + ".class"; + FileInputStream fileInputStream; + byte[] classBytes; + fileInputStream = new FileInputStream(path); + int length = fileInputStream.available(); + classBytes = new byte[length]; + fileInputStream.read(classBytes); + fileInputStream.close(); + return classBytes; + } + } + + private static class TestClassLoader1 extends ClassLoader { + private String basePath; + + public TestClassLoader1(String basePath) { + this.basePath = basePath; + } + + Map> loadedClass = new ConcurrentHashMap<>(); + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + try { + byte[] bytes = loadClassData(name); + return defineClass(name, bytes, 0, bytes.length); + } catch (Exception e) { + throw new ClassNotFoundException(); + } + } + + @Override + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (loadedClass.containsKey(name)) { + return loadedClass.get(name); + } + if (name.startsWith("demo")) { + Class aClass = this.findClass(name); + this.loadedClass.put(name, aClass); + if (resolve) { + this.resolveClass(aClass); + } + return aClass; + } else { + Class loadedClass = this.findLoadedClass(name); + if (loadedClass != null) { + return loadedClass; + } else { + return super.loadClass(name, resolve); + } + } + } + + + public byte[] loadClassData(String className) throws IOException { + className = className.replaceAll("\\.", "/"); + String path = basePath + File.separator + className + ".class"; + FileInputStream fileInputStream; + byte[] classBytes; + fileInputStream = new FileInputStream(path); + int length = fileInputStream.available(); + classBytes = new byte[length]; + fileInputStream.read(classBytes); + fileInputStream.close(); + return classBytes; + } + } + + private static class TestClassLoader2 extends ClassLoader { + private String basePath; + private TestClassLoader1 testClassLoader; + + Map> loadedClass = new ConcurrentHashMap<>(); + + public TestClassLoader2(TestClassLoader1 testClassLoader, String basePath) { + this.testClassLoader = testClassLoader; + this.basePath = basePath; + } + + @Override + protected Class findClass(String name) throws ClassNotFoundException { + try { + byte[] bytes = loadClassData(name); + return defineClass(name, bytes, 0, bytes.length); + } catch (Exception e) { + throw new ClassNotFoundException(); + } + } + + @Override + public Class loadClass(String name, boolean resolve) throws ClassNotFoundException { + if (loadedClass.containsKey(name)) { + return loadedClass.get(name); + } + if (name.startsWith("demo.MultiClassLoaderServiceRe")) { + Class aClass = this.findClass(name); + this.loadedClass.put(name, aClass); + if (resolve) { + this.resolveClass(aClass); + } + return aClass; + } else { + return testClassLoader.loadClass(name, resolve); + } + } + + public byte[] loadClassData(String className) throws IOException { className = className.replaceAll("\\.", "/"); String path = basePath + File.separator + className + ".class"; diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml index 3fd09339de..164115ba2f 100644 --- a/dubbo-distribution/dubbo-all/pom.xml +++ b/dubbo-distribution/dubbo-all/pom.xml @@ -789,6 +789,12 @@ META-INF/dubbo/internal/org.apache.dubbo.registry.ProviderFirstParams + + + META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer + + diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java index f55e28c1d2..d05a730bf0 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataInfo.java @@ -228,7 +228,6 @@ public class MetadataInfo implements Serializable { } public static class ServiceInfo implements Serializable { - private static ExtensionLoader loader = ExtensionLoader.getExtensionLoader(MetadataParamsFilter.class); private String name; private String group; private String version; @@ -250,6 +249,7 @@ public class MetadataInfo implements Serializable { private transient String matchKey; private transient URL url; + private transient ExtensionLoader loader; private final static String[] KEYS_TO_REMOVE = {MONITOR_KEY, BIND_IP_KEY, BIND_PORT_KEY, QOS_ENABLE, QOS_HOST, QOS_PORT, ACCEPT_FOREIGN_IP, VALIDATION_KEY, INTERFACES, PID_KEY, TIMESTAMP_KEY}; @@ -258,7 +258,7 @@ public class MetadataInfo implements Serializable { public ServiceInfo(URL url) { this(url.getServiceInterface(), url.getGroup(), url.getVersion(), url.getProtocol(), url.getPath(), null); - + this.loader = url.getOrDefaultApplicationModel().getExtensionLoader(MetadataParamsFilter.class); this.url = url; Map params = new HashMap<>(); List filters = loader.getActivateExtension(url, "params-filter"); diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java index 82547f3d83..e6192f36bd 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java @@ -19,11 +19,11 @@ package org.apache.dubbo.metadata; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.lang.Prioritized; +import org.apache.dubbo.rpc.model.ScopeModel; import java.util.List; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION; /** @@ -84,8 +84,8 @@ public interface MetadataServiceExporter extends Prioritized { * @return non-null * @since 2.7.8 */ - static MetadataServiceExporter getExtension(String metadataType) { - return getExtensionLoader(MetadataServiceExporter.class).getOrDefaultExtension(metadataType); + static MetadataServiceExporter getExtension(ScopeModel scopeModel, String metadataType) { + return scopeModel.getExtensionLoader(MetadataServiceExporter.class).getOrDefaultExtension(metadataType); } /** @@ -94,8 +94,8 @@ public interface MetadataServiceExporter extends Prioritized { * @return non-null * @since 2.7.8 */ - static MetadataServiceExporter getDefaultExtension() { - return getExtension(DEFAULT_METADATA_STORAGE_TYPE); + static MetadataServiceExporter getDefaultExtension(ScopeModel scopeModel) { + return getExtension(scopeModel, DEFAULT_METADATA_STORAGE_TYPE); } } diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java index 96dca1ae9d..ac71b5cd24 100644 --- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java @@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.model.ScopeModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.Arrays; import java.util.HashSet; @@ -27,7 +28,6 @@ import java.util.Set; import static java.util.Collections.emptySet; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION; import static org.apache.dubbo.common.utils.StringUtils.SLASH; @@ -51,16 +51,8 @@ public interface ServiceNameMapping { * * @return non-null {@link ServiceNameMapping} */ - static ServiceNameMapping getDefaultExtension() { - return getExtensionLoader(ServiceNameMapping.class).getDefaultExtension(); - } - static ServiceNameMapping getDefaultExtension(ScopeModel scopeModel) { - if (scopeModel != null) { - return scopeModel.getDefaultExtension(ServiceNameMapping.class); - } else { - return getExtensionLoader(ServiceNameMapping.class).getDefaultExtension(); - } + return ScopeModelUtil.getApplicationModel(scopeModel).getDefaultExtension(ServiceNameMapping.class); } static String buildMappingKey(URL url) { diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataScopeModelInitializer.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataScopeModelInitializer.java new file mode 100644 index 0000000000..c88eaf774a --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataScopeModelInitializer.java @@ -0,0 +1,41 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.metadata.report; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +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 MetadataScopeModelInitializer implements ScopeModelInitializer { + @Override + public void initializeFrameworkModel(FrameworkModel frameworkModel) { + + } + + @Override + public void initializeApplicationModel(ApplicationModel applicationModel) { + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + beanFactory.registerBean(MetadataReportInstance.class); + } + + @Override + public void initializeModuleModel(ModuleModel moduleModel) { + + } +} diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer new file mode 100644 index 0000000000..6492e52557 --- /dev/null +++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer @@ -0,0 +1 @@ +dubbo-metadata-api=org.apache.dubbo.metadata.report.MetadataScopeModelInitializer diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java index dc591655c7..b8ee2f6eda 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/AccessKeyAuthenticator.java @@ -24,11 +24,17 @@ import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.auth.utils.SignatureUtils; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.rpc.Invocation; +import org.apache.dubbo.rpc.model.ApplicationModel; public class AccessKeyAuthenticator implements Authenticator { + private ApplicationModel applicationModel; + + public AccessKeyAuthenticator(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } + @Override public void sign(Invocation invocation, URL url) { String currentTime = String.valueOf(System.currentTimeMillis()); @@ -66,7 +72,7 @@ public class AccessKeyAuthenticator implements Authenticator { } AccessKeyPair getAccessKeyPair(Invocation invocation, URL url) { - AccessKeyStorage accessKeyStorage = ExtensionLoader.getExtensionLoader(AccessKeyStorage.class) + AccessKeyStorage accessKeyStorage = applicationModel.getExtensionLoader(AccessKeyStorage.class) .getExtension(url.getParameter(Constants.ACCESS_KEY_STORAGE_KEY, Constants.DEFAULT_ACCESS_KEY_STORAGE)); AccessKeyPair accessKeyPair = null; diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java index 96438c53d0..aad5279150 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ConsumerSignFilter.java @@ -21,12 +21,12 @@ import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ApplicationModel; /** * The ConsumerSignFilter @@ -35,13 +35,18 @@ import org.apache.dubbo.rpc.RpcException; */ @Activate(group = CommonConstants.CONSUMER, value = Constants.SERVICE_AUTH, order = -10000) public class ConsumerSignFilter implements Filter { + private ApplicationModel applicationModel; + + public ConsumerSignFilter(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false); if (shouldAuth) { - Authenticator authenticator = ExtensionLoader.getExtensionLoader(Authenticator.class) + Authenticator authenticator = applicationModel.getExtensionLoader(Authenticator.class) .getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR)); authenticator.sign(invocation, url); } diff --git a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java index fbb18a894b..3b1008d2ce 100644 --- a/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java +++ b/dubbo-plugin/dubbo-auth/src/main/java/org/apache/dubbo/auth/filter/ProviderAuthFilter.java @@ -21,23 +21,28 @@ import org.apache.dubbo.auth.spi.Authenticator; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.rpc.AsyncRpcResult; import org.apache.dubbo.rpc.Filter; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; import org.apache.dubbo.rpc.RpcException; +import org.apache.dubbo.rpc.model.ApplicationModel; @Activate(group = CommonConstants.PROVIDER, order = -10000) public class ProviderAuthFilter implements Filter { + private ApplicationModel applicationModel; + + public ProviderAuthFilter(ApplicationModel applicationModel) { + this.applicationModel = applicationModel; + } @Override public Result invoke(Invoker invoker, Invocation invocation) throws RpcException { URL url = invoker.getUrl(); boolean shouldAuth = url.getParameter(Constants.SERVICE_AUTH, false); if (shouldAuth) { - Authenticator authenticator = ExtensionLoader.getExtensionLoader(Authenticator.class) + Authenticator authenticator = applicationModel.getExtensionLoader(Authenticator.class) .getExtension(url.getParameter(Constants.AUTHENTICATOR, Constants.DEFAULT_AUTHENTICATOR)); try { authenticator.authenticate(invocation, url); diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java index 5a0cfb296e..c12c3131d2 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/AccessKeyAuthenticatorTest.java @@ -22,6 +22,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Test; @@ -93,7 +94,7 @@ class AccessKeyAuthenticatorTest { .addParameter(CommonConstants.APPLICATION_KEY, "test") .addParameter(Constants.SECRET_ACCESS_KEY_KEY, "sk"); Invocation invocation = new RpcInvocation(); - AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(ApplicationModel.defaultModel()); assertThrows(RpcAuthenticationException.class, () -> helper.authenticate(invocation, url)); } @@ -101,7 +102,7 @@ class AccessKeyAuthenticatorTest { void testGetAccessKeyPairFailed() { URL url = URL.valueOf("dubbo://10.10.10.10:2181") .addParameter(Constants.ACCESS_KEY_ID_KEY, "ak"); - AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(ApplicationModel.defaultModel()); Invocation invocation = mock(Invocation.class); assertThrows(RuntimeException.class, () -> helper.getAccessKeyPair(invocation, url)); } @@ -111,7 +112,7 @@ class AccessKeyAuthenticatorTest { URL url = mock(URL.class); Invocation invocation = mock(Invocation.class); String secretKey = "123456"; - AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(ApplicationModel.defaultModel()); String signature = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis())); assertNotNull(signature); } @@ -124,7 +125,7 @@ class AccessKeyAuthenticatorTest { String secretKey = "123456"; Object[] params = {"dubbo", new ArrayList()}; when(invocation.getArguments()).thenReturn(params); - AccessKeyAuthenticator helper = new AccessKeyAuthenticator(); + AccessKeyAuthenticator helper = new AccessKeyAuthenticator(ApplicationModel.defaultModel()); String signature = helper.getSignature(url, invocation, secretKey, String.valueOf(System.currentTimeMillis())); assertNotNull(signature); diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java index 167bc8fabd..8a520813d8 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ConsumerSignFilterTest.java @@ -21,6 +21,7 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Test; @@ -41,7 +42,7 @@ class ConsumerSignFilterTest { Invoker invoker = mock(Invoker.class); Invocation invocation = mock(Invocation.class); when(invoker.getUrl()).thenReturn(url); - ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(); + ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(ApplicationModel.defaultModel()); consumerSignFilter.invoke(invoker, invocation); verify(invocation, never()).setAttachment(eq(Constants.REQUEST_SIGNATURE_KEY), anyString()); } @@ -56,7 +57,7 @@ class ConsumerSignFilterTest { Invoker invoker = mock(Invoker.class); Invocation invocation = mock(Invocation.class); when(invoker.getUrl()).thenReturn(url); - ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(); + ConsumerSignFilter consumerSignFilter = new ConsumerSignFilter(ApplicationModel.defaultModel()); consumerSignFilter.invoke(invoker, invocation); verify(invocation, times(1)).setAttachment(eq(Constants.REQUEST_SIGNATURE_KEY), anyString()); } diff --git a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java index cbb9379948..a3d1dab507 100644 --- a/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java +++ b/dubbo-plugin/dubbo-auth/src/test/java/org/apache/dubbo/auth/filter/ProviderAuthFilterTest.java @@ -24,6 +24,7 @@ import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.rpc.Invocation; import org.apache.dubbo.rpc.Invoker; import org.apache.dubbo.rpc.Result; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Test; @@ -45,7 +46,7 @@ class ProviderAuthFilterTest { Invoker invoker = mock(Invoker.class); Invocation invocation = mock(Invocation.class); when(invoker.getUrl()).thenReturn(url); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); providerAuthFilter.invoke(invoker, invocation); verify(url, never()).getParameter(eq(Constants.AUTHENTICATOR), eq(Constants.DEFAULT_AUTHENTICATOR)); } @@ -60,7 +61,7 @@ class ProviderAuthFilterTest { Invoker invoker = mock(Invoker.class); Invocation invocation = mock(Invocation.class); when(invoker.getUrl()).thenReturn(url); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); providerAuthFilter.invoke(invoker, invocation); verify(invocation, atLeastOnce()).getAttachment(anyString()); } @@ -78,7 +79,7 @@ class ProviderAuthFilterTest { when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(null); when(invoker.getUrl()).thenReturn(url); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); Result result = providerAuthFilter.invoke(invoker, invocation); assertTrue(result.hasException()); @@ -96,7 +97,7 @@ class ProviderAuthFilterTest { when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(null); when(invoker.getUrl()).thenReturn(url); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); Result result = providerAuthFilter.invoke(invoker, invocation); assertTrue(result.hasException()); } @@ -114,7 +115,7 @@ class ProviderAuthFilterTest { when(invocation.getObjectAttachment(Constants.REQUEST_TIMESTAMP_KEY)).thenReturn(System.currentTimeMillis()); when(invoker.getUrl()).thenReturn(url); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); Result result = providerAuthFilter.invoke(invoker, invocation); assertTrue(result.hasException()); assertTrue(result.getException() instanceof RpcAuthenticationException); @@ -150,7 +151,7 @@ class ProviderAuthFilterTest { String sign = SignatureUtils.sign(originalParams, requestString, "sk"); when(invocation.getObjectAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(sign); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); Result result = providerAuthFilter.invoke(invoker, invocation); assertTrue(result.hasException()); assertTrue(result.getException() instanceof RpcAuthenticationException); @@ -181,7 +182,7 @@ class ProviderAuthFilterTest { String sign = SignatureUtils.sign(requestString, "sk"); when(invocation.getAttachment(Constants.REQUEST_SIGNATURE_KEY)).thenReturn(sign); - ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(); + ProviderAuthFilter providerAuthFilter = new ProviderAuthFilter(ApplicationModel.defaultModel()); Result result = providerAuthFilter.invoke(invoker, invocation); assertNull(result); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactoryWrapper.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactoryWrapper.java index 568b86aa85..6fe365d970 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactoryWrapper.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryFactoryWrapper.java @@ -18,7 +18,6 @@ package org.apache.dubbo.registry; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import java.util.Collections; @@ -32,7 +31,7 @@ public class RegistryFactoryWrapper implements RegistryFactory { @Override public Registry getRegistry(URL url) { return new ListenerRegistryWrapper(registryFactory.getRegistry(url), - Collections.unmodifiableList(ExtensionLoader.getExtensionLoader(RegistryServiceListener.class) + Collections.unmodifiableList(url.getOrDefaultApplicationModel().getExtensionLoader(RegistryServiceListener.class) .getActivateExtension(url, "registry.listeners"))); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryNotifier.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryNotifier.java index 58ca018063..3b3fd2f6ae 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryNotifier.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryNotifier.java @@ -16,7 +16,7 @@ */ package org.apache.dubbo.registry; -import org.apache.dubbo.common.extension.ExtensionLoader; +import org.apache.dubbo.common.URL; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; @@ -42,14 +42,14 @@ public abstract class RegistryNotifier { private ScheduledExecutorService scheduler; - public RegistryNotifier(long delayTime) { - this(delayTime, null); + public RegistryNotifier(URL registryUrl, long delayTime) { + this(registryUrl, delayTime, null); } - public RegistryNotifier(long delayTime, ScheduledExecutorService scheduler) { + public RegistryNotifier(URL registryUrl, long delayTime, ScheduledExecutorService scheduler) { this.delayTime = delayTime; if (scheduler == null) { - this.scheduler = ExtensionLoader.getExtensionLoader(ExecutorRepository.class) + this.scheduler = registryUrl.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class) .getDefaultExtension().getRegistryNotificationExecutor(); } else { this.scheduler = scheduler; diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java new file mode 100644 index 0000000000..a356b87a2f --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/RegistryScopeModelInitializer.java @@ -0,0 +1,42 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.dubbo.registry; + +import org.apache.dubbo.common.beans.factory.ScopeBeanFactory; +import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl; +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 RegistryScopeModelInitializer implements ScopeModelInitializer { + @Override + public void initializeFrameworkModel(FrameworkModel frameworkModel) { + + } + + @Override + public void initializeApplicationModel(ApplicationModel applicationModel) { + ScopeBeanFactory beanFactory = applicationModel.getBeanFactory(); + beanFactory.registerBean(RemoteMetadataServiceImpl.class); + } + + @Override + public void initializeModuleModel(ModuleModel moduleModel) { + + } +} diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java index 780222ee61..7f0f1a5da4 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceDiscoveryFactory.java @@ -20,8 +20,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; - /** * The default {@link SPI} implementation of {@link ServiceDiscoveryFactory} to {@link #getServiceDiscovery(URL) get the * instance of ServiceDiscovery} via the {@link URL#getProtocol() protocol} from the {@link URL} that will connect @@ -42,7 +40,7 @@ public class DefaultServiceDiscoveryFactory extends AbstractServiceDiscoveryFact @Override protected ServiceDiscovery createDiscovery(URL registryURL) { String protocol = registryURL.getProtocol(); - ExtensionLoader loader = getExtensionLoader(ServiceDiscovery.class); + ExtensionLoader loader = registryURL.getOrDefaultApplicationModel().getExtensionLoader(ServiceDiscovery.class); return loader.getExtension(protocol); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java index 483c862447..aba5ccc632 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/DefaultServiceInstance.java @@ -212,6 +212,7 @@ public class DefaultServiceInstance implements ServiceInstance { } @Override + @Transient public Map getAttributes() { return attributes; } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java index a6bbcf37bc..f94cce26ce 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryFactory.java @@ -20,8 +20,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.extension.SPI; -import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader; - /** * The factory to create {@link ServiceDiscovery} * @@ -47,7 +45,7 @@ public interface ServiceDiscoveryFactory { */ static ServiceDiscoveryFactory getExtension(URL registryURL) { String protocol = registryURL.getProtocol(); - ExtensionLoader loader = getExtensionLoader(ServiceDiscoveryFactory.class); + ExtensionLoader loader = registryURL.getOrDefaultApplicationModel().getExtensionLoader(ServiceDiscoveryFactory.class); return loader.getOrDefaultExtension(protocol); } } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java index cfcb3a851a..54f5262f56 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistry.java @@ -115,7 +115,7 @@ public class ServiceDiscoveryRegistry implements Registry { } private List initSubscribedURLsSynthesizers() { - ExtensionLoader loader = ExtensionLoader.getExtensionLoader(SubscribedURLsSynthesizer.class); + ExtensionLoader loader = getUrl().getOrDefaultApplicationModel().getExtensionLoader(SubscribedURLsSynthesizer.class); return Collections.unmodifiableList(new ArrayList<>(loader.getSupportedExtensionInstances())); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java index a4a1cb1d45..e5ea6d898f 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryDirectory.java @@ -36,7 +36,6 @@ import org.apache.dubbo.rpc.RpcServiceContext; import org.apache.dubbo.rpc.cluster.Configurator; import org.apache.dubbo.rpc.cluster.RouterChain; import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.ArrayList; import java.util.Collections; @@ -75,7 +74,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { applicationModel = getApplicationModel(url.getScopeModel()); consumerConfigurationListener = new ConsumerConfigurationListener(applicationModel); - Set providerFirstParams = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getExtensionLoader(ProviderFirstParams.class).getSupportedExtensionInstances(); + Set providerFirstParams = url.getOrDefaultApplicationModel().getExtensionLoader(ProviderFirstParams.class).getSupportedExtensionInstances(); if (CollectionUtils.isEmpty(providerFirstParams)) { this.providerFirstParams = null; } else { @@ -147,7 +146,7 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { RpcServiceContext.setRpcContext(getConsumerUrl()); // 3.x added for extend URL address - ExtensionLoader addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class); + ExtensionLoader addressListenerExtensionLoader = getUrl().getOrDefaultApplicationModel().getExtensionLoader(AddressListener.class); List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); if (supportedListeners != null && !supportedListeners.isEmpty()) { for (AddressListener addressListener : supportedListeners) { @@ -294,11 +293,11 @@ public class ServiceDiscoveryRegistryDirectory extends DynamicDirectory { if (EMPTY_PROTOCOL.equals(instanceAddressURL.getProtocol())) { continue; } - if (!ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(instanceAddressURL.getProtocol())) { + if (!getUrl().getOrDefaultFrameworkModel().getExtensionLoader(Protocol.class).hasExtension(instanceAddressURL.getProtocol())) { logger.error(new IllegalStateException("Unsupported protocol " + instanceAddressURL.getProtocol() + " in notified url: " + instanceAddressURL + " from registry " + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost() + ", supported protocol: " + - ExtensionLoader.getExtensionLoader(Protocol.class).getSupportedExtensions())); + getUrl().getOrDefaultFrameworkModel().getExtensionLoader(Protocol.class).getSupportedExtensions())); continue; } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java index 05e3dd91b9..d3e363d18c 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/ServiceInstance.java @@ -17,7 +17,9 @@ package org.apache.dubbo.registry.client; import org.apache.dubbo.rpc.model.ApplicationModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; +import java.beans.Transient; import java.io.Serializable; import java.util.Map; import java.util.SortedMap; @@ -96,6 +98,11 @@ public interface ServiceInstance extends Serializable { ApplicationModel getApplicationModel(); + @Transient + default ApplicationModel getOrDefaultApplicationModel() { + return ScopeModelUtil.getApplicationModel(getApplicationModel()); + } + /** * Get the value of metadata by the specified name * diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java index 158634897c..ee547d9f8f 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/event/listener/ServiceInstancesChangedListener.java @@ -17,7 +17,6 @@ package org.apache.dubbo.registry.client.event.listener; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; @@ -35,6 +34,7 @@ import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent; import org.apache.dubbo.registry.client.metadata.MetadataUtils; import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils; import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.ArrayList; import java.util.Collections; @@ -80,7 +80,7 @@ public class ServiceInstancesChangedListener { private volatile long lastRefreshTime; private Semaphore retryPermission; private volatile ScheduledFuture retryFuture; - private static ScheduledExecutorService scheduler = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().getMetadataRetryExecutor(); + private ScheduledExecutorService scheduler; public ServiceInstancesChangedListener(Set serviceNames, ServiceDiscovery serviceDiscovery) { this.serviceNames = serviceNames; @@ -90,6 +90,8 @@ public class ServiceInstancesChangedListener { this.serviceUrls = new HashMap<>(); this.revisionToMetadata = new HashMap<>(); retryPermission = new Semaphore(1); + this.scheduler = ScopeModelUtil.getApplicationModel(serviceDiscovery == null || serviceDiscovery.getUrl() == null ? null : serviceDiscovery.getUrl().getScopeModel()) + .getExtensionLoader(ExecutorRepository.class).getDefaultExtension().getMetadataRetryExecutor(); } /** diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java index ab42d01db9..6c126dbb0a 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMapping.java @@ -29,7 +29,6 @@ import org.apache.dubbo.metadata.report.MetadataReport; import org.apache.dubbo.metadata.report.MetadataReportInstance; import org.apache.dubbo.registry.client.RegistryClusterIdentifier; import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.rpc.model.ScopeModelAware; import java.util.Collections; import java.util.List; @@ -38,7 +37,7 @@ import java.util.Set; import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR; import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY; -public class MetadataServiceNameMapping extends AbstractServiceNameMapping implements ScopeModelAware { +public class MetadataServiceNameMapping extends AbstractServiceNameMapping { private final Logger logger = LoggerFactory.getLogger(getClass()); @@ -47,8 +46,8 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping imple private static final int CAS_RETRY_TIMES = 6; protected MetadataReportInstance metadataReportInstance; - public MetadataServiceNameMapping() { - metadataReportInstance = ApplicationModel.defaultModel().getBeanFactory().getBean(MetadataReportInstance.class); + public MetadataServiceNameMapping(ApplicationModel applicationModel) { + metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class); } @Override @@ -109,12 +108,6 @@ public class MetadataServiceNameMapping extends AbstractServiceNameMapping imple return metadataReport.getServiceAppMapping(serviceInterface, mappingListener, url); } - @Override - public void setApplicationModel(ApplicationModel applicationModel) { - super.setApplicationModel(applicationModel); - metadataReportInstance = applicationModel.getBeanFactory().getBean(MetadataReportInstance.class); - } - protected String getRegistryCluster(URL url) { String registryCluster = RegistryClusterIdentifier.getExtension(url).providerKey(url); if (registryCluster == null) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java index b9b09eedd5..53f09db9db 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/MetadataUtils.java @@ -55,7 +55,7 @@ public class MetadataUtils { WritableMetadataService.getDefaultExtension(url.getScopeModel()).publishServiceDefinition(url); // send to remote if (REMOTE_METADATA_STORAGE_TYPE.equalsIgnoreCase(url.getParameter(METADATA_KEY))) { - getRemoteMetadataService(ScopeModelUtil.getApplicationModel(url.getScopeModel())).publishServiceDefinition(url); + getRemoteMetadataService(url.getOrDefaultApplicationModel()).publishServiceDefinition(url); } } @@ -79,8 +79,8 @@ public class MetadataUtils { private static MetadataService referProxy(String key, ServiceInstance instance) { MetadataServiceURLBuilder builder = null; - ExtensionLoader loader - = ExtensionLoader.getExtensionLoader(MetadataServiceURLBuilder.class); + ExtensionLoader loader = instance.getOrDefaultApplicationModel() + .getExtensionLoader(MetadataServiceURLBuilder.class); Map metadata = instance.getMetadata(); // METADATA_SERVICE_URLS_PROPERTY_NAME is a unique key exists only on instances of spring-cloud-alibaba. diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java index ddf4bd2238..45bd23d52e 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/ServiceInstanceMetadataUtils.java @@ -284,7 +284,7 @@ public class ServiceInstanceMetadataUtils { public static void customizeInstance(ServiceInstance instance) { ExtensionLoader loader = - ExtensionLoader.getExtensionLoader(ServiceInstanceCustomizer.class); + instance.getOrDefaultApplicationModel().getExtensionLoader(ServiceInstanceCustomizer.class); // FIXME, sort customizer before apply loader.getSupportedExtensionInstances().forEach(customizer -> { // customizes diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java index e724467648..3b8685d6dc 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/migration/MigrationInvoker.java @@ -17,7 +17,6 @@ package org.apache.dubbo.registry.client.migration; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.CollectionUtils; @@ -34,6 +33,7 @@ import org.apache.dubbo.rpc.cluster.Cluster; import org.apache.dubbo.rpc.cluster.ClusterInvoker; import org.apache.dubbo.rpc.cluster.Directory; import org.apache.dubbo.rpc.model.ConsumerModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.Map; import java.util.Set; @@ -178,7 +178,8 @@ public class MigrationInvoker implements MigrationClusterInvoker { return true; } - Set detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); + Set detectors = ScopeModelUtil.getApplicationModel(consumerUrl == null ? null : consumerUrl.getScopeModel()) + .getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); if (CollectionUtils.isNotEmpty(detectors)) { if (detectors.stream().allMatch(comparator -> comparator.shouldMigrate(invoker, serviceDiscoveryInvoker, newRule))) { this.currentAvailableInvoker = invoker; @@ -215,7 +216,8 @@ public class MigrationInvoker implements MigrationClusterInvoker { return true; } - Set detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); + Set detectors = ScopeModelUtil.getApplicationModel(consumerUrl == null ? null : consumerUrl.getScopeModel()) + .getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); if (CollectionUtils.isNotEmpty(detectors)) { if (detectors.stream().allMatch(comparator -> comparator.shouldMigrate(serviceDiscoveryInvoker, invoker, newRule))) { this.currentAvailableInvoker = serviceDiscoveryInvoker; @@ -461,7 +463,8 @@ public class MigrationInvoker implements MigrationClusterInvoker { if (serviceDiscoveryInvoker == null || invoker == null) { return; } - Set detectors = ExtensionLoader.getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); + Set detectors = ScopeModelUtil.getApplicationModel(consumerUrl == null ? null : consumerUrl.getScopeModel()) + .getExtensionLoader(MigrationAddressComparator.class).getSupportedExtensionInstances(); if (CollectionUtils.isNotEmpty(detectors)) { // pick preferred invoker // the real invoker choice in invocation will be affected by promotion diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java index 87abfc71ac..d9dbcfa024 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java @@ -106,7 +106,10 @@ public abstract class AbstractConfiguratorListener implements ConfigurationListe try { // parseConfigurators will recognize app/service config automatically. List urls = ConfigParser.parseConfigurators(rawConfig); - List safeUrls = urls.stream().map(url -> url.removeParameters(securityKey)).collect(Collectors.toList()); + List safeUrls = urls.stream() + .map(url -> url.removeParameters(securityKey)) + .map(url -> url.setScopeModel(applicationModel)) + .collect(Collectors.toList()); configurators = Configurator.toConfigurators(safeUrls).orElse(configurators); } catch (Exception e) { logger.error("Failed to parse raw dynamic config and it will not take effect, the raw config is: " + diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java index ec23771368..97a5902d33 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DynamicDirectory.java @@ -56,10 +56,9 @@ public abstract class DynamicDirectory extends AbstractDirectory implement private static final Logger logger = LoggerFactory.getLogger(DynamicDirectory.class); - protected static final Cluster CLUSTER = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension(); + protected final Cluster cluster; - protected static final RouterFactory ROUTER_FACTORY = ExtensionLoader.getExtensionLoader(RouterFactory.class) - .getAdaptiveExtension(); + protected final RouterFactory routerFactory; /** * Initialization at construction time, assertion not null @@ -113,6 +112,9 @@ public abstract class DynamicDirectory extends AbstractDirectory implement public DynamicDirectory(Class serviceType, URL url) { super(url, true); + this.cluster = url.getOrDefaultApplicationModel().getExtensionLoader(Cluster.class).getAdaptiveExtension(); + this.routerFactory = url.getOrDefaultApplicationModel().getExtensionLoader(RouterFactory.class).getAdaptiveExtension(); + if (serviceType == null) { throw new IllegalArgumentException("service type is null."); } @@ -280,7 +282,7 @@ public abstract class DynamicDirectory extends AbstractDirectory implement logger.warn("unexpected error when unsubscribe service " + serviceKey + " from registry: " + registry.getUrl(), t); } - ExtensionLoader addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class); + ExtensionLoader addressListenerExtensionLoader = getUrl().getOrDefaultApplicationModel().getExtensionLoader(AddressListener.class); List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); if (supportedListeners != null && !supportedListeners.isEmpty()) { for (AddressListener addressListener : supportedListeners) { diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java index 4fa1f7680f..92d08807e5 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java @@ -146,7 +146,7 @@ public class RegistryDirectory extends DynamicDirectory { List providerURLs = categoryUrls.getOrDefault(PROVIDERS_CATEGORY, Collections.emptyList()); // 3.x added for extend URL address - ExtensionLoader addressListenerExtensionLoader = ExtensionLoader.getExtensionLoader(AddressListener.class); + ExtensionLoader addressListenerExtensionLoader = getUrl().getOrDefaultApplicationModel().getExtensionLoader(AddressListener.class); List supportedListeners = addressListenerExtensionLoader.getActivateExtension(getUrl(), (String[]) null); if (supportedListeners != null && !supportedListeners.isEmpty()) { for (AddressListener addressListener : supportedListeners) { @@ -265,7 +265,7 @@ public class RegistryDirectory extends DynamicDirectory { for (List> groupList : groupMap.values()) { StaticDirectory staticDirectory = new StaticDirectory<>(groupList); staticDirectory.buildRouterChain(); - mergedInvokers.add(CLUSTER.join(staticDirectory)); + mergedInvokers.add(cluster.join(staticDirectory)); } } else { mergedInvokers = invokers; @@ -293,7 +293,7 @@ public class RegistryDirectory extends DynamicDirectory { url = url.setProtocol(routerType); } try { - Router router = ROUTER_FACTORY.getRouter(url); + Router router = routerFactory.getRouter(url); if (!routers.contains(router)) { routers.add(router); } @@ -335,11 +335,11 @@ public class RegistryDirectory extends DynamicDirectory { if (EMPTY_PROTOCOL.equals(providerUrl.getProtocol())) { continue; } - if (!ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) { + if (!getUrl().getOrDefaultFrameworkModel().getExtensionLoader(Protocol.class).hasExtension(providerUrl.getProtocol())) { logger.error(new IllegalStateException("Unsupported protocol " + providerUrl.getProtocol() + " in notified url: " + providerUrl + " from registry " + getUrl().getAddress() + " to consumer " + NetUtils.getLocalHost() + ", supported protocol: " + - ExtensionLoader.getExtensionLoader(Protocol.class).getSupportedExtensions())); + getUrl().getOrDefaultFrameworkModel().getExtensionLoader(Protocol.class).getSupportedExtensions())); continue; } URL url = mergeUrl(providerUrl); @@ -381,7 +381,7 @@ public class RegistryDirectory extends DynamicDirectory { if (providerUrl instanceof ServiceAddressURL) { providerUrl = overrideWithConfigurator(providerUrl); } else { - providerUrl = ClusterUtils.mergeUrl(providerUrl, queryMap); // Merge the consumer side parameters + providerUrl = applicationModel.getBeanFactory().getBean(ClusterUtils.class).mergeUrl(providerUrl, queryMap); // Merge the consumer side parameters providerUrl = overrideWithConfigurator(providerUrl); providerUrl = providerUrl.addParameter(Constants.CHECK_KEY, String.valueOf(false)); // Do not check whether the connection is successful or not, always create Invoker! } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java index 9fb5b0627a..6f92fe0a3b 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java @@ -472,11 +472,11 @@ public class RegistryProtocol implements Protocol, ScopeModelAware { String group = qs.get(GROUP_KEY); if (group != null && group.length() > 0) { if ((COMMA_SPLIT_PATTERN.split(group)).length > 1 || "*".equals(group)) { - return doRefer(Cluster.getCluster(MergeableCluster.NAME), registry, type, url, qs); + return doRefer(Cluster.getCluster(url.getScopeModel(), MergeableCluster.NAME), registry, type, url, qs); } } - Cluster cluster = Cluster.getCluster(qs.get(CLUSTER_KEY)); + Cluster cluster = Cluster.getCluster(url.getScopeModel(), qs.get(CLUSTER_KEY)); return doRefer(cluster, registry, type, url, qs); } diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java index c356cea38b..45066f242f 100644 --- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java +++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/CacheableFailbackRegistry.java @@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.common.URLBuilder; import org.apache.dubbo.common.URLStrParser; import org.apache.dubbo.common.config.ConfigurationUtils; -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; @@ -34,7 +33,6 @@ import org.apache.dubbo.common.utils.UrlUtils; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.ProviderFirstParams; import org.apache.dubbo.rpc.model.ScopeModel; -import org.apache.dubbo.rpc.model.ScopeModelUtil; import java.util.ArrayList; import java.util.Collection; @@ -85,7 +83,7 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry { extraParameters = new HashMap<>(8); extraParameters.put(CHECK_KEY, String.valueOf(false)); - cacheRemovalScheduler = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getExtensionLoader(ExecutorRepository.class).getDefaultExtension().nextScheduledExecutor(); + cacheRemovalScheduler = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class).getDefaultExtension().nextScheduledExecutor(); cacheRemovalTaskIntervalInMillis = getIntConfig(url.getScopeModel(), CACHE_CLEAR_TASK_INTERVAL, 2 * 60 * 1000); cacheClearWaitingThresholdInMillis = getIntConfig(url.getScopeModel(), CACHE_CLEAR_WAITING_THRESHOLD, 5 * 60 * 1000); } @@ -232,7 +230,7 @@ public abstract class CacheableFailbackRegistry extends FailbackRegistry { } protected URL removeParamsFromConsumer(URL consumer) { - Set providerFirstParams = ExtensionLoader.getExtensionLoader(ProviderFirstParams.class).getSupportedExtensionInstances(); + Set providerFirstParams = consumer.getOrDefaultApplicationModel().getExtensionLoader(ProviderFirstParams.class).getSupportedExtensionInstances(); if (CollectionUtils.isEmpty(providerFirstParams)) { return consumer; } diff --git a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer new file mode 100644 index 0000000000..75c3a85e4b --- /dev/null +++ b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.rpc.model.ScopeModelInitializer @@ -0,0 +1 @@ +dubbo-registry-api=org.apache.dubbo.registry.RegistryScopeModelInitializer diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java index f8378d42aa..6d4e855215 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/ServiceDiscoveryRegistryTest.java @@ -28,8 +28,6 @@ import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; -import org.mockito.MockedStatic; -import org.mockito.Mockito; import java.util.ArrayList; import java.util.Collections; @@ -50,7 +48,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -59,7 +56,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.Mockito.withSettings; public class ServiceDiscoveryRegistryTest { public static final String APP_NAME1 = "app1"; @@ -97,6 +93,9 @@ public class ServiceDiscoveryRegistryTest { doNothing().when(instanceListener).onEvent(any()); when(serviceDiscovery.createListener(any())).thenReturn(instanceListener); when(serviceDiscovery.getInstances(any())).thenReturn(Collections.emptyList()); + ApplicationModel applicationModel = spy(ApplicationModel.defaultModel()); + when(applicationModel.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping); + registryURL = registryURL.setScopeModel(applicationModel); spiedMetadataService = spy(WritableMetadataService.getDefaultExtension(ApplicationModel.defaultModel())); serviceDiscoveryRegistry = new ServiceDiscoveryRegistry(registryURL, serviceDiscovery, spiedMetadataService); @@ -160,59 +159,56 @@ public class ServiceDiscoveryRegistryTest { */ @Test public void testSubscribeURLs() { - try (MockedStatic mockStaticMapping = Mockito.mockStatic(ServiceNameMapping.class, withSettings().defaultAnswer(CALLS_REAL_METHODS))) { - mockStaticMapping.when(ServiceNameMapping::getDefaultExtension).thenReturn(mapping); - // interface to single app mapping - Set singleApp = new TreeSet<>(); - singleApp.add(APP_NAME1); - serviceDiscoveryRegistry.subscribeURLs(url, testServiceListener, singleApp); + // interface to single app mapping + Set singleApp = new TreeSet<>(); + singleApp.add(APP_NAME1); + serviceDiscoveryRegistry.subscribeURLs(url, testServiceListener, singleApp); - assertEquals(1, serviceDiscoveryRegistry.getServiceListeners().size()); - verify(testServiceListener, times(1)).addServiceListener(instanceListener); - verify(instanceListener, never()).onEvent(any()); - verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(instanceListener); + assertEquals(1, serviceDiscoveryRegistry.getServiceListeners().size()); + verify(testServiceListener, times(1)).addServiceListener(instanceListener); + verify(instanceListener, never()).onEvent(any()); + verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(instanceListener); - // interface to multiple apps mapping - Set multiApps = new TreeSet<>(); - multiApps.add(APP_NAME1); - multiApps.add(APP_NAME2); - MockServiceInstancesChangedListener multiAppsInstanceListener = spy(new MockServiceInstancesChangedListener(multiApps, serviceDiscovery)); - doNothing().when(multiAppsInstanceListener).onEvent(any()); - List urls = new ArrayList<>(); - urls.add(URL.valueOf("dubbo://127.0.0.1:20880/TestService")); - doReturn(urls).when(multiAppsInstanceListener).getAddresses(any(), any()); - when(serviceDiscovery.createListener(multiApps)).thenReturn(multiAppsInstanceListener); - when(serviceDiscovery.getInstances(APP_NAME1)).thenReturn(instanceList1); - when(serviceDiscovery.getInstances(APP_NAME2)).thenReturn(instanceList2); - serviceDiscoveryRegistry.subscribeURLs(url, testServiceListener, multiApps); + // interface to multiple apps mapping + Set multiApps = new TreeSet<>(); + multiApps.add(APP_NAME1); + multiApps.add(APP_NAME2); + MockServiceInstancesChangedListener multiAppsInstanceListener = spy(new MockServiceInstancesChangedListener(multiApps, serviceDiscovery)); + doNothing().when(multiAppsInstanceListener).onEvent(any()); + List urls = new ArrayList<>(); + urls.add(URL.valueOf("dubbo://127.0.0.1:20880/TestService")); + doReturn(urls).when(multiAppsInstanceListener).getAddresses(any(), any()); + when(serviceDiscovery.createListener(multiApps)).thenReturn(multiAppsInstanceListener); + when(serviceDiscovery.getInstances(APP_NAME1)).thenReturn(instanceList1); + when(serviceDiscovery.getInstances(APP_NAME2)).thenReturn(instanceList2); + serviceDiscoveryRegistry.subscribeURLs(url, testServiceListener, multiApps); - assertEquals(2, serviceDiscoveryRegistry.getServiceListeners().size()); - assertEquals(instanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(singleApp))); - assertEquals(multiAppsInstanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(multiApps))); - verify(testServiceListener, times(1)).addServiceListener(multiAppsInstanceListener); - verify(multiAppsInstanceListener, times(2)).onEvent(any()); - verify(multiAppsInstanceListener, times(1)).addListenerAndNotify(any(), eq(testServiceListener)); - verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(multiAppsInstanceListener); - ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); - verify(testServiceListener).notify(captor.capture()); - assertEquals(urls, captor.getValue()); + assertEquals(2, serviceDiscoveryRegistry.getServiceListeners().size()); + assertEquals(instanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(singleApp))); + assertEquals(multiAppsInstanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(multiApps))); + verify(testServiceListener, times(1)).addServiceListener(multiAppsInstanceListener); + verify(multiAppsInstanceListener, times(2)).onEvent(any()); + verify(multiAppsInstanceListener, times(1)).addListenerAndNotify(any(), eq(testServiceListener)); + verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(multiAppsInstanceListener); + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + verify(testServiceListener).notify(captor.capture()); + assertEquals(urls, captor.getValue()); - // different interface mapping to the same apps - NotifyListener testServiceListener2 = mock(NotifyListener.class); - URL url2 = URL.valueOf("consumer://127.0.0.1/TestService2?interface=TestService1&check=false&protocol=tri"); - serviceDiscoveryRegistry.subscribeURLs(url2, testServiceListener2, multiApps); - // check instance listeners not changed, methods not called - assertEquals(2, serviceDiscoveryRegistry.getServiceListeners().size()); - assertEquals(multiAppsInstanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(multiApps))); - verify(multiAppsInstanceListener, times(1)).addListenerAndNotify(any(), eq(testServiceListener)); - // still called once, not executed this time - verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(multiAppsInstanceListener); - // check different protocol - Map serviceListeners = multiAppsInstanceListener.getServiceListeners(); - assertEquals(2, serviceListeners.size()); - String protocolServiceKey = url2.getServiceKey() + GROUP_CHAR_SEPARATOR + url2.getParameter(PROTOCOL_KEY, DUBBO); - assertEquals(testServiceListener2, serviceListeners.get(protocolServiceKey)); - } + // different interface mapping to the same apps + NotifyListener testServiceListener2 = mock(NotifyListener.class); + URL url2 = URL.valueOf("consumer://127.0.0.1/TestService2?interface=TestService1&check=false&protocol=tri"); + serviceDiscoveryRegistry.subscribeURLs(url2, testServiceListener2, multiApps); + // check instance listeners not changed, methods not called + assertEquals(2, serviceDiscoveryRegistry.getServiceListeners().size()); + assertEquals(multiAppsInstanceListener, serviceDiscoveryRegistry.getServiceListeners().get(toStringKeys(multiApps))); + verify(multiAppsInstanceListener, times(1)).addListenerAndNotify(any(), eq(testServiceListener)); + // still called once, not executed this time + verify(serviceDiscovery, times(1)).addServiceInstancesChangedListener(multiAppsInstanceListener); + // check different protocol + Map serviceListeners = multiAppsInstanceListener.getServiceListeners(); + assertEquals(2, serviceListeners.size()); + String protocolServiceKey = url2.getServiceKey() + GROUP_CHAR_SEPARATOR + url2.getParameter(PROTOCOL_KEY, DUBBO); + assertEquals(testServiceListener2, serviceListeners.get(protocolServiceKey)); } /** diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java index 353c93ba6a..870293f740 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/MetadataServiceNameMappingTest.java @@ -60,7 +60,7 @@ public class MetadataServiceNameMappingTest { applicationModel = new ApplicationModel(FrameworkModel.defaultModel()); configManager = mock(ConfigManager.class); metadataReport = mock(MetadataReport.class); - mapping = new MetadataServiceNameMapping(); + mapping = new MetadataServiceNameMapping(ApplicationModel.defaultModel()); mapping.setApplicationModel(applicationModel); url = URL.valueOf("dubbo://127.0.0.1:20880/TestService?version=1.0.0"); } diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java index 844ab38d15..30ce073885 100644 --- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java +++ b/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/migration/model/MigrationRuleTest.java @@ -20,7 +20,6 @@ import org.apache.dubbo.common.URL; import org.apache.dubbo.metadata.ServiceNameMapping; import org.apache.dubbo.metadata.WritableMetadataService; import org.apache.dubbo.rpc.model.ApplicationModel; -import org.apache.dubbo.rpc.model.ModuleModel; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; @@ -76,7 +75,7 @@ public class MigrationRuleTest { assertEquals(false, migrationRule.getForce()); URL url = Mockito.mock(URL.class); - ModuleModel defaultModule = Mockito.spy(ApplicationModel.defaultModel().getDefaultModule()); + ApplicationModel defaultModule = Mockito.spy(ApplicationModel.defaultModel()); Mockito.when(defaultModule.getDefaultExtension(ServiceNameMapping.class)).thenReturn(mapping); Mockito.when(url.getScopeModel()).thenReturn(defaultModule); diff --git a/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java b/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java index c80cdaaa1d..14089e9f6b 100644 --- a/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java +++ b/dubbo-registry/dubbo-registry-dns/src/test/java/org/apache/dubbo/registry/dns/DNSServiceDiscoveryTest.java @@ -154,8 +154,8 @@ public class DNSServiceDiscoveryTest { serviceInstances = dnsServiceDiscovery.getInstances("Test.Service."); assertEquals("c", serviceInstances.get(0).getMetadata("a")); - dnsServiceDiscovery.addServiceInstancesChangedListener(changedListener); ArgumentCaptor argument = ArgumentCaptor.forClass(ServiceInstancesChangedEvent.class); + dnsServiceDiscovery.addServiceInstancesChangedListener(changedListener); Thread.sleep(1000); Mockito.verify(changedListener, Mockito.timeout(1000)).onEvent(argument.capture()); assertEquals("c", argument.getValue().getServiceInstances().get(0).getMetadata("a")); diff --git a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java index ea2758b87e..4ee590e369 100644 --- a/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java +++ b/dubbo-registry/dubbo-registry-multiple/src/main/java/org/apache/dubbo/registry/multiple/MultipleRegistry.java @@ -19,7 +19,6 @@ package org.apache.dubbo.registry.multiple; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.constants.CommonConstants; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.registry.NotifyListener; import org.apache.dubbo.registry.Registry; @@ -44,7 +43,7 @@ public class MultipleRegistry extends AbstractRegistry { public static final String REGISTRY_FOR_SERVICE = "service-registry"; public static final String REGISTRY_FOR_REFERENCE = "reference-registry"; - protected RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); + protected RegistryFactory registryFactory; private final Map serviceRegistries = new ConcurrentHashMap<>(4); private final Map referenceRegistries = new ConcurrentHashMap(4); private final Map multipleNotifyListenerMap = new ConcurrentHashMap(32); @@ -57,6 +56,7 @@ public class MultipleRegistry extends AbstractRegistry { public MultipleRegistry(URL url) { this(url, true, true); + this.registryFactory = url.getOrDefaultApplicationModel().getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); boolean defaultRegistry = url.getParameter(CommonConstants.DEFAULT_KEY, true); if (defaultRegistry && effectServiceRegistryURLs.isEmpty() && effectReferenceRegistryURLs.isEmpty()) { @@ -69,6 +69,8 @@ public class MultipleRegistry extends AbstractRegistry { super(url); this.registryUrl = url; this.applicationName = url.getApplication(); + this.registryFactory = url.getOrDefaultApplicationModel().getExtensionLoader(RegistryFactory.class).getAdaptiveExtension(); + init(); checkApplicationName(this.applicationName); // This urls contain parameter and it donot inherit from the parameter of url in MultipleRegistry diff --git a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java index f8ff6cac69..c5dd522cea 100644 --- a/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java +++ b/dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java @@ -609,7 +609,7 @@ public class NacosRegistry extends FailbackRegistry { private RegistryNotifier notifier; public RegistryChildListenerImpl(String serviceName, URL consumerUrl, NotifyListener listener) { - notifier = new RegistryNotifier(NacosRegistry.this.getDelay()) { + notifier = new RegistryNotifier(getUrl(), NacosRegistry.this.getDelay()) { @Override protected void doNotify(Object rawAddresses) { List instances = (List) rawAddresses; diff --git a/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/util/XdsChannel.java b/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/util/XdsChannel.java index 088729e397..a9843a17d1 100644 --- a/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/util/XdsChannel.java +++ b/dubbo-registry/dubbo-registry-xds/src/main/java/org/apache/dubbo/registry/xds/util/XdsChannel.java @@ -17,7 +17,6 @@ package org.apache.dubbo.registry.xds.util; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.registry.xds.XdsCertificateSigner; @@ -45,7 +44,7 @@ public class XdsChannel { protected XdsChannel(URL url) { ManagedChannel channel1 = null; try { - XdsCertificateSigner signer = ExtensionLoader.getExtensionLoader(XdsCertificateSigner.class).getExtension(url.getParameter("Signer","istio")); + XdsCertificateSigner signer = url.getOrDefaultApplicationModel().getExtensionLoader(XdsCertificateSigner.class).getExtension(url.getParameter("Signer","istio")); XdsCertificateSigner.CertPair certPair = signer.request(url); SslContext context = GrpcSslContexts.forClient() .trustManager(InsecureTrustManagerFactory.INSTANCE) diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java index 3da0d145d6..904e451979 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperRegistry.java @@ -301,7 +301,7 @@ public class ZookeeperRegistry extends CacheableFailbackRegistry { public RegistryChildListenerImpl(URL consumerUrl, String path, NotifyListener listener, CountDownLatch latch) { this.latch = latch; - notifier = new RegistryNotifier(ZookeeperRegistry.this.getDelay()) { + notifier = new RegistryNotifier(getUrl(), ZookeeperRegistry.this.getDelay()) { @Override public void notify(Object rawAddresses) { long delayTime = getDelayTime(); diff --git a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java index 83d2333ff2..c28d35f13c 100644 --- a/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java +++ b/dubbo-registry/dubbo-registry-zookeeper/src/main/java/org/apache/dubbo/registry/zookeeper/ZookeeperServiceDiscoveryChangeWatcher.java @@ -65,7 +65,7 @@ public class ZookeeperServiceDiscoveryChangeWatcher implements CuratorWatcher { this.serviceName = serviceName; this.path = path; this.latch = latch; - this.notifier = new RegistryNotifier(zookeeperServiceDiscovery.getDelay(), + this.notifier = new RegistryNotifier(zookeeperServiceDiscovery.getUrl(), zookeeperServiceDiscovery.getDelay(), ScopeModelUtil.getApplicationModel(zookeeperServiceDiscovery.getUrl().getScopeModel()).getApplicationExecutorRepository().getServiceDiscoveryAddressNotificationExecutor()) { @Override protected void doNotify(Object rawAddresses) { diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java index 5856ba8df4..97062e8d5a 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/Transporters.java @@ -18,7 +18,6 @@ package org.apache.dubbo.remoting; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.remoting.transport.ChannelHandlerAdapter; import org.apache.dubbo.remoting.transport.ChannelHandlerDispatcher; @@ -53,7 +52,7 @@ public class Transporters { } else { handler = new ChannelHandlerDispatcher(handlers); } - return getTransporter().bind(url, handler); + return getTransporter(url).bind(url, handler); } public static Client connect(String url, ChannelHandler... handler) throws RemotingException { @@ -72,11 +71,11 @@ public class Transporters { } else { handler = new ChannelHandlerDispatcher(handlers); } - return getTransporter().connect(url, handler); + return getTransporter(url).connect(url, handler); } - public static Transporter getTransporter() { - return ExtensionLoader.getExtensionLoader(Transporter.class).getAdaptiveExtension(); + public static Transporter getTransporter(URL url) { + return url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getAdaptiveExtension(); } } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/MultiplexProtocolConnectionManager.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/MultiplexProtocolConnectionManager.java index e6f7df0828..f347538639 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/MultiplexProtocolConnectionManager.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/MultiplexProtocolConnectionManager.java @@ -17,8 +17,8 @@ package org.apache.dubbo.remoting.api; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.remoting.RemotingException; +import org.apache.dubbo.rpc.model.FrameworkModel; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -27,6 +27,12 @@ import java.util.function.Consumer; public class MultiplexProtocolConnectionManager implements ConnectionManager { private final ConcurrentMap protocols = new ConcurrentHashMap<>(); + private FrameworkModel frameworkModel; + + public MultiplexProtocolConnectionManager(FrameworkModel frameworkModel) { + this.frameworkModel = frameworkModel; + } + @Override public Connection connect(URL url) throws RemotingException { final ConnectionManager manager = protocols.computeIfAbsent(url.getProtocol(), this::createSingleProtocolConnectionManager); @@ -39,6 +45,6 @@ public class MultiplexProtocolConnectionManager implements ConnectionManager { } private ConnectionManager createSingleProtocolConnectionManager(String protocol) { - return ExtensionLoader.getExtensionLoader(ConnectionManager.class).getExtension("single"); + return frameworkModel.getExtensionLoader(ConnectionManager.class).getExtension("single"); } } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java index 71d8d87da7..5ff946b779 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/api/SslContexts.java @@ -21,7 +21,6 @@ import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.config.SslConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.rpc.model.ScopeModelUtil; import io.netty.handler.ssl.ClientAuth; import io.netty.handler.ssl.OpenSsl; @@ -39,7 +38,7 @@ public class SslContexts { private static final Logger logger = LoggerFactory.getLogger(SslContexts.class); public static SslContext buildServerSslContext(URL url) { - ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager(); + ConfigManager globalConfigManager = url.getOrDefaultApplicationModel().getApplicationConfigManager(); SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!")); SslContextBuilder sslClientContextBuilder; @@ -68,7 +67,7 @@ public class SslContexts { } public static SslContext buildClientSslContext(URL url) { - ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager(); + ConfigManager globalConfigManager = url.getOrDefaultApplicationModel().getApplicationConfigManager(); SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!")); SslContextBuilder builder = SslContextBuilder.forClient(); diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java index f3aadd204e..63a0ece0ab 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/exchange/Exchangers.java @@ -18,7 +18,6 @@ package org.apache.dubbo.remoting.exchange; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.remoting.ChannelHandler; import org.apache.dubbo.remoting.Constants; import org.apache.dubbo.remoting.RemotingException; @@ -111,11 +110,7 @@ public class Exchangers { public static Exchanger getExchanger(URL url) { String type = url.getParameter(Constants.EXCHANGER_KEY, Constants.DEFAULT_EXCHANGER); - return getExchanger(type); - } - - public static Exchanger getExchanger(String type) { - return ExtensionLoader.getExtensionLoader(Exchanger.class).getExtension(type); + return url.getOrDefaultFrameworkModel().getExtensionLoader(Exchanger.class).getExtension(type); } } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractClient.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractClient.java index f483b01375..a1447ff009 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractClient.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractClient.java @@ -18,7 +18,6 @@ package org.apache.dubbo.remoting.transport; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.Version; -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; @@ -49,10 +48,11 @@ public abstract class AbstractClient extends AbstractEndpoint implements Client private final Lock connectLock = new ReentrantLock(); private final boolean needReconnect; protected volatile ExecutorService executor; - private ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + private ExecutorRepository executorRepository; public AbstractClient(URL url, ChannelHandler handler) throws RemotingException { super(url, handler); + executorRepository = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); // set default needReconnect true when channel is not connected needReconnect = url.getParameter(Constants.SEND_RECONNECT_KEY, true); diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java index 716eaf64b7..8a6ed0c1d5 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/AbstractServer.java @@ -17,7 +17,6 @@ package org.apache.dubbo.remoting.transport; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; @@ -50,10 +49,11 @@ public abstract class AbstractServer extends AbstractEndpoint implements Remotin private InetSocketAddress bindAddress; private int accepts; - private ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + private ExecutorRepository executorRepository; public AbstractServer(URL url, ChannelHandler handler) throws RemotingException { super(url, handler); + executorRepository = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); localAddress = getUrl().toInetSocketAddress(); String bindIp = getUrl().getParameter(Constants.BIND_IP_KEY, getUrl().getHost()); diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java index 7693407989..650e783653 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/CodecSupport.java @@ -79,7 +79,7 @@ public class CodecSupport { } public static Serialization getSerialization(URL url) { - return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension( + return url.getOrDefaultFrameworkModel().getExtensionLoader(Serialization.class).getExtension( url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION)); } diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelHandlers.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelHandlers.java index 1ec59617ad..42fdcaf3dd 100644 --- a/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelHandlers.java +++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/remoting/transport/dispatcher/ChannelHandlers.java @@ -17,7 +17,6 @@ package org.apache.dubbo.remoting.transport.dispatcher; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.remoting.ChannelHandler; import org.apache.dubbo.remoting.Dispatcher; import org.apache.dubbo.remoting.exchange.support.header.HeartbeatHandler; @@ -43,7 +42,7 @@ public class ChannelHandlers { } protected ChannelHandler wrapInternal(ChannelHandler handler, URL url) { - return new MultiMessageHandler(new HeartbeatHandler(ExtensionLoader.getExtensionLoader(Dispatcher.class) + return new MultiMessageHandler(new HeartbeatHandler(url.getOrDefaultFrameworkModel().getExtensionLoader(Dispatcher.class) .getAdaptiveExtension().dispatch(handler, url))); } } diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java index 19a0434cfc..3a4e21613d 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/Invocation.java @@ -17,6 +17,8 @@ package org.apache.dubbo.rpc; import org.apache.dubbo.common.Experimental; +import org.apache.dubbo.rpc.model.ModuleModel; +import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.model.ServiceModel; import java.util.Map; @@ -46,6 +48,7 @@ public interface Invocation { /** * get the interface name + * * @return */ String getServiceName(); @@ -65,8 +68,8 @@ public interface Invocation { */ default String[] getCompatibleParamSignatures() { return Stream.of(getParameterTypes()) - .map(Class::getName) - .toArray(String[]::new); + .map(Class::getName) + .toArray(String[]::new); } /** @@ -143,6 +146,10 @@ public interface Invocation { ServiceModel getServiceModel(); + default ModuleModel getModuleModel() { + return ScopeModelUtil.getModuleModel(getServiceModel() == null ? null : getServiceModel().getModuleModel()); + } + Object put(Object key, Object value); Object get(Object key); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java index 73f529798e..183b2adc58 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/filter/GenericFilter.java @@ -22,7 +22,6 @@ import org.apache.dubbo.common.beanutil.JavaBeanSerializeUtil; import org.apache.dubbo.common.config.Configuration; import org.apache.dubbo.common.constants.CommonConstants; import org.apache.dubbo.common.extension.Activate; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.io.UnsafeByteArrayInputStream; import org.apache.dubbo.common.io.UnsafeByteArrayOutputStream; import org.apache.dubbo.common.logger.Logger; @@ -131,7 +130,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware { for (int i = 0; i < args.length; i++) { if (byte[].class == args[i].getClass()) { try (UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream((byte[]) args[i])) { - args[i] = ExtensionLoader.getExtensionLoader(Serialization.class) + args[i] = applicationModel.getExtensionLoader(Serialization.class) .getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA) .deserialize(null, is).readObject(); } catch (Exception e) { @@ -166,7 +165,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware { if (args.length == 1 && args[0] instanceof String) { try (UnsafeByteArrayInputStream is = new UnsafeByteArrayInputStream(((String) args[0]).getBytes())) { - args[0] = ExtensionLoader.getExtensionLoader(Serialization.class) + args[0] = applicationModel.getExtensionLoader(Serialization.class) .getExtension(GENERIC_SERIALIZATION_PROTOBUF) .deserialize(null, is).readObject(method.getParameterTypes()[0]); } catch (Exception e) { @@ -236,7 +235,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware { if (ProtocolUtils.isJavaGenericSerialization(generic)) { try { UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512); - ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA) + applicationModel.getExtensionLoader(Serialization.class).getExtension(GENERIC_SERIALIZATION_NATIVE_JAVA) .serialize(null, os).writeObject(appResponse.getValue()); appResponse.setValue(os.toByteArray()); } catch (IOException e) { @@ -250,7 +249,7 @@ public class GenericFilter implements Filter, Filter.Listener, ScopeModelAware { } else if (ProtocolUtils.isProtobufGenericSerialization(generic)) { try { UnsafeByteArrayOutputStream os = new UnsafeByteArrayOutputStream(512); - ExtensionLoader.getExtensionLoader(Serialization.class) + applicationModel.getExtensionLoader(Serialization.class) .getExtension(GENERIC_SERIALIZATION_PROTOBUF) .serialize(null, os).writeObject(appResponse.getValue()); appResponse.setValue(os.toString()); diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java index 70756d2fa1..282e1bc1c0 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/protocol/AbstractInvoker.java @@ -211,7 +211,7 @@ public abstract class AbstractInvoker implements Invoker { } // server context attachment - ExtensionLoader selectorExtensionLoader = ExtensionLoader.getExtensionLoader(PenetrateAttachmentSelector.class); + ExtensionLoader selectorExtensionLoader = invocation.getModuleModel().getExtensionLoader(PenetrateAttachmentSelector.class); Set supportedSelectors = selectorExtensionLoader.getSupportedExtensions(); if (CollectionUtils.isNotEmpty(supportedSelectors)) { // custom context attachment @@ -293,7 +293,7 @@ public abstract class AbstractInvoker implements Invoker { // -- Protected api protected ExecutorService getCallbackExecutor(URL url, Invocation inv) { - ExecutorService sharedExecutor = ExtensionLoader.getExtensionLoader(ExecutorRepository.class) + ExecutorService sharedExecutor = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class) .getDefaultExtension() .getExecutor(url); if (InvokeMode.SYNC == RpcUtils.getInvokeMode(getUrl(), inv)) { diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java index 801e212a0c..ffc4539d4b 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java +++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/support/MockInvoker.java @@ -17,8 +17,8 @@ package org.apache.dubbo.rpc.support; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.extension.ExtensionDirector; import org.apache.dubbo.common.extension.ExtensionInjector; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ArrayUtils; import org.apache.dubbo.common.utils.ConfigUtils; import org.apache.dubbo.common.utils.PojoUtils; @@ -48,7 +48,7 @@ import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX; import static org.apache.dubbo.rpc.Constants.THROW_PREFIX; final public class MockInvoker implements Invoker { - private final static ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); + private final ProxyFactory proxyFactory; private final static Map> MOCK_MAP = new ConcurrentHashMap>(); private final static Map THROWABLE_MAP = new ConcurrentHashMap(); @@ -58,6 +58,7 @@ final public class MockInvoker implements Invoker { public MockInvoker(URL url, Class type) { this.url = url; this.type = type; + this.proxyFactory = url.getOrDefaultFrameworkModel().getExtensionLoader(ProxyFactory.class).getAdaptiveExtension(); } public static Object parseMockValue(String mock) throws Exception { @@ -169,8 +170,8 @@ final public class MockInvoker implements Invoker { return invoker; } - T mockObject = (T) getMockObject(mock, serviceType); - invoker = PROXY_FACTORY.getInvoker(mockObject, serviceType, url); + T mockObject = (T) getMockObject(url.getOrDefaultApplicationModel().getExtensionDirector(), mock, serviceType); + invoker = proxyFactory.getInvoker(mockObject, serviceType, url); if (MOCK_MAP.size() < 10000) { MOCK_MAP.put(mockService, invoker); } @@ -178,7 +179,7 @@ final public class MockInvoker implements Invoker { } @SuppressWarnings("unchecked") - public static Object getMockObject(String mockService, Class serviceType) { + public static Object getMockObject(ExtensionDirector extensionDirector, String mockService, Class serviceType) { boolean isDefault = ConfigUtils.isDefault(mockService); if (isDefault) { mockService = serviceType.getName() + "Mock"; @@ -190,7 +191,7 @@ final public class MockInvoker implements Invoker { } catch (Exception e) { if (!isDefault) {// does not check Spring bean if it is default config. ExtensionInjector extensionFactory = - ExtensionLoader.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension(); + extensionDirector.getExtensionLoader(ExtensionInjector.class).getAdaptiveExtension(); Object obj = extensionFactory.getInstance(serviceType, mockService); if (obj != null) { return obj; diff --git a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvokerTest.java b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvokerTest.java index 646c789e2e..e1c8f6611f 100644 --- a/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvokerTest.java +++ b/dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/MockInvokerTest.java @@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.support; import org.apache.dubbo.common.URL; import org.apache.dubbo.rpc.RpcException; import org.apache.dubbo.rpc.RpcInvocation; +import org.apache.dubbo.rpc.model.ApplicationModel; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -132,16 +133,16 @@ public class MockInvokerTest { @Test public void testGetMockObject() { Assertions.assertEquals("", - MockInvoker.getMockObject("java.lang.String", String.class)); + MockInvoker.getMockObject(ApplicationModel.defaultModel().getExtensionDirector(), "java.lang.String", String.class)); Assertions.assertThrows(IllegalStateException.class, () -> MockInvoker - .getMockObject("true", String.class)); + .getMockObject(ApplicationModel.defaultModel().getExtensionDirector(), "true", String.class)); Assertions.assertThrows(IllegalStateException.class, () -> MockInvoker - .getMockObject("default", String.class)); + .getMockObject(ApplicationModel.defaultModel().getExtensionDirector(), "default", String.class)); Assertions.assertThrows(IllegalStateException.class, () -> MockInvoker - .getMockObject("java.lang.String", Integer.class)); + .getMockObject(ApplicationModel.defaultModel().getExtensionDirector(), "java.lang.String", Integer.class)); Assertions.assertThrows(IllegalStateException.class, () -> MockInvoker - .getMockObject("java.io.Serializable", Serializable.class)); + .getMockObject(ApplicationModel.defaultModel().getExtensionDirector(), "java.io.Serializable", Serializable.class)); } @Test diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java index ce21fabaf5..2eec406785 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/CallbackServiceCodec.java @@ -37,7 +37,6 @@ 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.ProviderModel; -import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.model.ServiceDescriptor; import org.apache.dubbo.rpc.model.ServiceMetadata; @@ -199,7 +198,7 @@ class CallbackServiceCodec { URL referurl = URL.valueOf("callback://" + url.getAddress() + "/" + clazz.getName() + "?" + INTERFACE_KEY + "=" + clazz.getName()); referurl = referurl.addParametersIfAbsent(url.getParameters()).removeParameter(METHODS_KEY); if (!isInstancesOverLimit(channel, referurl, clazz.getName(), instid, true)) { - ScopeModelUtil.getApplicationModel(url.getScopeModel()).getDefaultModule().getServiceRepository().registerService(clazz); + url.getOrDefaultApplicationModel().getDefaultModule().getServiceRepository().registerService(clazz); @SuppressWarnings("rawtypes") Invoker invoker = new ChannelWrappedInvoker(clazz, channel, referurl, String.valueOf(instid)); proxy = proxyFactory.getProxy(invoker); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java index 68b7dcc6e6..0ed252f543 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcInvocation.java @@ -132,6 +132,7 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec String desc = in.readUTF(); setParameterTypesDesc(desc); + ClassLoader originClassLoader = Thread.currentThread().getContextClassLoader(); try { if (Boolean.parseBoolean(System.getProperty(SERIALIZATION_SECURITY_CHECK_KEY, "true"))) { CodecSupport.checkSerialization(frameworkModel.getServiceRepository(), path, version, serializationType); @@ -170,6 +171,32 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec if (methodDescriptor != null) { pts = methodDescriptor.getParameterClasses(); this.setReturnTypes(methodDescriptor.getReturnTypes()); + + // switch TCCL + if (CollectionUtils.isNotEmpty(providerModels)) { + if (providerModels.size() == 1) { + Thread.currentThread().setContextClassLoader(providerModels.get(0).getClassLoader()); + } else { + // try all providerModels' classLoader can load pts, use the first one + for (ProviderModel providerModel : providerModels) { + ClassLoader classLoader = providerModel.getClassLoader(); + boolean match = true; + for (Class pt : pts) { + try { + if (!pt.equals(classLoader.loadClass(pt.getName()))) { + match = false; + } + } catch (ClassNotFoundException e) { + match = false; + } + } + if (match) { + Thread.currentThread().setContextClassLoader(classLoader); + break; + } + } + } + } } } @@ -217,6 +244,7 @@ public class DecodeableRpcInvocation extends RpcInvocation implements Codec, Dec } catch (ClassNotFoundException e) { throw new IOException(StringUtils.toString("Read invocation data failed.", e)); } finally { + Thread.currentThread().setContextClassLoader(originClassLoader); if (in instanceof Cleanable) { ((Cleanable) in).cleanup(); } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java index d93d3452b8..b8336c7a02 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DecodeableRpcResult.java @@ -81,6 +81,10 @@ public class DecodeableRpcResult extends AppResponse implements Codec, Decodeabl log.debug("Decoding in thread -- [" + thread.getName() + "#" + thread.getId() + "]"); } + // switch TCCL + if (invocation.getServiceModel() != null) { + Thread.currentThread().setContextClassLoader(invocation.getServiceModel().getClassLoader()); + } ObjectInput in = CodecSupport.getSerialization(channel.getUrl(), serializationType) .deserialize(channel.getUrl(), input); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java index dcc7bd57b1..913138dc66 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodec.java @@ -66,10 +66,6 @@ public class DubboCodec extends ExchangeCodec { private CallbackServiceCodec callbackServiceCodec; private FrameworkModel frameworkModel; - public DubboCodec() { - this(FrameworkModel.defaultModel()); - } - public DubboCodec(FrameworkModel frameworkModel) { this.frameworkModel = frameworkModel; callbackServiceCodec = new CallbackServiceCodec(frameworkModel); diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java index 500888fa85..e422685001 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboCodecSupport.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.protocol.dubbo; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.serialize.Serialization; import org.apache.dubbo.remoting.Constants; import org.apache.dubbo.remoting.transport.CodecSupport; @@ -34,7 +33,7 @@ public class DubboCodecSupport { if (serializationTypeObj != null) { return CodecSupport.getSerializationById((byte) serializationTypeObj); } - return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension( + return url.getOrDefaultFrameworkModel().getExtensionLoader(Serialization.class).getExtension( url.getParameter(org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION)); } @@ -47,7 +46,7 @@ public class DubboCodecSupport { return CodecSupport.getSerializationById((byte) serializationTypeObj); } } - return ExtensionLoader.getExtensionLoader(Serialization.class).getExtension( + return url.getOrDefaultFrameworkModel().getExtensionLoader(Serialization.class).getExtension( url.getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION)); } } diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java index a4acc327cc..2c4a8a1983 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/main/java/org/apache/dubbo/rpc/protocol/dubbo/DubboProtocol.java @@ -119,6 +119,10 @@ public class DubboProtocol extends AbstractProtocol { Invocation inv = (Invocation) message; Invoker invoker = getInvoker(channel, inv); inv.setServiceModel(invoker.getUrl().getServiceModel()); + // switch TCCL + if (invoker.getUrl().getServiceModel() != null) { + Thread.currentThread().setContextClassLoader(invoker.getUrl().getServiceModel().getClassLoader()); + } // need to consider backward-compatibility if it's a callback if (Boolean.TRUE.toString().equals(inv.getObjectAttachments().get(IS_CALLBACK_SERVICE_INVOKE))) { String methodsStr = invoker.getUrl().getParameters().get("methods"); @@ -343,7 +347,7 @@ public class DubboProtocol extends AbstractProtocol { .build(); String str = url.getParameter(SERVER_KEY, DEFAULT_REMOTING_SERVER); - if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { + if (str != null && str.length() > 0 && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) { throw new RpcException("Unsupported server type: " + str + ", url: " + url); } @@ -356,7 +360,7 @@ public class DubboProtocol extends AbstractProtocol { str = url.getParameter(CLIENT_KEY); if (str != null && str.length() > 0) { - Set supportedTypes = ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(); + Set supportedTypes = url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(); if (!supportedTypes.contains(str)) { throw new RpcException("Unsupported client type: " + str); } @@ -611,9 +615,9 @@ public class DubboProtocol extends AbstractProtocol { url = url.addParameterIfAbsent(HEARTBEAT_KEY, String.valueOf(DEFAULT_HEARTBEAT)); // BIO is not allowed since it has severe performance issue. - if (str != null && str.length() > 0 && !ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(str)) { + if (str != null && str.length() > 0 && !url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).hasExtension(str)) { throw new RpcException("Unsupported client type: " + str + "," + - " supported client type is " + StringUtils.join(ExtensionLoader.getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); + " supported client type is " + StringUtils.join(url.getOrDefaultFrameworkModel().getExtensionLoader(Transporter.class).getSupportedExtensions(), " ")); } ExchangeClient client; diff --git a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java index 81ca83a6b5..421fbe6040 100644 --- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java +++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/decode/DubboTelnetDecodeTest.java @@ -16,9 +16,6 @@ */ package org.apache.dubbo.rpc.protocol.dubbo.decode; -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.embedded.EmbeddedChannel; import org.apache.dubbo.common.URL; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.url.component.ServiceConfigURL; @@ -41,6 +38,10 @@ import org.apache.dubbo.rpc.model.ModuleServiceRepository; import org.apache.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation; import org.apache.dubbo.rpc.protocol.dubbo.DubboCodec; import org.apache.dubbo.rpc.protocol.dubbo.support.DemoService; + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.embedded.EmbeddedChannel; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeAll; @@ -467,7 +468,7 @@ public class DubboTelnetDecodeTest { ByteBuf dubboByteBuf = Unpooled.buffer(); ChannelBuffer buffer = new NettyBackedChannelBuffer(dubboByteBuf); - DubboCodec dubboCodec = new DubboCodec(); + DubboCodec dubboCodec = new DubboCodec(FrameworkModel.defaultModel()); dubboCodec.encode(new MockChannel(), buffer, request); return dubboByteBuf; diff --git a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java index ac2c4e7239..a6bd20805e 100644 --- a/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java +++ b/dubbo-rpc/dubbo-rpc-grpc/src/main/java/org/apache/dubbo/rpc/protocol/grpc/GrpcOptionsUtils.java @@ -22,7 +22,6 @@ import org.apache.dubbo.common.threadpool.ThreadPool; import org.apache.dubbo.common.utils.CollectionUtils; import org.apache.dubbo.config.SslConfig; import org.apache.dubbo.config.context.ConfigManager; -import org.apache.dubbo.rpc.model.ScopeModelUtil; import org.apache.dubbo.rpc.protocol.grpc.interceptors.ClientInterceptor; import org.apache.dubbo.rpc.protocol.grpc.interceptors.GrpcConfigurator; import org.apache.dubbo.rpc.protocol.grpc.interceptors.ServerInterceptor; @@ -90,14 +89,14 @@ public class GrpcOptionsUtils { } // server interceptors - List serverInterceptors = ExtensionLoader.getExtensionLoader(ServerInterceptor.class) + List serverInterceptors = url.getOrDefaultFrameworkModel().getExtensionLoader(ServerInterceptor.class) .getActivateExtension(url, SERVER_INTERCEPTORS, PROVIDER_SIDE); for (ServerInterceptor serverInterceptor : serverInterceptors) { builder.intercept(serverInterceptor); } // server filters - List transportFilters = ExtensionLoader.getExtensionLoader(ServerTransportFilter.class) + List transportFilters = url.getOrDefaultFrameworkModel().getExtensionLoader(ServerTransportFilter.class) .getActivateExtension(url, TRANSPORT_FILTERS, PROVIDER_SIDE); for (ServerTransportFilter transportFilter : transportFilters) { builder.addTransportFilter(transportFilter.grpcTransportFilter()); @@ -107,7 +106,7 @@ public class GrpcOptionsUtils { if ("direct".equals(thread)) { builder.directExecutor(); } else { - builder.executor(ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url)); + builder.executor(url.getOrDefaultFrameworkModel().getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url)); } // Give users the chance to customize ServerBuilder @@ -130,7 +129,7 @@ public class GrpcOptionsUtils { // client interceptors List interceptors = new ArrayList<>( - ExtensionLoader.getExtensionLoader(ClientInterceptor.class) + url.getOrDefaultFrameworkModel().getExtensionLoader(ClientInterceptor.class) .getActivateExtension(url, CLIENT_INTERCEPTORS, CONSUMER_SIDE) ); @@ -153,7 +152,7 @@ public class GrpcOptionsUtils { } private static SslContext buildServerSslContext(URL url) { - ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager(); + ConfigManager globalConfigManager = url.getOrDefaultApplicationModel().getApplicationConfigManager(); SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!")); SslContextBuilder sslClientContextBuilder = null; @@ -183,7 +182,7 @@ public class GrpcOptionsUtils { } private static SslContext buildClientSslContext(URL url) { - ConfigManager globalConfigManager = ScopeModelUtil.getApplicationModel(url.getScopeModel()).getApplicationConfigManager(); + ConfigManager globalConfigManager = url.getOrDefaultApplicationModel().getApplicationConfigManager(); SslConfig sslConfig = globalConfigManager.getSsl().orElseThrow(() -> new IllegalStateException("Ssl enabled, but no ssl cert information provided!")); diff --git a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java index 5aaaed202c..33a07750f0 100644 --- a/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java +++ b/dubbo-rpc/dubbo-rpc-injvm/src/main/java/org/apache/dubbo/rpc/protocol/injvm/InjvmInvoker.java @@ -17,7 +17,6 @@ package org.apache.dubbo.rpc.protocol.injvm; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.threadpool.manager.ExecutorRepository; import org.apache.dubbo.rpc.AppResponse; import org.apache.dubbo.rpc.AsyncRpcResult; @@ -48,12 +47,13 @@ public class InjvmInvoker extends AbstractInvoker { private final Map> exporterMap; - private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); + private final ExecutorRepository executorRepository; InjvmInvoker(Class type, URL url, String key, Map> exporterMap) { super(type, url); this.key = key; this.exporterMap = exporterMap; + this.executorRepository = url.getOrDefaultApplicationModel().getExtensionLoader(ExecutorRepository.class).getDefaultExtension(); } @Override diff --git a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java index 2d4fd41256..36ebd8812e 100644 --- a/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java +++ b/dubbo-rpc/dubbo-rpc-triple/src/main/java/org/apache/dubbo/rpc/protocol/tri/AbstractServerStream.java @@ -64,7 +64,7 @@ public abstract class AbstractServerStream extends AbstractStream implements Str super(url, executor); this.providerModel = providerModel; this.serialize(getUrl().getParameter(Constants.SERIALIZATION_KEY, Constants.DEFAULT_REMOTING_SERIALIZATION)); - this.headerFilters = ExtensionLoader.getExtensionLoader(HeaderFilter.class).getActivateExtension(url, HEADER_FILTER_KEY); + this.headerFilters = url.getOrDefaultApplicationModel().getExtensionLoader(HeaderFilter.class).getActivateExtension(url, HEADER_FILTER_KEY); } private static Executor lookupExecutor(URL url, ProviderModel providerModel) { diff --git a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DefaultMultipleSerialization.java b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DefaultMultipleSerialization.java index de18d5104e..ad7cd97c90 100644 --- a/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DefaultMultipleSerialization.java +++ b/dubbo-serialization/dubbo-serialization-api/src/main/java/org/apache/dubbo/common/serialize/DefaultMultipleSerialization.java @@ -18,7 +18,6 @@ package org.apache.dubbo.common.serialize; import org.apache.dubbo.common.URL; -import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ClassUtils; import java.io.IOException; @@ -30,7 +29,7 @@ public class DefaultMultipleSerialization implements MultipleSerialization { @Override public void serialize(URL url, String serializeType, String clz, Object obj, OutputStream os) throws IOException { serializeType = convertHessian(serializeType); - final Serialization serialization = ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(serializeType); + final Serialization serialization = url.getOrDefaultFrameworkModel().getExtensionLoader(Serialization.class).getExtension(serializeType); final ObjectOutput serialize = serialization.serialize(null, os); serialize.writeObject(obj); serialize.flushBuffer(); @@ -39,7 +38,7 @@ public class DefaultMultipleSerialization implements MultipleSerialization { @Override public Object deserialize(URL url, String serializeType, String clz, InputStream os) throws IOException, ClassNotFoundException { serializeType = convertHessian(serializeType); - final Serialization serialization = ExtensionLoader.getExtensionLoader(Serialization.class).getExtension(serializeType); + final Serialization serialization = url.getOrDefaultFrameworkModel().getExtensionLoader(Serialization.class).getExtension(serializeType); final Class aClass = ClassUtils.forName(clz); final ObjectInput in = serialization.deserialize(null, os); return in.readObject(aClass); diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java index 2729e6ed37..3976b6290b 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectInput.java @@ -30,19 +30,11 @@ import java.lang.reflect.Type; * Hessian2 object input implementation */ public class Hessian2ObjectInput implements ObjectInput, Cleanable { - - private static ThreadLocal INPUT_TL = ThreadLocal.withInitial(() -> { - Hessian2Input h2i = new Hessian2Input(null); - h2i.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); - h2i.setCloseStreamOnClose(true); - return h2i; - }); - private final Hessian2Input mH2i; public Hessian2ObjectInput(InputStream is) { - mH2i = INPUT_TL.get(); - mH2i.init(is); + mH2i = new Hessian2Input(is); + mH2i.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); } @Override @@ -92,6 +84,9 @@ public class Hessian2ObjectInput implements ObjectInput, Cleanable { @Override public Object readObject() throws IOException { + if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { + mH2i.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); + } return mH2i.readObject(); } @@ -99,11 +94,17 @@ public class Hessian2ObjectInput implements ObjectInput, Cleanable { @SuppressWarnings("unchecked") public T readObject(Class cls) throws IOException, ClassNotFoundException { + if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { + mH2i.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); + } return (T) mH2i.readObject(cls); } @Override public T readObject(Class cls, Type type) throws IOException, ClassNotFoundException { + if (!mH2i.getSerializerFactory().getClassLoader().equals(Thread.currentThread().getContextClassLoader())) { + mH2i.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); + } return readObject(cls); } diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java index 874a2c8b21..858ab57cb0 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2ObjectOutput.java @@ -30,18 +30,11 @@ import java.io.OutputStream; */ public class Hessian2ObjectOutput implements ObjectOutput, Cleanable { - private static ThreadLocal OUTPUT_TL = ThreadLocal.withInitial(() -> { - Hessian2Output h2o = new Hessian2Output(null); - h2o.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); - h2o.setCloseStreamOnClose(true); - return h2o; - }); - private final Hessian2Output mH2o; public Hessian2ObjectOutput(OutputStream os) { - mH2o = OUTPUT_TL.get(); - mH2o.init(os); + mH2o = new Hessian2Output(os); + mH2o.setSerializerFactory(Hessian2FactoryInitializer.getInstance().getSerializerFactory()); } @Override diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java index 6a8db87897..52cf50504d 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/Hessian2SerializerFactory.java @@ -23,9 +23,4 @@ public class Hessian2SerializerFactory extends SerializerFactory { public Hessian2SerializerFactory() { } - @Override - public ClassLoader getClassLoader() { - return Thread.currentThread().getContextClassLoader(); - } - } diff --git a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java index 41c9495595..9d4ccf7aee 100644 --- a/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java +++ b/dubbo-serialization/dubbo-serialization-hessian2/src/main/java/org/apache/dubbo/common/serialize/hessian2/dubbo/AbstractHessian2FactoryInitializer.java @@ -18,18 +18,25 @@ package org.apache.dubbo.common.serialize.hessian2.dubbo; import com.alibaba.com.caucho.hessian.io.SerializerFactory; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + public abstract class AbstractHessian2FactoryInitializer implements Hessian2FactoryInitializer { - private static SerializerFactory SERIALIZER_FACTORY; + private static final Map CL_2_SERIALIZER_FACTORY = new ConcurrentHashMap<>(); @Override public SerializerFactory getSerializerFactory() { - if (SERIALIZER_FACTORY != null) { - return SERIALIZER_FACTORY; + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { + synchronized (AbstractHessian2FactoryInitializer.class) { + if (!CL_2_SERIALIZER_FACTORY.containsKey(classLoader)) { + SerializerFactory serializerFactory = createSerializerFactory(); + CL_2_SERIALIZER_FACTORY.put(classLoader, serializerFactory); + return serializerFactory; + } + } } - synchronized (this) { - SERIALIZER_FACTORY = createSerializerFactory(); - } - return SERIALIZER_FACTORY; + return CL_2_SERIALIZER_FACTORY.get(classLoader); } protected abstract SerializerFactory createSerializerFactory();