Add 3.0 Multi Instance Support (#8662)

* Add ExtensionDirector and Models

* Fix access static getter method of ApplicationModel

* Replace ExtensionFactory with ExtensionInjector

* specify scope of some SPIs

* Support scoped injection for extension

* improve create extension loader logic

* Add ScopeModel and ScopeBeanFactory, fix extension initialization of XxxConfig

* polish doc of scope model

* Extract FrameworkStatusReportService from FrameworkStatusReporter

* Fix application model of default bootstrap instance

* Pass scope model through URL

* Fix scope model of registry, metadata, cluster and so on

* exact ServiceModel from ProviderModel and ConsumerModel

* Add ASF license header for ScopeBeanFactoryInitializer

* Remove unused import

* Remove unused import

* Fix ut in ConfigManagerTest

* Change default Scope Behave

* Resolve recursive creation of Scope Model

* Fix inject default model when scope is parent

* Fix inject default model when scope is parent

* Compact with url without ScopeModel

* Change HttpBinder Scope

* Change some SPIs' scope

* Fix setApplicationModel override issue of MetadataServiceNameMapping

* Default inject ScopeModel in ConfigManager

* Add default Scope for AbstractConfig when init

* Fix field override & Fix ut env

* Fix zk not startup in DubboBootstrapMultiInstanceTest

* Fix ExtensionAccessor not inject in UT of MetricsFilterTest

* Compact old style getName

* Fix UT in DNSServiceDiscoveryTest

* Compact old style ApplicationModel

* Fix UT in DNSServiceDiscoveryTest

* Fix repository changed after ApplicationModel destroyed

* Fix SpringExtensionInjector pollution in UT

* Pass ApplicationModel in ServiceInstance

* reintroduce metadata delay key

* Add Transient on ApplicationModel getter of DefaultServiceInstance

* Fix Configurator Listener in Singleton mode override issue

* Fix Configurator Listener in Singleton mode override issue

* Compact old style getApplication

* Invocation pass ServiceModel

* Compact old style registerConsumer

* Fix NPE in RpcInvocation

* Add ServiceModel pass when init

* Fix ServiceModel cast error

* Add ServiceModel pass when invoke

* Fix NPE when simplify registry url

* Revert "Resolve recursive creation of Scope Model"

This reverts commit 37a99957

* Improve scope model aware

* polish scope model

* Cleanup ApplicationModel.defaultModel usage

* Fix ut

* Compatible with 2.6 Registry

* Fix ut

* Add Callback Service build ProviderModel

* improve scope model of config bean

* Fix scope model of reference/service model

* Revert CallbackServiceCodec for dev

* Fix scope model NPE

* Fix consumer url NPE

* Add Callback Service build ProviderModel

* Fix NPE when destroy

* Fix ut

* add failback logic for ut

* Fix ut

* Add Scope Model check

* Fix uts

* Fix ut in DubboBootstrapTest

* Fix ut in DubboBootstrapTest

* Fix uts

* Reset ApplicationModel Before Test

Co-authored-by: gongdewei <kylixs@qq.com>
This commit is contained in:
Albumen Kevin 2021-09-02 17:54:20 +08:00 committed by GitHub
parent b8de0a7fd5
commit ff39bf36c3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
302 changed files with 5200 additions and 1907 deletions

View File

@ -16,11 +16,12 @@
*/
package org.apache.dubbo.rpc.cluster.filter;
import org.apache.dubbo.common.URL;
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.Invoker;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.util.List;
@ -33,7 +34,8 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
@Override
public <T> Invoker<T> buildInvokerChain(final Invoker<T> originalInvoker, String key, String group) {
Invoker<T> last = originalInvoker;
List<Filter> filters = ExtensionLoader.getExtensionLoader(Filter.class).getActivateExtension(originalInvoker.getUrl(), key, group);
URL url = originalInvoker.getUrl();
List<Filter> filters = ScopeModelUtil.getExtensionLoader(Filter.class, url.getScopeModel()).getActivateExtension(url, key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {
@ -52,7 +54,8 @@ public class DefaultFilterChainBuilder implements FilterChainBuilder {
@Override
public <T> ClusterInvoker<T> buildClusterInvokerChain(final ClusterInvoker<T> originalInvoker, String key, String group) {
ClusterInvoker<T> last = originalInvoker;
List<ClusterFilter> filters = ExtensionLoader.getExtensionLoader(ClusterFilter.class).getActivateExtension(originalInvoker.getUrl(), key, group);
URL url = originalInvoker.getUrl();
List<ClusterFilter> filters = ScopeModelUtil.getExtensionLoader(ClusterFilter.class, url.getScopeModel()).getActivateExtension(url, key, group);
if (!filters.isEmpty()) {
for (int i = filters.size() - 1; i >= 0; i--) {

View File

@ -28,7 +28,9 @@ import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.ClusterInvoker;
import org.apache.dubbo.rpc.cluster.Directory;
@SPI("default")
import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
@SPI(value = "default", scope = APPLICATION)
public interface FilterChainBuilder {
/**
* build consumer/provider filter chain

View File

@ -19,13 +19,13 @@ package org.apache.dubbo.rpc.cluster.filter;
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.common.utils.UrlUtils;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProtocolServer;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.util.List;
@ -39,8 +39,6 @@ import static org.apache.dubbo.common.constants.CommonConstants.SERVICE_FILTER_K
public class ProtocolFilterWrapper implements Protocol {
private final Protocol protocol;
private static final FilterChainBuilder builder
= ExtensionLoader.getExtensionLoader(FilterChainBuilder.class).getDefaultExtension();
public ProtocolFilterWrapper(Protocol protocol) {
if (protocol == null) {
@ -59,14 +57,20 @@ public class ProtocolFilterWrapper implements Protocol {
if (UrlUtils.isRegistry(invoker.getUrl())) {
return protocol.export(invoker);
}
FilterChainBuilder builder = getFilterChainBuilder(invoker.getUrl());
return protocol.export(builder.buildInvokerChain(invoker, SERVICE_FILTER_KEY, CommonConstants.PROVIDER));
}
private <T> FilterChainBuilder getFilterChainBuilder(URL url) {
return ScopeModelUtil.getExtensionLoader(FilterChainBuilder.class, url.getScopeModel()).getDefaultExtension();
}
@Override
public <T> Invoker<T> refer(Class<T> type, URL url) throws RpcException {
if (UrlUtils.isRegistry(url)) {
return protocol.refer(type, url);
}
FilterChainBuilder builder = getFilterChainBuilder(url);
return builder.buildInvokerChain(protocol.refer(type, url), REFERENCE_FILTER_KEY, CommonConstants.CONSUMER);
}

View File

@ -19,8 +19,11 @@ package org.apache.dubbo.rpc.cluster.governance;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository {
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository, ScopeModelAware {
private ApplicationModel applicationModel;
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
@ -47,8 +50,13 @@ public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleReposi
return null;
}
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
private DynamicConfiguration getDynamicConfiguration() {
return ApplicationModel.getEnvironment().getDynamicConfiguration().orElse(null);
return ApplicationModel.ofNullable(applicationModel).getApplicationEnvironment().getDynamicConfiguration().orElse(null);
}
}

View File

@ -19,7 +19,9 @@ package org.apache.dubbo.rpc.cluster.governance;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.extension.SPI;
@SPI("default")
import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
@SPI(value = "default", scope = APPLICATION)
public interface GovernanceRuleRepository {
String DEFAULT_GROUP = "dubbo";

View File

@ -23,6 +23,7 @@ import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.cluster.Constants;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
@ -41,11 +42,11 @@ import java.util.concurrent.atomic.AtomicBoolean;
* if there are multiple invokers and the weights are not the same, then random according to the total weight;
* if there are multiple invokers and the same weight, then randomly called.
*/
public class ShortestResponseLoadBalance extends AbstractLoadBalance {
public class ShortestResponseLoadBalance extends AbstractLoadBalance implements ScopeModelAware {
public static final String NAME = "shortestresponse";
private static final int SLIDE_PERIOD = ApplicationModel.getEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
private int SLIDE_PERIOD = 30_000;
private ConcurrentMap<RpcStatus, SlideWindowData> methodMap = new ConcurrentHashMap<>();
@ -53,6 +54,11 @@ public class ShortestResponseLoadBalance extends AbstractLoadBalance {
private volatile long lastUpdateTime = System.currentTimeMillis();
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
SLIDE_PERIOD = applicationModel.getApplicationEnvironment().getConfiguration().getInt(Constants.SHORTEST_RESPONSE_SLIDE_PERIOD, 30_000);
}
protected static class SlideWindowData {
private final static ExecutorService EXECUTOR_SERVICE = Executors.newSingleThreadExecutor((new NamedThreadFactory("Dubbo-slidePeriod-reset")));

View File

@ -42,7 +42,7 @@ public final class MeshRuleManager {
MeshAppRuleListener meshAppRuleListener = new MeshAppRuleListener(app);
String appRuleDataId = app + MESH_RULE_DATA_ID_SUFFIX;
DynamicConfiguration configuration = ApplicationModel.getEnvironment().getDynamicConfiguration()
DynamicConfiguration configuration = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration()
.orElse(null);
Set<MeshEnvListenerFactory> envListenerFactories = ExtensionLoader.getExtensionLoader(MeshEnvListenerFactory.class).getSupportedExtensionInstances();

View File

@ -48,7 +48,7 @@ public abstract class AbstractCluster implements Cluster {
// AbstractClusterInvoker<T> last = clusterInvoker;
AbstractClusterInvoker<T> last = buildInterceptorInvoker(new ClusterFilterInvoker<>(clusterInvoker));
if (Boolean.parseBoolean(ConfigurationUtils.getProperty(CLUSTER_INTERCEPTOR_COMPATIBLE_KEY, "false"))) {
if (Boolean.parseBoolean(ConfigurationUtils.getProperty(clusterInvoker.getDirectory().getConsumerUrl().getScopeModel(), CLUSTER_INTERCEPTOR_COMPATIBLE_KEY, "false"))) {
return build27xCompatibleClusterInterceptors(clusterInvoker, last);
}
return last;

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.rpc.cluster;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.rpc.AppResponse;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
@ -72,7 +71,6 @@ public class StickyTest {
clusterinvoker = new StickyClusterInvoker<StickyTest>(dic);
ExtensionLoader.resetExtensionLoader(LoadBalance.class);
}
@Test

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.rpc.cluster.directory;
import org.apache.dubbo.rpc.AttachmentsAdapter;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.model.ServiceModel;
import java.util.HashMap;
import java.util.Map;
@ -129,6 +130,16 @@ public class MockDirInvocation implements Invocation {
return null;
}
@Override
public void setServiceModel(ServiceModel serviceModel) {
}
@Override
public ServiceModel getServiceModel() {
return null;
}
@Override
public Map<Object, Object> getAttributes() {
return null;

View File

@ -19,6 +19,8 @@ package org.apache.dubbo.rpc.cluster.loadbalance;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcStatus;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
@ -42,6 +44,7 @@ public class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest {
int loop = 10000;
ShortestResponseLoadBalance lb = new ShortestResponseLoadBalance();
lb.setApplicationModel(ApplicationModel.defaultModel());
for (int i = 0; i < loop; i++) {
Invoker selected = lb.select(weightInvokersSR, null, weightTestInvocation);
@ -74,6 +77,7 @@ public class ShortestResponseLoadBalanceTest extends LoadBalanceBaseTest {
//active -> 0
RpcStatus.endCount(weightInvoker5.getUrl(), weightTestInvocation.getMethodName(), 5000L, true);
ShortestResponseLoadBalance lb = new ShortestResponseLoadBalance();
lb.setApplicationModel(ApplicationModel.defaultModel());
//reset slideWindow
Field lastUpdateTimeField = ReflectUtils.forName(ShortestResponseLoadBalance.class.getName()).getDeclaredField("lastUpdateTime");

View File

@ -20,6 +20,7 @@ package org.apache.dubbo.rpc.cluster.router.mesh.route;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.rpc.cluster.router.mesh.rule.VsDestinationGroup;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
@ -38,11 +39,11 @@ public class MeshRuleManagerTest {
@Test
public void subscribeAppRule() {
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
Optional<DynamicConfiguration> before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration();
try {
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration);
MeshRuleManager.subscribeAppRule("test");
@ -53,7 +54,7 @@ public class MeshRuleManagerTest {
assertEquals("test.MESHAPPRULE", result);
} finally {
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null));
}
@ -61,11 +62,11 @@ public class MeshRuleManagerTest {
@Test
public void register() {
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
Optional<DynamicConfiguration> before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration();
try {
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration);
when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
"kind: VirtualService\n" +
@ -109,17 +110,17 @@ public class MeshRuleManagerTest {
assertEquals(1, result.getVirtualServiceRuleList().size());
assertEquals(0, result.getDestinationRuleList().size());
} finally {
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null));
}
}
@Test
public void unregister() {
Optional<DynamicConfiguration> before = ApplicationModel.getEnvironment().getDynamicConfiguration();
Optional<DynamicConfiguration> before = ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicConfiguration();
try {
DynamicConfiguration dynamicConfiguration = mock(DynamicConfiguration.class);
ApplicationModel.getEnvironment().setDynamicConfiguration(dynamicConfiguration);
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(dynamicConfiguration);
when(dynamicConfiguration.getConfig(anyString(), anyString(), anyLong())).thenReturn("apiVersion: service.dubbo.apache.org/v1alpha1\n" +
"kind: VirtualService\n" +
@ -154,7 +155,7 @@ public class MeshRuleManagerTest {
MeshRuleManager.unregister(meshRuleRouter);
} finally {
ApplicationModel.getEnvironment().setDynamicConfiguration(before.orElse(null));
ApplicationModel.defaultModel().getApplicationEnvironment().setDynamicConfiguration(before.orElse(null));
}
}
}

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.common;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.constants.RemotingConstants;
import org.apache.dubbo.common.url.component.PathURLAddress;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
@ -29,6 +30,8 @@ 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.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceModel;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
@ -122,15 +125,22 @@ class URL implements Serializable {
private transient String serviceKey;
private transient String protocolServiceKey;
protected final Map<String, Object> attributes;
protected URL() {
this.urlAddress = null;
this.urlParam = null;
this.attributes = new HashMap<>();
}
public URL(URLAddress urlAddress, URLParam urlParam) {
this(urlAddress, urlParam, null);
}
public URL(URLAddress urlAddress, URLParam urlParam, Map<String, Object> attributes) {
this.urlAddress = urlAddress;
this.urlParam = urlParam;
this.attributes = (attributes != null ? attributes : new HashMap<>());
}
public URL(String protocol, String host, int port) {
@ -179,6 +189,7 @@ class URL implements Serializable {
this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port);
this.urlParam = URLParam.parse(parameters);
this.attributes = new HashMap<>();
}
protected URL(String protocol,
@ -196,6 +207,7 @@ class URL implements Serializable {
this.urlAddress = new PathURLAddress(protocol, username, password, path, host, port);
this.urlParam = URLParam.parse(parameters);
this.attributes = new HashMap<>();
}
public static URL cacheableValueOf(String url) {
@ -218,6 +230,10 @@ class URL implements Serializable {
return valueOf(url, false);
}
public static URL valueOf(String url, ScopeModel scopeModel) {
return valueOf(url).setScopeModel(scopeModel);
}
/**
* parse normal or encoded url string into strutted URL:
* - dubbo://host:port/path?param=value
@ -271,8 +287,8 @@ class URL implements Serializable {
}
}
}
return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map<String, String>) null)
: new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap);
return newMap.isEmpty() ? new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), (Map<String, String>) null, url.getAttributes())
: new ServiceConfigURL(url.getProtocol(), url.getUsername(), url.getPassword(), url.getHost(), url.getPort(), url.getPath(), newMap, url.getAttributes());
}
public static String encode(String value) {
@ -532,6 +548,22 @@ class URL implements Serializable {
return result;
}
public URL setScopeModel(ScopeModel scopeModel) {
return putAttribute(CommonConstants.SCOPE_MODEL, scopeModel);
}
public ScopeModel getScopeModel() {
return (ScopeModel) getAttribute(CommonConstants.SCOPE_MODEL);
}
public URL setServiceModel(ServiceModel serviceModel) {
return putAttribute(CommonConstants.SERVICE_MODEL, serviceModel);
}
public ServiceModel getServiceModel() {
return (ServiceModel) getAttribute(CommonConstants.SERVICE_MODEL);
}
protected Map<String, Number> getNumbers() {
// concurrent initialization is tolerant
if (numbers == null) {
@ -1449,7 +1481,7 @@ class URL implements Serializable {
}
protected <T extends URL> T newURL(URLAddress urlAddress, URLParam urlParam) {
return (T) new ServiceConfigURL(urlAddress, urlParam, null);
return (T) new ServiceConfigURL(urlAddress, urlParam, attributes);
}
/* methods introduced for CompositeURL, CompositeURL must override to make the implementations meaningful */
@ -1517,27 +1549,30 @@ class URL implements Serializable {
/* Service Config URL, START*/
public Map<String, Object> getAttributes() {
return new HashMap<>();
return attributes;
}
public URL addAttributes(Map<String, Object> attributes) {
attributes.putAll(attributes);
return this;
}
public Object getAttribute(String key) {
return null;
return attributes.get(key);
}
public URL putAttribute(String key, Object obj) {
attributes.put(key, obj);
return this;
}
public URL removeAttribute(String key) {
attributes.remove(key);
return this;
}
public boolean hasAttribute(String key) {
return true;
return attributes.containsKey(key);
}
/* Service Config URL, END*/

View File

@ -19,12 +19,15 @@ package org.apache.dubbo.common;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import static org.apache.dubbo.common.constants.CommonConstants.SCOPE_MODEL;
public final class URLBuilder extends ServiceConfigURL {
private String protocol;
@ -206,6 +209,12 @@ public final class URLBuilder extends ServiceConfigURL {
return this;
}
@Override
public URLBuilder setScopeModel(ScopeModel scopeModel) {
this.attributes.put(SCOPE_MODEL, scopeModel);
return this;
}
@Override
public URLBuilder addParameterAndEncoded(String key, String value) {
if (StringUtils.isEmpty(value)) {

View File

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.beans;
public class ScopeBeanException extends RuntimeException {
public ScopeBeanException(String message, Throwable cause) {
super(message, cause);
}
public ScopeBeanException(String message) {
super(message);
}
}

View File

@ -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.common.beans;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.extension.ExtensionInjector;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
/**
* Inject scope bean to SPI extension instance
*/
public class ScopeBeanExtensionInjector implements ExtensionInjector, ScopeModelAware {
private ScopeModel scopeModel;
private ScopeBeanFactory beanFactory;
@Override
public void setScopeModel(ScopeModel scopeModel) {
this.scopeModel = scopeModel;
this.beanFactory = scopeModel.getBeanFactory();
}
@Override
public <T> T getInstance(Class<T> type, String name) {
return beanFactory.getBean(name, type);
}
}

View File

@ -0,0 +1,195 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.beans.factory;
import org.apache.dubbo.common.beans.ScopeBeanException;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionAccessorAware;
import org.apache.dubbo.common.extension.ExtensionPostProcessor;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* A bean factory for internal sharing.
*/
public class ScopeBeanFactory {
private final ScopeBeanFactory parent;
private ExtensionAccessor extensionAccessor;
private List<ExtensionPostProcessor> extensionPostProcessors;
private Map<Class, AtomicInteger> beanNameIdCounterMap = new ConcurrentHashMap<>();
private List<BeanInfo> registeredBeanInfos = Collections.synchronizedList(new ArrayList<>());
public ScopeBeanFactory(ScopeBeanFactory parent, ExtensionAccessor extensionAccessor) {
this.parent = parent;
this.extensionAccessor = extensionAccessor;
extensionPostProcessors = extensionAccessor.getExtensionDirector().getExtensionPostProcessors();
}
public <T> T registerBean(Class<T> bean) throws ScopeBeanException {
return this.registerBean(null, bean);
}
public <T> T registerBean(String name, Class<T> clazz) throws ScopeBeanException {
T instance = getBean(name, clazz);
if (instance != null) {
throw new ScopeBeanException("already exists bean with same name and type, name=" + name + ", type=" + clazz.getName());
}
try {
instance = clazz.newInstance();
} catch (Throwable e) {
throw new ScopeBeanException("create bean instance failed, type=" + clazz.getName());
}
registerBean(name, instance);
return instance;
}
public void registerBean(Object bean) {
this.registerBean(null, bean);
}
public void registerBean(String name, Object bean) {
// avoid duplicated register same bean
if (containsBean(name, bean)) {
return;
}
Class<?> beanClass = bean.getClass();
if (name == null) {
name = beanClass.getName() + "#" + getNextId(beanClass);
}
initializeBean(name, bean);
registeredBeanInfos.add(new BeanInfo(name, bean));
}
public <T> T registerBeanIfAbsent(Class<T> type) {
return registerBeanIfAbsent(null, type);
}
public <T> T registerBeanIfAbsent(String name, Class<T> type) {
T bean = getBean(name, type);
if (bean == null) {
bean = registerBean(name, type);
}
return bean;
}
public <T> T registerBeanIfAbsent(Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
return registerBeanIfAbsent(null, type, mappingFunction);
}
public <T> T registerBeanIfAbsent(String name, Class<T> type, Function<? super Class<T>, ? extends T> mappingFunction) {
T bean = getBean(name, type);
if (bean == null) {
//TODO add lock
bean = mappingFunction.apply(type);
registerBean(name, bean);
}
return bean;
}
public <T> T initializeBean(T bean) {
this.initializeBean(null, bean);
return bean;
}
private void initializeBean(String name, Object bean) {
try {
if (bean instanceof ExtensionAccessorAware) {
((ExtensionAccessorAware) bean).setExtensionAccessor(extensionAccessor);
}
for (ExtensionPostProcessor processor : extensionPostProcessors) {
processor.postProcessAfterInitialization(bean, name);
}
} catch (Exception e) {
throw new ScopeBeanException("register bean failed! name=" + name + ", type=" + bean.getClass().getName(), e);
}
}
private boolean containsBean(String name, Object bean) {
for (BeanInfo beanInfo : registeredBeanInfos) {
if (beanInfo.instance == bean &&
(name == null || StringUtils.isEquals(name, beanInfo.name))) {
return true;
}
}
return false;
}
private int getNextId(Class<?> beanClass) {
return beanNameIdCounterMap.computeIfAbsent(beanClass, key -> new AtomicInteger()).incrementAndGet();
}
public <T> T getBean(Class<T> type) {
return this.getBean(null, type);
}
public <T> T getBean(String name, Class<T> type) {
T bean = getBeanInternal(name, type);
if (bean == null && parent != null) {
return parent.getBean(name, type);
}
return bean;
}
private <T> T getBeanInternal(String name, Class<T> type) {
List<BeanInfo> candidates = null;
for (BeanInfo beanInfo : registeredBeanInfos) {
// if required bean type is same class/superclass/interface of the registered bean
if (type.isAssignableFrom(beanInfo.instance.getClass())) {
if (StringUtils.isEquals(beanInfo.name, name)) {
return (T) beanInfo.instance;
} else {
if (candidates == null) {
candidates = new ArrayList<>();
}
candidates.add(beanInfo);
}
}
}
// if bean name not matched and only single candidate
if (candidates != null) {
if (candidates.size() == 1) {
return (T) candidates.get(0).instance;
} else if (candidates.size() > 1) {
List<String> candidateBeanNames = candidates.stream().map(beanInfo -> beanInfo.name).collect(Collectors.toList());
throw new ScopeBeanException("expected single matching bean but found " + candidates.size() + " candidates for type [" + type.getName() + "]: " + candidateBeanNames);
}
}
return null;
}
static class BeanInfo {
private String name;
private Object instance;
public BeanInfo(String name, Object instance) {
this.name = name;
this.instance = instance;
}
}
}

View File

@ -0,0 +1,75 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.beans.factory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelPostProcessor;
/**
* Initialize the bean factory for ScopeModel
*/
public abstract class ScopeBeanFactoryInitializer implements ScopeModelPostProcessor {
@Override
public void postProcessScopeModel(ScopeModel scopeModel) {
if (scopeModel instanceof ApplicationModel) {
ApplicationModel applicationModel = (ApplicationModel) scopeModel;
registerApplicationBeans(applicationModel, applicationModel.getBeanFactory());
} else if (scopeModel instanceof FrameworkModel) {
FrameworkModel frameworkModel = (FrameworkModel) scopeModel;
registerFrameworkBeans(frameworkModel, frameworkModel.getBeanFactory());
} else if (scopeModel instanceof ModuleModel) {
ModuleModel moduleModel = (ModuleModel) scopeModel;
registerModuleBeans(moduleModel, moduleModel.getBeanFactory());
}
}
/**
* Initialize beans for framework
*
* @param frameworkModel
* @param beanFactory
*/
protected void registerFrameworkBeans(FrameworkModel frameworkModel, ScopeBeanFactory beanFactory) {
}
/**
* Initialize beans for application
*
* @param applicationModel
* @param beanFactory
*/
protected void registerApplicationBeans(ApplicationModel applicationModel, ScopeBeanFactory beanFactory) {
// beanFactory.registerBean(MetadataReportInstance.class);
// beanFactory.registerBean(RemoteMetadataServiceImpl.class);
}
/**
* Initialize beans for module
*
* @param moduleModel
* @param beanFactory
*/
protected void registerModuleBeans(ModuleModel moduleModel, ScopeBeanFactory beanFactory) {
}
}

View File

@ -16,12 +16,13 @@
*/
package org.apache.dubbo.common.compiler;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
/**
* Compiler. (SPI, Singleton, ThreadSafe)
*/
@SPI("javassist")
@SPI(value = "javassist", scope = ExtensionScope.FRAMEWORK)
public interface Compiler {
/**

View File

@ -16,10 +16,15 @@
*/
package org.apache.dubbo.common.config;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.extension.ExtensionAccessor;
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.StringUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ScopeModelUtil;
import java.io.IOException;
import java.io.StringReader;
@ -48,8 +53,8 @@ public class ConfigurationUtils {
*
* @return
*/
public static Configuration getSystemConfiguration() {
return ApplicationModel.getEnvironment().getSystemConfiguration();
public static Configuration getSystemConfiguration(ScopeModel scopeModel) {
return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getSystemConfiguration();
}
/**
@ -57,8 +62,9 @@ public class ConfigurationUtils {
*
* @return
*/
public static Configuration getEnvConfiguration() {
return ApplicationModel.getEnvironment().getEnvironmentConfiguration();
public static Configuration getEnvConfiguration(ScopeModel scopeModel) {
return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getEnvironmentConfiguration();
}
/**
@ -68,19 +74,20 @@ public class ConfigurationUtils {
*
* @return
*/
public static Configuration getGlobalConfiguration() {
return ApplicationModel.getEnvironment().getConfiguration();
public static Configuration getGlobalConfiguration(ScopeModel scopeModel) {
return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getConfiguration();
}
public static Configuration getDynamicGlobalConfiguration() {
return ApplicationModel.getEnvironment().getDynamicGlobalConfiguration();
public static Configuration getDynamicGlobalConfiguration(ScopeModel scopeModel) {
return ScopeModelUtil.getApplicationModel(scopeModel).getApplicationEnvironment().getDynamicGlobalConfiguration();
}
// FIXME
@SuppressWarnings("deprecation")
public static int getServerShutdownTimeout() {
public static int getServerShutdownTimeout(ScopeModel scopeModel) {
int timeout = DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
Configuration configuration = getGlobalConfiguration();
Configuration configuration = getGlobalConfiguration(scopeModel);
String value = StringUtils.trim(configuration.getString(SHUTDOWN_WAIT_KEY));
if (value != null && value.length() > 0) {
@ -102,29 +109,29 @@ public class ConfigurationUtils {
return timeout;
}
public static String getCachedDynamicProperty(String key, String defaultValue) {
String value = CACHED_DYNAMIC_PROPERTIES.computeIfAbsent(key, _k -> ConfigurationUtils.getDynamicProperty(key, ""));
public static String getCachedDynamicProperty(ScopeModel scopeModel, String key, String defaultValue) {
String value = CACHED_DYNAMIC_PROPERTIES.computeIfAbsent(key, _k -> ConfigurationUtils.getDynamicProperty(scopeModel, key, ""));
return StringUtils.isEmpty(value) ? defaultValue : value;
}
public static String getDynamicProperty(String property) {
return getDynamicProperty(property, null);
public static String getDynamicProperty(ScopeModel scopeModel, String property) {
return getDynamicProperty(scopeModel, property, null);
}
public static String getDynamicProperty(String property, String defaultValue) {
return StringUtils.trim(getDynamicGlobalConfiguration().getString(property, defaultValue));
public static String getDynamicProperty(ScopeModel scopeModel, String property, String defaultValue) {
return StringUtils.trim(getDynamicGlobalConfiguration(scopeModel).getString(property, defaultValue));
}
public static String getProperty(String property) {
return getProperty(property, null);
public static String getProperty(ScopeModel scopeModel, String property) {
return getProperty(scopeModel, property, null);
}
public static String getProperty(String property, String defaultValue) {
return StringUtils.trim(getGlobalConfiguration().getString(property, defaultValue));
public static String getProperty(ScopeModel scopeModel, String property, String defaultValue) {
return StringUtils.trim(getGlobalConfiguration(scopeModel).getString(property, defaultValue));
}
public static int get(String property, int defaultValue) {
return getGlobalConfiguration().getInt(property, defaultValue);
public static int get(ScopeModel scopeModel, String property, int defaultValue) {
return getGlobalConfiguration(scopeModel).getInt(property, defaultValue);
}
public static Map<String, String> parseProperties(String content) throws IOException {
@ -275,4 +282,70 @@ public class ConfigurationUtils {
return ids;
}
/**
* Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
* extension of {@link DynamicConfigurationFactory}
*
* @param name the name of extension of {@link DynamicConfigurationFactory}
* @return non-null
* @see 2.7.4
*/
public static DynamicConfigurationFactory getDynamicConfigurationFactory(ExtensionAccessor extensionAccessor, String name) {
ExtensionLoader<DynamicConfigurationFactory> loader = extensionAccessor.getExtensionLoader(DynamicConfigurationFactory.class);
return loader.getOrDefaultExtension(name);
}
/**
* For compact single instance
*/
@Deprecated
public static Configuration getSystemConfiguration() {
return ApplicationModel.defaultModel().getApplicationEnvironment().getSystemConfiguration();
}
@Deprecated
public static Configuration getEnvConfiguration() {
return ApplicationModel.defaultModel().getApplicationEnvironment().getEnvironmentConfiguration();
}
@Deprecated
public static Configuration getGlobalConfiguration() {
return ApplicationModel.defaultModel().getApplicationEnvironment().getConfiguration();
}
@Deprecated
public static Configuration getDynamicGlobalConfiguration() {
return ApplicationModel.defaultModel().getApplicationEnvironment().getDynamicGlobalConfiguration();
}
@Deprecated
public static String getCachedDynamicProperty(String key, String defaultValue) {
return getCachedDynamicProperty(ApplicationModel.defaultModel(), key, defaultValue);
}
@Deprecated
public static String getDynamicProperty(String property) {
return getDynamicProperty(ApplicationModel.defaultModel(), property);
}
@Deprecated
public static String getDynamicProperty(String property, String defaultValue) {
return getDynamicProperty(ApplicationModel.defaultModel(), property, defaultValue);
}
@Deprecated
public static String getProperty(String property) {
return getProperty(ApplicationModel.defaultModel(), property);
}
@Deprecated
public static String getProperty(String property, String defaultValue) {
return getProperty(ApplicationModel.defaultModel(), property, defaultValue);
}
@Deprecated
public static int get(String property, int defaultValue) {
return get(ApplicationModel.defaultModel(), property, defaultValue);
}
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.config;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.Properties;
@ -26,7 +27,7 @@ import java.util.Properties;
* The smaller value, the higher priority
*
*/
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface OrderedPropertiesProvider {
/**
* order

View File

@ -17,30 +17,15 @@
package org.apache.dubbo.common.config.configcenter;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
* The factory interface to create the instance of {@link DynamicConfiguration}
*/
@SPI("nop") // 2.7.5 change the default SPI implementation
@SPI(value = "nop", scope = ExtensionScope.APPLICATION) // 2.7.5 change the default SPI implementation
public interface DynamicConfigurationFactory {
DynamicConfiguration getDynamicConfiguration(URL url);
/**
* Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
* extension of {@link DynamicConfigurationFactory}
*
* @param name the name of extension of {@link DynamicConfigurationFactory}
* @return non-null
* @see 2.7.4
*/
static DynamicConfigurationFactory getDynamicConfigurationFactory(String name) {
Class<DynamicConfigurationFactory> factoryClass = DynamicConfigurationFactory.class;
ExtensionLoader<DynamicConfigurationFactory> loader = getExtensionLoader(factoryClass);
return loader.getOrDefaultExtension(name);
}
}

View File

@ -464,6 +464,10 @@ public interface CommonConstants {
String SERVICE_NAME_MAPPING_KEY = "service-name-mapping";
String SCOPE_MODEL = "scopeModel";
String SERVICE_MODEL = "serviceModel";
/**
* The property name for {@link NetworkInterface#getDisplayName() the name of network interface} that
* the Dubbo application will be ignored

View File

@ -16,9 +16,10 @@
*/
package org.apache.dubbo.common.context;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface FrameworkExt extends Lifecycle {
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.convert;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
@ -31,7 +32,7 @@ import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
* @param <T> The target type
* @since 2.7.6
*/
@SPI
@SPI(scope = ExtensionScope.FRAMEWORK)
@FunctionalInterface
public interface Converter<S, T> extends Prioritized {

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.convert.multiple;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
@ -32,7 +33,7 @@ import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
* @param <S> The source type
* @since 2.7.6
*/
@SPI
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface MultiValueConverter<S> extends Prioritized {
/**

View File

@ -0,0 +1,45 @@
/*
* 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.extension;
/**
* Uniform accessor for extension
*/
public interface ExtensionAccessor {
ExtensionDirector getExtensionDirector();
default <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
return this.getExtensionDirector().getExtensionLoader(type);
}
default <T> T getExtension(Class<T> type, String name) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getExtension(name) : null;
}
default <T> T getAdaptiveExtension(Class<T> type) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getAdaptiveExtension() : null;
}
default <T> T getDefaultExtension(Class<T> type) {
ExtensionLoader<T> extensionLoader = getExtensionLoader(type);
return extensionLoader != null ? extensionLoader.getDefaultExtension() : null;
}
}

View File

@ -0,0 +1,26 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension;
/**
* SPI extension can implement this aware interface to obtain appropriate {@link ExtensionAccessor} instance.
*/
public interface ExtensionAccessorAware {
void setExtensionAccessor(ExtensionAccessor extensionAccessor);
}

View File

@ -0,0 +1,127 @@
/*
* 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.extension;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
* ExtensionDirector is a scoped extension loader manager.
*
* <p></p>
* <p>ExtensionDirector supports multiple levels, and the child can inherit the parent's extension instances. </p>
* <p>The way to find and create an extension instance is similar to Java classloader.</p>
*/
public class ExtensionDirector implements ExtensionAccessor {
private final ConcurrentMap<Class<?>, ExtensionLoader<?>> extensionLoadersMap = new ConcurrentHashMap<>(64);
private ExtensionDirector parent;
private final ExtensionScope scope;
private List<ExtensionPostProcessor> extensionPostProcessors = new ArrayList<>();
public ExtensionDirector(ExtensionDirector parent, ExtensionScope scope) {
this.parent = parent;
this.scope = scope;
}
public void addExtensionPostProcessor(ExtensionPostProcessor processor) {
if (!this.extensionPostProcessors.contains(processor)) {
this.extensionPostProcessors.add(processor);
}
}
public List<ExtensionPostProcessor> getExtensionPostProcessors() {
return extensionPostProcessors;
}
@Override
public ExtensionDirector getExtensionDirector() {
return this;
}
@Override
public <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
}
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
// 1. find in local cache
ExtensionLoader<T> loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
final SPI annotation = type.getAnnotation(SPI.class);
ExtensionScope scope = annotation.scope();
if (loader == null && scope == ExtensionScope.SELF) {
// create an instance in self scope
loader = createExtensionLoader0(type);
}
// 2. find in parent
if (loader == null) {
if (this.parent != null) {
loader = this.parent.getExtensionLoader(type);
}
}
// 3. create it
if (loader == null) {
loader = createExtensionLoader(type);
}
return loader;
}
private <T> ExtensionLoader<T> createExtensionLoader(Class<T> type) {
ExtensionLoader<T> loader = null;
if (isScopeMatched(type)) {
// if scope is matched, just create it
loader = createExtensionLoader0(type);
} else {
// if scope is not matched, ignore it
}
return loader;
}
private <T> ExtensionLoader<T> createExtensionLoader0(Class<T> type) {
ExtensionLoader<T> loader;
extensionLoadersMap.putIfAbsent(type, new ExtensionLoader<T>(type, this));
loader = (ExtensionLoader<T>) extensionLoadersMap.get(type);
return loader;
}
private boolean isScopeMatched(Class<?> type) {
final SPI defaultAnnotation = type.getAnnotation(SPI.class);
return defaultAnnotation.scope().equals(scope);
}
private static boolean withExtensionAnnotation(Class<?> type) {
return type.isAnnotationPresent(SPI.class);
}
public ExtensionDirector getParent() {
return parent;
}
}

View File

@ -18,9 +18,16 @@ package org.apache.dubbo.common.extension;
/**
* ExtensionFactory
* @deprecated use {@link ExtensionInjector} instead
*/
@SPI
public interface ExtensionFactory {
@Deprecated
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface ExtensionFactory extends ExtensionInjector {
@Override
default <T> T getInstance(Class<T> type, String name) {
return getExtension(type, name);
}
/**
* Get extension.

View File

@ -0,0 +1,37 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension;
/**
* An injector to provide resources for SPI extension.
*/
@SPI(scope = ExtensionScope.SELF)
public interface ExtensionInjector extends ExtensionAccessorAware {
/**
* Get instance of specify type and name.
*
* @param type object type.
* @param name object name.
* @return object instance.
*/
<T> T getInstance(Class<T> type, String name);
@Override
default void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
}
}

View File

@ -17,6 +17,8 @@
package org.apache.dubbo.common.extension;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.context.FrameworkExt;
import org.apache.dubbo.common.context.Lifecycle;
import org.apache.dubbo.common.extension.support.ActivateComparator;
import org.apache.dubbo.common.extension.support.WrapperComparator;
@ -32,6 +34,8 @@ import org.apache.dubbo.common.utils.Holder;
import org.apache.dubbo.common.utils.ReflectUtils;
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 java.io.BufferedReader;
import java.io.InputStreamReader;
@ -90,13 +94,11 @@ public class ExtensionLoader<T> {
private static final Pattern NAME_SEPARATOR = Pattern.compile("\\s*[,]+\\s*");
private static final ConcurrentMap<Class<?>, ExtensionLoader<?>> EXTENSION_LOADERS = new ConcurrentHashMap<>(64);
private static final ConcurrentMap<Class<?>, Object> EXTENSION_INSTANCES = new ConcurrentHashMap<>(64);
private final ConcurrentMap<Class<?>, Object> extensionInstances = new ConcurrentHashMap<>(64);
private final Class<?> type;
private final ExtensionFactory objectFactory;
private final ExtensionInjector injector;
private final ConcurrentMap<Class<?>, String> cachedNames = new ConcurrentHashMap<>();
@ -121,6 +123,9 @@ public class ExtensionLoader<T> {
* Record all unacceptable exceptions when using SPI
*/
private Set<String> unacceptableExceptions = new ConcurrentHashSet<>();
private ExtensionDirector extensionDirector;
private List<ExtensionPostProcessor> extensionPostProcessors;
private Environment environment;
public static void setLoadingStrategies(LoadingStrategy... strategies) {
if (ArrayUtils.isNotEmpty(strategies)) {
@ -152,52 +157,42 @@ public class ExtensionLoader<T> {
return asList(strategies);
}
private ExtensionLoader(Class<?> type) {
ExtensionLoader(Class<?> type, ExtensionDirector extensionDirector) {
this.extensionDirector = extensionDirector;
this.extensionPostProcessors = extensionDirector.getExtensionPostProcessors();
this.type = type;
objectFactory = (type == ExtensionFactory.class ? null : ExtensionLoader.getExtensionLoader(ExtensionFactory.class).getAdaptiveExtension());
this.injector = (type == ExtensionInjector.class ? null : extensionDirector.getExtensionLoader(ExtensionInjector.class)
.getAdaptiveExtension());
}
private static <T> boolean withExtensionAnnotation(Class<T> type) {
return type.isAnnotationPresent(SPI.class);
}
@SuppressWarnings("unchecked")
/**
* @see ApplicationModel#getExtensionDirector()
* @see FrameworkModel#getExtensionDirector()
* @see ModuleModel#getExtensionDirector()
* @see ExtensionDirector#getExtensionLoader(java.lang.Class)
* @deprecated get extension loader from extension director of some module.
*/
@Deprecated
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (type == null) {
throw new IllegalArgumentException("Extension type == null");
}
if (!type.isInterface()) {
throw new IllegalArgumentException("Extension type (" + type + ") is not an interface!");
}
if (!withExtensionAnnotation(type)) {
throw new IllegalArgumentException("Extension type (" + type +
") is not an extension, because it is NOT annotated with @" + SPI.class.getSimpleName() + "!");
}
ExtensionLoader<T> loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
if (loader == null) {
EXTENSION_LOADERS.putIfAbsent(type, new ExtensionLoader<T>(type));
loader = (ExtensionLoader<T>) EXTENSION_LOADERS.get(type);
}
return loader;
return ApplicationModel.defaultModel().getExtensionLoader(type);
}
// For testing purposes only
public static void resetExtensionLoader(Class type) {
ExtensionLoader loader = EXTENSION_LOADERS.get(type);
if (loader != null) {
// Remove all instances associated with this loader as well
Map<String, Class<?>> classes = loader.getExtensionClasses();
for (Map.Entry<String, Class<?>> entry : classes.entrySet()) {
EXTENSION_INSTANCES.remove(entry.getValue());
}
classes.clear();
EXTENSION_LOADERS.remove(type);
}
// ExtensionLoader loader = EXTENSION_LOADERS.get(type);
// if (loader != null) {
// // Remove all instances associated with this loader as well
// Map<String, Class<?>> classes = loader.getExtensionClasses();
// for (Map.Entry<String, Class<?>> entry : classes.entrySet()) {
// EXTENSION_INSTANCES.remove(entry.getValue());
// }
// classes.clear();
// EXTENSION_LOADERS.remove(type);
// }
}
public static void destroyAll() {
EXTENSION_INSTANCES.forEach((_type, instance) -> {
public void destroy() {
extensionInstances.forEach((_type, instance) -> {
if (instance instanceof Lifecycle) {
Lifecycle lifecycle = (Lifecycle) instance;
try {
@ -207,13 +202,9 @@ public class ExtensionLoader<T> {
}
}
});
extensionInstances.clear();
// TODO Improve extension loader, clear static refer extension instance.
// Some extension instances may be referenced by static fields, if clear EXTENSION_INSTANCES may cause inconsistent.
// e.g. org.apache.dubbo.registry.client.metadata.MetadataUtils.localMetadataService
// EXTENSION_INSTANCES.clear();
EXTENSION_LOADERS.clear();
// TODO destroy extension loader, release resources.
}
private static ClassLoader findClassLoader() {
@ -695,16 +686,16 @@ public class ExtensionLoader<T> {
throw findException(name);
}
try {
T instance = (T) EXTENSION_INSTANCES.get(clazz);
T instance = (T) extensionInstances.get(clazz);
if (instance == null) {
EXTENSION_INSTANCES.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
instance = (T) EXTENSION_INSTANCES.get(clazz);
extensionInstances.putIfAbsent(clazz, clazz.getDeclaredConstructor().newInstance());
instance = (T) extensionInstances.get(clazz);
}
instance = postProcessBeforeInitialization(instance, name);
injectExtension(instance);
instance = postProcessAfterInitialization(instance, name);
if (wrap) {
List<Class<?>> wrapperClassesList = new ArrayList<>();
if (cachedWrapperClasses != null) {
wrapperClassesList.addAll(cachedWrapperClasses);
@ -718,6 +709,7 @@ public class ExtensionLoader<T> {
if (wrapper == null
|| (ArrayUtils.contains(wrapper.matches(), name) && !ArrayUtils.contains(wrapper.mismatches(), name))) {
instance = injectExtension((T) wrapperClass.getConstructor(type).newInstance(instance));
instance = postProcessAfterInitialization(instance, name);
}
}
}
@ -732,13 +724,34 @@ public class ExtensionLoader<T> {
}
}
private T postProcessBeforeInitialization(T instance, String name) throws Exception {
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
instance = (T) processor.postProcessBeforeInitialization(instance, name);
}
}
return instance;
}
private T postProcessAfterInitialization(T instance, String name) throws Exception {
if (instance instanceof ExtensionAccessorAware) {
((ExtensionAccessorAware) instance).setExtensionAccessor(extensionDirector);
}
if (extensionPostProcessors != null) {
for (ExtensionPostProcessor processor : extensionPostProcessors) {
instance = (T) processor.postProcessAfterInitialization(instance, name);
}
}
return instance;
}
private boolean containsExtension(String name) {
return getExtensionClasses().containsKey(name);
}
private T injectExtension(T instance) {
if (objectFactory == null) {
if (injector == null) {
return instance;
}
@ -760,7 +773,7 @@ public class ExtensionLoader<T> {
try {
String property = getSetterProperty(method);
Object object = objectFactory.getExtension(pt, property);
Object object = injector.getInstance(pt, property);
if (object != null) {
method.invoke(instance, object);
}
@ -840,13 +853,25 @@ public class ExtensionLoader<T> {
Map<String, Class<?>> extensionClasses = new HashMap<>();
for (LoadingStrategy strategy : strategies) {
loadDirectory(extensionClasses, strategy.directory(), type.getName(), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
loadDirectory(extensionClasses, strategy.directory(), type.getName().replace("org.apache", "com.alibaba"), strategy.preferExtensionClassLoader(), strategy.overridden(), strategy.excludedPackages());
loadDirectory(extensionClasses, strategy, type.getName());
// compatible with old ExtensionFactory
if (this.type == ExtensionInjector.class) {
loadDirectory(extensionClasses, strategy, ExtensionFactory.class.getName());
}
}
return extensionClasses;
}
private void loadDirectory(Map<String, Class<?>> extensionClasses, LoadingStrategy strategy, String type) {
loadDirectory(extensionClasses, strategy.directory(), type, strategy.preferExtensionClassLoader(),
strategy.overridden(), strategy.excludedPackages());
String oldType = type.replace("org.apache", "com.alibaba");
loadDirectory(extensionClasses, strategy.directory(), oldType, strategy.preferExtensionClassLoader(),
strategy.overridden(), strategy.excludedPackages());
}
/**
* extract and cache default extension name if exists
*/
@ -934,7 +959,8 @@ public class ExtensionLoader<T> {
loadClass(extensionClasses, resourceURL, Class.forName(clazz, true, classLoader), name, overridden);
}
} catch (Throwable t) {
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type + ", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
IllegalStateException e = new IllegalStateException("Failed to load extension class (interface: " + type +
", class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
exceptions.put(line, e);
}
}
@ -1087,7 +1113,12 @@ public class ExtensionLoader<T> {
@SuppressWarnings("unchecked")
private T createAdaptiveExtension() {
try {
return injectExtension((T) getAdaptiveExtensionClass().newInstance());
T instance = (T) getAdaptiveExtensionClass().newInstance();
instance = postProcessBeforeInitialization(instance, null);
instance = injectExtension(instance);
instance = postProcessAfterInitialization(instance, null);
initExtension(instance);
return instance;
} catch (Exception e) {
throw new IllegalStateException("Can't create adaptive extension " + type + ", cause: " + e.getMessage(), e);
}
@ -1104,17 +1135,25 @@ public class ExtensionLoader<T> {
private Class<?> createAdaptiveExtensionClass() {
ClassLoader classLoader = findClassLoader();
try {
if (ApplicationModel.getEnvironment().getConfiguration().getBoolean(NATIVE, false)) {
if (getEnvironment().getConfiguration().getBoolean(NATIVE, false)) {
return classLoader.loadClass(type.getName() + "$Adaptive");
}
} catch (Throwable ignore) {
}
String code = new AdaptiveClassCodeGenerator(type, cachedDefaultName).generate();
org.apache.dubbo.common.compiler.Compiler compiler = ExtensionLoader.getExtensionLoader(org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
org.apache.dubbo.common.compiler.Compiler compiler = extensionDirector.getExtensionLoader(
org.apache.dubbo.common.compiler.Compiler.class).getAdaptiveExtension();
return compiler.compile(code, classLoader);
}
private Environment getEnvironment() {
if (environment == null) {
environment = (Environment) extensionDirector.getExtensionLoader(FrameworkExt.class).getExtension(Environment.NAME);
}
return environment;
}
@Override
public String toString() {
return this.getClass().getName() + "[" + type.getName() + "]";

View File

@ -0,0 +1,32 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension;
/**
* A Post-processor called before or after extension initialization.
*/
public interface ExtensionPostProcessor {
default Object postProcessBeforeInitialization(Object instance, String name) throws Exception {
return instance;
}
default Object postProcessAfterInitialization(Object instance, String name) throws Exception {
return instance;
}
}

View File

@ -0,0 +1,78 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
/**
* Extension SPI Scope
* @see SPI
* @see ExtensionDirector
*/
public enum ExtensionScope {
/**
* The extension instance is used within framework, shared with all applications and modules.
*
* <p>Framework scope SPI extension can only obtain {@link FrameworkModel},
* cannot get the {@link ApplicationModel} and {@link ModuleModel}.</p>
*
* <p></p>
* Consideration:
* <ol>
* <li>Some SPI need share data between applications inside framework</li>
* <li>Stateless SPI is safe shared inside framework</li>
* </ol>
*/
FRAMEWORK,
/**
* The extension instance is used within one application, shared with all modules of the application,
* and different applications create different extension instances.
*
* <p>Application scope SPI extension can obtain {@link FrameworkModel} and {@link ApplicationModel},
* cannot get the {@link ModuleModel}.</p>
*
* <p></p>
* Consideration:
* <ol>
* <li>Isolate extension data in different applications inside framework</li>
* <li>Share extension data between all modules inside application</li>
* </ol>
*/
APPLICATION,
/**
* The extension instance is used within one module, and different modules create different extension instances.
*
* <p>Module scope SPI extension can obtain {@link FrameworkModel}, {@link ApplicationModel} and {@link ModuleModel}.</p>
*
* <p></p>
* Consideration:
* <ol>
* <li>Isolate extension data in different modules inside application</li>
* </ol>
*/
MODULE,
/**
* self-sufficient, creates an instance for per scope, for special SPI extension, like {@link ExtensionInjector}
*/
SELF
}

View File

@ -61,4 +61,8 @@ public @interface SPI {
*/
String value() default "";
/**
* scope of SPI, default value is application scope.
*/
ExtensionScope scope() default ExtensionScope.APPLICATION;
}

View File

@ -1,55 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.factory;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionFactory;
import org.apache.dubbo.common.extension.ExtensionLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* AdaptiveExtensionFactory
*/
@Adaptive
public class AdaptiveExtensionFactory implements ExtensionFactory {
private final List<ExtensionFactory> factories;
public AdaptiveExtensionFactory() {
ExtensionLoader<ExtensionFactory> loader = ExtensionLoader.getExtensionLoader(ExtensionFactory.class);
List<ExtensionFactory> list = new ArrayList<ExtensionFactory>();
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
factories = Collections.unmodifiableList(list);
}
@Override
public <T> T getExtension(Class<T> type, String name) {
for (ExtensionFactory factory : factories) {
T extension = factory.getExtension(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.extension.inject;
import org.apache.dubbo.common.context.Lifecycle;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionInjector;
import org.apache.dubbo.common.extension.ExtensionLoader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* AdaptiveExtensionInjector
*/
@Adaptive
public class AdaptiveExtensionInjector implements ExtensionInjector, Lifecycle {
private List<ExtensionInjector> injectors = Collections.emptyList();
private ExtensionAccessor extensionAccessor;
public AdaptiveExtensionInjector() {
}
@Override
public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
this.extensionAccessor = extensionAccessor;
}
@Override
public void initialize() throws IllegalStateException {
ExtensionLoader<ExtensionInjector> loader = extensionAccessor.getExtensionLoader(ExtensionInjector.class);
List<ExtensionInjector> list = new ArrayList<ExtensionInjector>();
for (String name : loader.getSupportedExtensions()) {
list.add(loader.getExtension(name));
}
injectors = Collections.unmodifiableList(list);
}
@Override
public <T> T getInstance(Class<T> type, String name) {
for (ExtensionInjector injector : injectors) {
T extension = injector.getInstance(type, name);
if (extension != null) {
return extension;
}
}
return null;
}
@Override
public void start() throws IllegalStateException {
}
@Override
public void destroy() throws IllegalStateException {
}
}

View File

@ -14,21 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.factory;
package org.apache.dubbo.common.extension.inject;
import org.apache.dubbo.common.extension.ExtensionFactory;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionInjector;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
/**
* SpiExtensionFactory
* SpiExtensionInjector
*/
public class SpiExtensionFactory implements ExtensionFactory {
public class SpiExtensionInjector implements ExtensionInjector {
private ExtensionAccessor extensionAccessor;
@Override
public <T> T getExtension(Class<T> type, String name) {
public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
this.extensionAccessor = extensionAccessor;
}
@Override
public <T> T getInstance(Class<T> type, String name) {
if (type.isInterface() && type.isAnnotationPresent(SPI.class)) {
ExtensionLoader<T> loader = ExtensionLoader.getExtensionLoader(type);
ExtensionLoader<T> loader = extensionAccessor.getExtensionLoader(type);
if (loader == null) {
return null;
}
if (!loader.getSupportedExtensions().isEmpty()) {
return loader.getAdaptiveExtension();
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.infra;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.Map;
@ -26,7 +27,7 @@ import java.util.Map;
* 2. get configurations from third-party systems which maybe useful for a specific component.
*/
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface InfraAdapter {
/**

View File

@ -20,6 +20,8 @@ import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.common.infra.InfraAdapter;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import java.util.HashMap;
import java.util.Map;
@ -31,7 +33,14 @@ import static org.apache.dubbo.common.constants.CommonConstants.EQUAL_SPLIT_PATT
import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN;
@Activate
public class EnvironmentAdapter implements InfraAdapter {
public class EnvironmentAdapter implements InfraAdapter, ScopeModelAware {
private ApplicationModel applicationModel;
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
/**
* 1. OS Environment: DUBBO_LABELS=tag=pre;key=value
@ -41,7 +50,7 @@ public class EnvironmentAdapter implements InfraAdapter {
public Map<String, String> getExtraAttributes(Map<String, String> params) {
Map<String, String> parameters = new HashMap<>();
String rawLabels = ConfigurationUtils.getProperty(DUBBO_LABELS);
String rawLabels = ConfigurationUtils.getProperty(applicationModel, DUBBO_LABELS);
if (StringUtils.isNotEmpty(rawLabels)) {
String[] labelPairs = SEMICOLON_SPLIT_PATTERN.split(rawLabels);
for (String pair : labelPairs) {
@ -52,11 +61,11 @@ public class EnvironmentAdapter implements InfraAdapter {
}
}
String rawKeys = ConfigurationUtils.getProperty(DUBBO_ENV_KEYS);
String rawKeys = ConfigurationUtils.getProperty(applicationModel, DUBBO_ENV_KEYS);
if (StringUtils.isNotEmpty(rawKeys)) {
String[] keys = COMMA_SPLIT_PATTERN.split(rawKeys);
for (String key : keys) {
String value = ConfigurationUtils.getProperty(key);
String value = ConfigurationUtils.getProperty(applicationModel, key);
if (value != null) {
parameters.put(key, value);
}
@ -67,6 +76,6 @@ public class EnvironmentAdapter implements InfraAdapter {
@Override
public String getAttribute(String key) {
return ConfigurationUtils.getProperty(key);
return ConfigurationUtils.getProperty(applicationModel, key);
}
}

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.lang;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
/**
@ -23,7 +24,7 @@ import org.apache.dubbo.common.extension.SPI;
*
* @since 2.7.5
*/
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface ShutdownHookCallback extends Prioritized {
/**

View File

@ -16,6 +16,7 @@
*/
package org.apache.dubbo.common.logger;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.io.File;
@ -23,7 +24,7 @@ import java.io.File;
/**
* Logger provider
*/
@SPI
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface LoggerAdapter {
/**

View File

@ -16,12 +16,13 @@
*/
package org.apache.dubbo.common.status;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
/**
* StatusChecker
*/
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface StatusChecker {
/**

View File

@ -0,0 +1,109 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.status.reporter;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Set;
/**
*
*/
public class FrameworkStatusReportService implements ScopeModelAware {
private static final Logger logger = LoggerFactory.getLogger(FrameworkStatusReporter.class);
public static final String REGISTRATION_STATUS = "registration";
public static final String ADDRESS_CONSUMPTION_STATUS = "consumption";
public static final String MIGRATION_STEP_STATUS = "migrationStepStatus";
private ApplicationModel applicationModel;
private Set<FrameworkStatusReporter> reporters;
private Gson gson = new Gson();
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
reporters = applicationModel.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances();
}
public void reportRegistrationStatus(Object obj) {
doReport(REGISTRATION_STATUS, obj);
}
public void reportConsumptionStatus(Object obj) {
doReport(ADDRESS_CONSUMPTION_STATUS, obj);
}
public void reportMigrationStepStatus(Object obj) {
doReport(MIGRATION_STEP_STATUS, obj);
}
public boolean hasReporter() {
return reporters.size() > 0;
}
private void doReport(String type, Object obj) {
// TODO, report asynchronously
try {
if (CollectionUtils.isNotEmpty(reporters)) {
FrameworkStatusReporter reporter = reporters.iterator().next();
reporter.report(type, obj);
}
} catch (Exception e) {
logger.info("Report " + type + " status failed because of " + e.getMessage());
}
}
public String createRegistrationReport(String status) {
return "{\"application\":\"" +
applicationModel.getApplicationName() +
"\",\"status\":\"" +
status +
"\"}";
}
public String createConsumptionReport(String interfaceName, String version, String group, String status) {
HashMap<String, String> migrationStatus = new HashMap<>();
migrationStatus.put("type", "consumption");
migrationStatus.put("application", applicationModel.getApplicationName());
migrationStatus.put("service", interfaceName);
migrationStatus.put("version", version);
migrationStatus.put("group", group);
migrationStatus.put("status", status);
return gson.toJson(migrationStatus);
}
public String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) {
HashMap<String, String> migrationStatus = new HashMap<>();
migrationStatus.put("type", "migrationStepStatus");
migrationStatus.put("application", applicationModel.getApplicationName());
migrationStatus.put("service", interfaceName);
migrationStatus.put("version", version);
migrationStatus.put("group", group);
migrationStatus.put("originStep", originStep);
migrationStatus.put("newStep", newStep);
migrationStatus.put("success", success);
return gson.toJson(migrationStatus);
}
}

View File

@ -16,86 +16,14 @@
*/
package org.apache.dubbo.common.status.reporter;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import com.google.gson.Gson;
import java.util.HashMap;
import java.util.Set;
@SPI
public interface FrameworkStatusReporter {
static final Gson gson = new Gson();
Logger logger = LoggerFactory.getLogger(FrameworkStatusReporter.class);
String REGISTRATION_STATUS = "registration";
String ADDRESS_CONSUMPTION_STATUS = "consumption";
String MIGRATION_STEP_STATUS = "migrationStepStatus";
@SPI(scope = ExtensionScope.APPLICATION)
public interface FrameworkStatusReporter extends ScopeModelAware {
void report(String type, Object obj);
static void reportRegistrationStatus(Object obj) {
doReport(REGISTRATION_STATUS, obj);
}
static void reportConsumptionStatus(Object obj) {
doReport(ADDRESS_CONSUMPTION_STATUS, obj);
}
static void reportMigrationStepStatus(Object obj) {
doReport(MIGRATION_STEP_STATUS, obj);
}
static boolean hasReporter() {
return ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensions().size() > 0;
}
static void doReport(String type, Object obj) {
// TODO, report asynchronously
try {
Set<FrameworkStatusReporter> reporters = ExtensionLoader.getExtensionLoader(FrameworkStatusReporter.class).getSupportedExtensionInstances();
if (CollectionUtils.isNotEmpty(reporters)) {
FrameworkStatusReporter reporter = reporters.iterator().next();
reporter.report(type, obj);
}
} catch (Exception e) {
logger.info("Report " + type + " status failed because of " + e.getMessage());
}
}
static String createRegistrationReport(String status) {
return "{\"application\":\"" +
ApplicationModel.getName() +
"\",\"status\":\"" +
status +
"\"}";
}
static String createConsumptionReport(String interfaceName, String version, String group, String status) {
HashMap<String, String> migrationStatus = new HashMap<>();
migrationStatus.put("type", "consumption");
migrationStatus.put("application", ApplicationModel.getName());
migrationStatus.put("service", interfaceName);
migrationStatus.put("version", version);
migrationStatus.put("group", group);
migrationStatus.put("status", status);
return gson.toJson(migrationStatus);
}
static String createMigrationStepReport(String interfaceName, String version, String group, String originStep, String newStep, String success) {
HashMap<String, String> migrationStatus = new HashMap<>();
migrationStatus.put("type", "migrationStepStatus");
migrationStatus.put("application", ApplicationModel.getName());
migrationStatus.put("service", interfaceName);
migrationStatus.put("version", version);
migrationStatus.put("group", group);
migrationStatus.put("originStep", originStep);
migrationStatus.put("newStep", newStep);
migrationStatus.put("success", success);
return gson.toJson(migrationStatus);
}
}

View File

@ -17,11 +17,12 @@
package org.apache.dubbo.common.store;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.Map;
@SPI("simple")
@SPI(value = "simple", scope = ExtensionScope.APPLICATION)
public interface DataStore {
/**

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.common.threadpool;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.concurrent.Executor;
@ -27,7 +28,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
/**
* ThreadPool
*/
@SPI("fixed")
//TODO which scope for ThreadPool? APPLICATION or FRAMEWORK
@SPI(value = "fixed", scope = ExtensionScope.FRAMEWORK)
public interface ThreadPool {
/**

View File

@ -17,7 +17,8 @@
package org.apache.dubbo.common.threadpool.manager;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionAccessorAware;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadlocal.NamedInternalThreadFactory;
@ -27,6 +28,8 @@ import org.apache.dubbo.common.utils.ExecutorUtil;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import java.util.List;
import java.util.Map;
@ -46,12 +49,11 @@ import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_REFER_TH
import static org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_SERVICE_COMPONENT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
import static org.apache.dubbo.rpc.model.ApplicationModel.getConfigManager;
/**
* Consider implementing {@code Licycle} to enable executors shutdown when the process stops.
*/
public class DefaultExecutorRepository implements ExecutorRepository {
public class DefaultExecutorRepository implements ExecutorRepository, ExtensionAccessorAware, ScopeModelAware {
private static final Logger logger = LoggerFactory.getLogger(DefaultExecutorRepository.class);
private int DEFAULT_SCHEDULER_SIZE = Runtime.getRuntime().availableProcessors();
@ -79,6 +81,9 @@ public class DefaultExecutorRepository implements ExecutorRepository {
private static Ring<ExecutorService> executorServiceRing = new Ring<ExecutorService>();
private static final Object LOCK = new Object();
private ExtensionAccessor extensionAccessor;
private ApplicationModel applicationModel;
public DefaultExecutorRepository() {
for (int i = 0; i < DEFAULT_SCHEDULER_SIZE; i++) {
@ -228,7 +233,7 @@ public class DefaultExecutorRepository implements ExecutorRepository {
}
private Integer getExportThreadNum() {
List<Integer> threadNum = getConfigManager().getProviders()
List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getProviders()
.stream()
.map(ProviderConfig::getExportThreadNum)
.filter(k -> k != null && k > 0)
@ -275,7 +280,7 @@ public class DefaultExecutorRepository implements ExecutorRepository {
}
private Integer getReferThreadNum() {
List<Integer> threadNum = getConfigManager().getConsumers()
List<Integer> threadNum = ApplicationModel.ofNullable(applicationModel).getApplicationConfigManager().getConsumers()
.stream()
.map(ConsumerConfig::getReferThreadNum)
.filter(k -> k != null && k > 0)
@ -311,7 +316,7 @@ public class DefaultExecutorRepository implements ExecutorRepository {
}
private ExecutorService createExecutor(URL url) {
return (ExecutorService) ExtensionLoader.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
return (ExecutorService) extensionAccessor.getExtensionLoader(ThreadPool.class).getAdaptiveExtension().getExecutor(url);
}
@Override
@ -362,4 +367,14 @@ public class DefaultExecutorRepository implements ExecutorRepository {
// executorService.shutdown();
// }
}
@Override
public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
this.extensionAccessor = extensionAccessor;
}
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.threadpool.manager;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.concurrent.ExecutorService;
@ -25,7 +26,7 @@ import java.util.concurrent.ScheduledExecutorService;
/**
*
*/
@SPI("default")
@SPI(value = "default", scope = ExtensionScope.APPLICATION)
public interface ExecutorRepository {
/**

View File

@ -18,6 +18,8 @@ package org.apache.dubbo.common.url.component;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceModel;
import java.util.Map;
import java.util.Objects;
@ -96,6 +98,16 @@ public class DubboServiceAddressURL extends ServiceAddressURL {
this.overrideURL = overrideURL;
}
@Override
public ScopeModel getScopeModel() {
return consumerURL.getScopeModel();
}
@Override
public ServiceModel getServiceModel() {
return consumerURL.getServiceModel();
}
@Override
public int hashCode() {
final int prime = 31;

View File

@ -23,7 +23,6 @@ import java.util.HashMap;
import java.util.Map;
public class ServiceConfigURL extends URL {
private final Map<String, Object> attributes;
private volatile transient String full;
private volatile transient String string;
@ -31,12 +30,11 @@ public class ServiceConfigURL extends URL {
private volatile transient String parameter;
public ServiceConfigURL() {
this.attributes = null;
super();
}
public ServiceConfigURL(URLAddress urlAddress, URLParam urlParam, Map<String, Object> attributes) {
super(urlAddress, urlParam);
this.attributes = (attributes != null ? attributes : new HashMap<>());
super(urlAddress, urlParam, attributes);
}
@ -98,22 +96,11 @@ public class ServiceConfigURL extends URL {
return (T) new ServiceConfigURL(urlAddress, urlParam, attributes);
}
@Override
public Map<String, Object> getAttributes() {
return attributes;
}
@Override
public Object getAttribute(String key) {
return attributes.get(key);
}
@Override
public URL addAttributes(Map<String, Object> attributes) {
Map<String, Object> newAttributes = new HashMap<>();
newAttributes.putAll(this.attributes);
newAttributes.putAll(attributes);
return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes);
}
@ -121,7 +108,6 @@ public class ServiceConfigURL extends URL {
public ServiceConfigURL putAttribute(String key, Object obj) {
Map<String, Object> newAttributes = new HashMap<>(attributes);
newAttributes.put(key, obj);
return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes);
}
@ -129,15 +115,9 @@ public class ServiceConfigURL extends URL {
public URL removeAttribute(String key) {
Map<String, Object> newAttributes = new HashMap<>(attributes);
newAttributes.remove(key);
return new ServiceConfigURL(getUrlAddress(), getUrlParam(), newAttributes);
}
@Override
public boolean hasAttribute(String key) {
return getAttribute(key) != null;
}
@Override
public String toString() {
if (string != null) {

View File

@ -16,11 +16,12 @@
*/
package org.apache.dubbo.common.url.component.param;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
import java.util.List;
@SPI
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface DynamicParamSource {
void init(List<String> keys, List<ParamValue> values);

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.logger.support.FailsafeLogger;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.io.IOException;
import java.net.Inet4Address;
@ -237,8 +238,8 @@ public class NetUtils {
return host;
}
public static String getIpByConfig() {
String configIp = ConfigurationUtils.getProperty(DUBBO_IP_TO_BIND);
public static String getIpByConfig(ScopeModel scopeModel) {
String configIp = ConfigurationUtils.getProperty(scopeModel, DUBBO_IP_TO_BIND);
if (configIp != null) {
return configIp;
}

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
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.ClassUtils;
@ -28,8 +29,11 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.MethodUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
@ -93,6 +97,21 @@ public abstract class AbstractConfig implements Serializable {
*/
protected Boolean isDefault;
/**
* The scope model of this config instance.
* <p>
* <b>NOTE:</b> the model maybe changed during config processing,
* the extension spi instance needs to be reinitialized after changing the model!
*/
protected ScopeModel scopeModel;
public AbstractConfig() {
this(ApplicationModel.defaultModel());
}
public AbstractConfig(ScopeModel scopeModel) {
this.setScopeModel(scopeModel);
}
public static String getTagName(Class<?> cls) {
return tagNameCache.computeIfAbsent(cls, (key) -> {
@ -302,6 +321,46 @@ public abstract class AbstractConfig implements Serializable {
return result;
}
public ApplicationModel getApplicationModel() {
if (scopeModel instanceof ApplicationModel) {
return (ApplicationModel) scopeModel;
} else if (scopeModel instanceof ModuleModel) {
return ((ModuleModel) scopeModel).getApplicationModel();
} else {
throw new IllegalStateException("scope model is invalid: " + scopeModel);
}
}
public ScopeModel getScopeModel() {
return scopeModel;
}
public void setScopeModel(ScopeModel scopeModel) {
if (this.scopeModel != scopeModel) {
this.scopeModel = scopeModel;
// reinitialize spi extension here
this.initExtensions();
}
}
/**
* Subclass should override this method to initialize its SPI extensions.
* <p>
* For example:
* <pre>
* this.protocol = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
* </pre>
*/
protected void initExtensions() {
}
protected <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
if (scopeModel == null) {
throw new IllegalStateException("owner module is not initialized");
}
return scopeModel.getExtensionLoader(type);
}
@Parameter(excluded = true, attribute = true)
public String getId() {
return id;
@ -443,7 +502,7 @@ public abstract class AbstractConfig implements Serializable {
// check and init before do refresh
preProcessRefresh();
Environment environment = ApplicationModel.getEnvironment();
Environment environment = getApplicationModel().getApplicationEnvironment();
List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
// Search props starts with PREFIX in order
@ -729,4 +788,7 @@ public abstract class AbstractConfig implements Serializable {
return methods;
}
protected ConfigManager getConfigManager() {
return getApplicationModel().getApplicationConfigManager();
}
}

View File

@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.bytecode.Wrapper;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
@ -27,7 +28,7 @@ import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import java.lang.reflect.Method;
@ -42,12 +43,12 @@ import java.util.stream.Collectors;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INVOKER_LISTENER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.NATIVE;
import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REFERENCE_FILTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TAG_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.NATIVE;
/**
@ -196,6 +197,34 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
return urls;
}
@Override
public void setScopeModel(ScopeModel scopeModel) {
super.setScopeModel(scopeModel);
// ApplicationModel applicationModel = ScopeModelUtil.getApplicationModel(scopeModel);
// if (this.configCenter != null && this.configCenter.getScopeModel() != applicationModel) {
// this.configCenter.setScopeModel(applicationModel);
// }
// if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) {
// this.metadataReportConfig.setScopeModel(applicationModel);
// }
// if (this.metrics != null && this.metrics.getScopeModel() != applicationModel) {
// this.metrics.setScopeModel(applicationModel);
// }
// if (this.monitor != null && this.monitor.getScopeModel() != applicationModel) {
// this.monitor.setScopeModel(applicationModel);
// }
// if (this.metadataReportConfig != null && this.metadataReportConfig.getScopeModel() != applicationModel) {
// this.metadataReportConfig.setScopeModel(applicationModel);
// }
// if (CollectionUtils.isNotEmpty(this.registries)) {
// this.registries.forEach(registryConfig -> {
// if (registryConfig.getScopeModel() != applicationModel) {
// registryConfig.setScopeModel(applicationModel);
// }
// });
// }
}
/**
* Check whether the registry config is exists, and then conversion it to {@link RegistryConfig}
*/
@ -225,7 +254,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
* @return
*/
protected String[] methods(Class<?> interfaceClass) {
boolean isNative = ApplicationModel.getEnvironment().getConfiguration().getBoolean(NATIVE, false);
boolean isNative = getEnvironment().getConfiguration().getBoolean(NATIVE, false);
if (isNative) {
return Arrays.stream(interfaceClass.getMethods()).map(Method::getName).toArray(String[]::new);
} else {
@ -233,6 +262,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
}
protected Environment getEnvironment() {
return getApplicationModel().getApplicationEnvironment();
}
@Override
protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
if (StringUtils.hasText(interfaceName)) {
@ -278,13 +311,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
List<MethodConfig> methodConfigs = this.getMethods();
if (methodConfigs != null && methodConfigs.size() > 0) {
// whether ignore invalid method config
Object ignoreInvalidMethodConfigVal = ApplicationModel.getEnvironment().getConfiguration()
Object ignoreInvalidMethodConfigVal = getEnvironment().getConfiguration()
.getProperty(ConfigKeys.DUBBO_CONFIG_IGNORE_INVALID_METHOD_CONFIG, "false");
boolean ignoreInvalidMethodConfig = Boolean.parseBoolean(ignoreInvalidMethodConfigVal.toString());
Class<?> finalInterfaceClass = interfaceClass;
List<MethodConfig> validMethodConfigs = methodConfigs.stream().filter(methodConfig -> {
methodConfig.setParentPrefix(preferredPrefix);
methodConfig.setScopeModel(getScopeModel());
methodConfig.refresh();
// verify method config
return verifyMethodConfig(methodConfig, finalInterfaceClass, ignoreInvalidMethodConfig);
@ -388,7 +422,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
computeValidRegistryIds();
if (StringUtils.isEmpty(registryIds)) {
if (CollectionUtils.isEmpty(registries)) {
List<RegistryConfig> registryConfigs = ApplicationModel.getConfigManager().getDefaultRegistries();
List<RegistryConfig> registryConfigs = getConfigManager().getDefaultRegistries();
registryConfigs = new ArrayList<>(registryConfigs);
setRegistries(registryConfigs);
}
@ -397,7 +431,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Arrays.stream(ids).forEach(id -> {
if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
Optional<RegistryConfig> globalRegistry = ApplicationModel.getConfigManager().getRegistry(id);
Optional<RegistryConfig> globalRegistry = getConfigManager().getRegistry(id);
if (globalRegistry.isPresent()) {
tmpRegistries.add(globalRegistry.get());
} else {
@ -561,14 +595,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (application != null) {
return application;
}
return ApplicationModel.getConfigManager().getApplicationOrElseThrow();
return getConfigManager().getApplicationOrElseThrow();
}
@Deprecated
public void setApplication(ApplicationConfig application) {
this.application = application;
if (application != null) {
ApplicationModel.getConfigManager().setApplication(application);
getConfigManager().setApplication(application);
}
}
@ -576,14 +610,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (module != null) {
return module;
}
return ApplicationModel.getConfigManager().getModule().orElse(null);
return getConfigManager().getModule().orElse(null);
}
@Deprecated
public void setModule(ModuleConfig module) {
this.module = module;
if (module != null) {
ApplicationModel.getConfigManager().setModule(module);
getConfigManager().setModule(module);
}
}
@ -637,7 +671,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
return monitor;
}
// FIXME: instead of return null, we should set default monitor when getMonitor() return null in ConfigManager
return ApplicationModel.getConfigManager().getMonitor().orElse(null);
return getConfigManager().getMonitor().orElse(null);
}
@Deprecated
@ -649,7 +683,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setMonitor(MonitorConfig monitor) {
this.monitor = monitor;
if (monitor != null) {
ApplicationModel.getConfigManager().setMonitor(monitor);
getConfigManager().setMonitor(monitor);
}
}
@ -666,7 +700,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (configCenter != null) {
return configCenter;
}
Collection<ConfigCenterConfig> configCenterConfigs = ApplicationModel.getConfigManager().getConfigCenters();
Collection<ConfigCenterConfig> configCenterConfigs = getConfigManager().getConfigCenters();
if (CollectionUtils.isNotEmpty(configCenterConfigs)) {
return configCenterConfigs.iterator().next();
}
@ -677,7 +711,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setConfigCenter(ConfigCenterConfig configCenter) {
this.configCenter = configCenter;
if (configCenter != null) {
ApplicationModel.getConfigManager().addConfigCenter(configCenter);
getConfigManager().addConfigCenter(configCenter);
}
}
@ -718,7 +752,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (metadataReportConfig != null) {
return metadataReportConfig;
}
Collection<MetadataReportConfig> metadataReportConfigs = ApplicationModel.getConfigManager().getMetadataConfigs();
Collection<MetadataReportConfig> metadataReportConfigs = getConfigManager().getMetadataConfigs();
if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
return metadataReportConfigs.iterator().next();
}
@ -729,7 +763,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setMetadataReportConfig(MetadataReportConfig metadataReportConfig) {
this.metadataReportConfig = metadataReportConfig;
if (metadataReportConfig != null) {
ApplicationModel.getConfigManager().addMetadataReport(metadataReportConfig);
getConfigManager().addMetadataReport(metadataReportConfig);
}
}
@ -738,14 +772,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (metrics != null) {
return metrics;
}
return ApplicationModel.getConfigManager().getMetrics().orElse(null);
return getConfigManager().getMetrics().orElse(null);
}
@Deprecated
public void setMetrics(MetricsConfig metrics) {
this.metrics = metrics;
if (metrics != null) {
ApplicationModel.getConfigManager().setMetrics(metrics);
getConfigManager().setMetrics(metrics);
}
}
@ -767,7 +801,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
public SslConfig getSslConfig() {
return ApplicationModel.getConfigManager().getSsl().orElse(null);
return getConfigManager().getSsl().orElse(null);
}
protected void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {

View File

@ -17,6 +17,9 @@
package org.apache.dubbo.config;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import java.util.Map;
@ -95,6 +98,23 @@ public abstract class AbstractMethodConfig extends AbstractConfig {
*/
protected Integer forks;
public AbstractMethodConfig() {
super(ApplicationModel.defaultModel().getDefaultModule());
}
@Override
public void setScopeModel(ScopeModel scopeModel) {
if (!(scopeModel instanceof ModuleModel)) {
throw new IllegalArgumentException("Invalid scope model, expect to be a ModuleModel but got: " + scopeModel);
}
super.setScopeModel(scopeModel);
}
@Override
public ModuleModel getScopeModel() {
return (ModuleModel) scopeModel;
}
public Integer getForks() {
return forks;
}

View File

@ -17,7 +17,6 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.compiler.support.AdaptiveCompiler;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.infra.InfraAdapter;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -34,17 +33,17 @@ import java.util.Map;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
import static org.apache.dubbo.common.constants.CommonConstants.DUMP_DIRECTORY;
import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_PROTOCOL_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METADATA_SERVICE_PORT_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.LIVENESS_PROBE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.READINESS_PROBE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.STARTUP_PROBE;
import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
@ -557,7 +556,7 @@ public class ApplicationConfig extends AbstractConfig {
parameters = new HashMap<>();
}
Set<InfraAdapter> adapters = ExtensionLoader.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
Set<InfraAdapter> adapters = this.getExtensionLoader(InfraAdapter.class).getSupportedExtensionInstances();
if (CollectionUtils.isNotEmpty(adapters)) {
Map<String, String> inputParameters = new HashMap<>();
inputParameters.put(APPLICATION_KEY, getName());

View File

@ -149,7 +149,9 @@ public class ConfigCenterConfig extends AbstractConfig {
if (StringUtils.isEmpty(map.get(PROTOCOL_KEY))) {
map.put(PROTOCOL_KEY, ZOOKEEPER_PROTOCOL);
}
return UrlUtils.parseURL(address, map);
URL url = UrlUtils.parseURL(address, map);
url.setScopeModel(getScopeModel());
return url;
}
public boolean checkOrUpdateInitialized(boolean update) {

View File

@ -124,7 +124,7 @@ public class MetadataReportConfig extends AbstractConfig {
throw new IllegalArgumentException("The address of metadata report is invalid.");
}
Map<String, String> map = new HashMap<String, String>();
URL url = URL.valueOf(address);
URL url = URL.valueOf(address, getScopeModel());
// Issue : https://github.com/apache/dubbo/issues/6491
// Append the parameters from address
map.putAll(url.getParameters());
@ -135,7 +135,7 @@ public class MetadataReportConfig extends AbstractConfig {
// put the protocol of URL as the "metadata"
map.put("metadata", url.getProtocol());
return new ServiceConfigURL("metadata", url.getUsername(), url.getPassword(), url.getHost(),
url.getPort(), url.getPath(), map);
url.getPort(), url.getPath(), map).setScopeModel(getScopeModel());
}

View File

@ -24,7 +24,6 @@ import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.AsyncMethodInfo;
import java.util.ArrayList;
@ -231,7 +230,7 @@ public class MethodConfig extends AbstractMethodConfig {
private void refreshArgument(ArgumentConfig argument, InmemoryConfiguration subPropsConfiguration) {
if (argument.getIndex() != null && argument.getIndex() >= 0) {
String prefix = argument.getIndex() + ".";
Environment environment = ApplicationModel.getEnvironment();
Environment environment = getApplicationModel().getApplicationEnvironment();
java.lang.reflect.Method[] methods = argument.getClass().getMethods();
for (java.lang.reflect.Method method : methods) {
if (MethodUtils.isSetter(method)) {

View File

@ -22,7 +22,7 @@ import org.apache.dubbo.common.utils.RegexProperties;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@ -115,7 +115,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
protected void preProcessRefresh() {
super.preProcessRefresh();
if (consumer == null) {
consumer = ApplicationModel.getConfigManager()
consumer = getConfigManager()
.getDefaultConsumer()
.orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized"));
}
@ -200,6 +200,14 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
return null;
}
@Override
public void setScopeModel(ScopeModel scopeModel) {
super.setScopeModel(scopeModel);
if (this.consumer != null && this.consumer.getScopeModel() != scopeModel) {
this.consumer.setScopeModel(scopeModel);
}
}
@Override
public String getInterface() {
return interfaceName;

View File

@ -327,7 +327,7 @@ public class RegistryConfig extends AbstractConfig {
}
public void setTransporter(String transporter) {
/*if(transporter != null && transporter.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(transporter)){
/*if(transporter != null && transporter.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(transporter)){
throw new IllegalStateException("No such transporter type : " + transporter);
}*/
this.transporter = transporter;
@ -338,7 +338,7 @@ public class RegistryConfig extends AbstractConfig {
}
public void setServer(String server) {
/*if(server != null && server.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(server)){
/*if(server != null && server.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(server)){
throw new IllegalStateException("No such server type : " + server);
}*/
this.server = server;
@ -349,7 +349,7 @@ public class RegistryConfig extends AbstractConfig {
}
public void setClient(String client) {
/*if(client != null && client.length() > 0 && ! ExtensionLoader.getExtensionLoader(Transporter.class).hasExtension(client)){
/*if(client != null && client.length() > 0 && ! this.getExtensionLoader(Transporter.class).hasExtension(client)){
throw new IllegalStateException("No such client type : " + client);
}*/
this.client = client;

View File

@ -21,7 +21,7 @@ import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceMetadata;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.support.ProtocolUtils;
@ -105,6 +105,14 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return protocols;
}
@Override
public void setScopeModel(ScopeModel scopeModel) {
super.setScopeModel(scopeModel);
if (this.provider != null && this.provider.getScopeModel() != scopeModel) {
this.provider.setScopeModel(scopeModel);
}
}
@Deprecated
private static List<ProviderConfig> convertProtocolToProvider(List<ProtocolConfig> protocols) {
if (CollectionUtils.isEmpty(protocols)) {
@ -199,7 +207,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
super.preProcessRefresh();
convertProviderIdToProvider();
if (provider == null) {
provider = ApplicationModel.getConfigManager()
provider = getConfigManager()
.getDefaultProvider()
.orElseThrow(() -> new IllegalArgumentException("Default provider is not initialized"));
}
@ -247,7 +255,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
protected void convertProviderIdToProvider() {
if (provider == null && StringUtils.hasText(providerIds)) {
provider = ApplicationModel.getConfigManager().getProvider(providerIds)
provider = getConfigManager().getProvider(providerIds)
.orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds));
}
}
@ -255,7 +263,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
protected void convertProtocolIdsToProtocols() {
if (StringUtils.isEmpty(protocolIds)) {
if (CollectionUtils.isEmpty(protocols)) {
List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
List<ProtocolConfig> protocolConfigs = getConfigManager().getDefaultProtocols();
if (protocolConfigs.isEmpty()) {
throw new IllegalStateException("The default protocol has not been initialized.");
}
@ -266,7 +274,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
Set<String> idsSet = new LinkedHashSet<>(Arrays.asList(idsArray));
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
for (String id : idsSet) {
Optional<ProtocolConfig> globalProtocol = ApplicationModel.getConfigManager().getProtocol(id);
Optional<ProtocolConfig> globalProtocol = getConfigManager().getProtocol(id);
if (globalProtocol.isPresent()) {
tmpProtocols.add(globalProtocol.get());
} else {
@ -336,7 +344,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
}
public void setProvider(ProviderConfig provider) {
ApplicationModel.getConfigManager().addProvider(provider);
getConfigManager().addProvider(provider);
this.provider = provider;
}

View File

@ -44,6 +44,7 @@ import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import java.util.ArrayList;
import java.util.Arrays;
@ -66,7 +67,7 @@ import static org.apache.dubbo.config.AbstractConfig.getTagName;
* A lock-free config manager (through ConcurrentHashMap), for fast read operation.
* The Write operation lock with sub configs map of config type, for safely check and add new config.
*/
public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
public class ConfigManager extends LifecycleAdapter implements FrameworkExt, ScopeModelAware {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
@ -105,12 +106,19 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
}
private ApplicationModel applicationModel;
public ConfigManager() {
}
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
@Override
public void initialize() throws IllegalStateException {
CompositeConfiguration configuration = ApplicationModel.getEnvironment().getConfiguration();
CompositeConfiguration configuration = applicationModel.getApplicationEnvironment().getConfiguration();
String configModeStr = (String) configuration.getProperty(DUBBO_CONFIG_MODE);
try {
if (StringUtils.hasText(configModeStr)) {
@ -367,6 +375,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
// ServiceConfig correlative methods
public void addService(ServiceConfigBase<?> serviceConfig) {
if (serviceConfig.getScopeModel() == null) {
serviceConfig.setScopeModel(applicationModel.getDefaultModule());
}
addConfig(serviceConfig);
}
@ -385,6 +396,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
// ReferenceConfig correlative methods
public void addReference(ReferenceConfigBase<?> referenceConfig) {
if (referenceConfig.getScopeModel() == null) {
referenceConfig.setScopeModel(applicationModel.getDefaultModule());
}
addConfig(referenceConfig);
}
@ -458,6 +472,9 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
if (config == null) {
return;
}
if (config.getScopeModel() == null) {
config.setScopeModel(applicationModel);
}
addConfig(config, isUniqueConfig(config));
}

View File

@ -16,9 +16,10 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI
@SPI(scope = ExtensionScope.APPLICATION)
public interface ApplicationInitListener {
/**
* init the application

View File

@ -18,14 +18,19 @@ package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.context.FrameworkExt;
import org.apache.dubbo.common.extension.ExtensionDirector;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.context.ConfigManager;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
@ -43,18 +48,48 @@ import java.util.concurrent.atomic.AtomicBoolean;
* <p>
*/
public class ApplicationModel {
public class ApplicationModel extends ScopeModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(ApplicationModel.class);
public static final String NAME = "application";
private static volatile ApplicationModel defaultInstance;
private static AtomicBoolean INIT_FLAG = new AtomicBoolean(false);
private static Environment environment;
private static ConfigManager configManager;
private static ServiceRepository serviceRepository;
private volatile List<ModuleModel> moduleModels = Collections.synchronizedList(new ArrayList<>());
private AtomicBoolean initFlag = new AtomicBoolean(false);
private Environment environment;
private ConfigManager configManager;
private ServiceRepository serviceRepository;
public static void init() {
if (INIT_FLAG.compareAndSet(false, true)) {
ExtensionLoader<ApplicationInitListener> extensionLoader = ExtensionLoader.getExtensionLoader(ApplicationInitListener.class);
private FrameworkModel frameworkModel;
public ApplicationModel(FrameworkModel frameworkModel) {
super(frameworkModel, new ExtensionDirector(frameworkModel.getExtensionDirector(), ExtensionScope.APPLICATION));
this.frameworkModel = frameworkModel;
frameworkModel.addApplication(this);
postProcessAfterCreated();
}
public static ApplicationModel ofNullable(ApplicationModel applicationModel) {
if (applicationModel != null) {
return applicationModel;
} else {
return defaultModel();
}
}
public static ApplicationModel defaultModel() {
if (defaultInstance == null) {
synchronized (ApplicationModel.class) {
if (defaultInstance == null) {
defaultInstance = new ApplicationModel(FrameworkModel.defaultModel());
}
}
}
return defaultInstance;
}
public void init() {
if (initFlag.compareAndSet(false, true)) {
ExtensionLoader<ApplicationInitListener> extensionLoader = this.getExtensionLoader(ApplicationInitListener.class);
Set<String> listenerNames = extensionLoader.getSupportedExtensions();
for (String listenerName : listenerNames) {
extensionLoader.getExtension(listenerName).init();
@ -62,99 +97,159 @@ public class ApplicationModel {
}
}
public void destroy() {
// TODO destroy application resources
}
public boolean isInit() {
return initFlag.get();
}
public FrameworkModel getFrameworkModel() {
return frameworkModel;
}
@Deprecated
public static Collection<ConsumerModel> allConsumerModels() {
return getServiceRepository().getReferredServices();
return defaultModel().getApplicationServiceRepository().getReferredServices();
}
public Collection<ConsumerModel> allApplicationConsumerModels() {
// TODO: aggregate from sub modules
return defaultModel().getApplicationServiceRepository().getReferredServices();
}
@Deprecated
public static Collection<ProviderModel> allProviderModels() {
return getServiceRepository().getExportedServices();
return defaultModel().getApplicationServiceRepository().getExportedServices();
}
public Collection<ProviderModel> allApplicationProviderModels() {
// TODO: aggregate from sub modules
return defaultModel().getApplicationServiceRepository().getExportedServices();
}
@Deprecated
public static ProviderModel getProviderModel(String serviceKey) {
return getServiceRepository().lookupExportedService(serviceKey);
return defaultModel().getApplicationServiceRepository().lookupExportedService(serviceKey);
}
@Deprecated
public static ConsumerModel getConsumerModel(String serviceKey) {
return getServiceRepository().lookupReferredService(serviceKey);
return defaultModel().getApplicationServiceRepository().lookupReferredService(serviceKey);
}
private static ExtensionLoader<FrameworkExt> LOADER = ExtensionLoader.getExtensionLoader(FrameworkExt.class);
public static void initFrameworkExts() {
Set<FrameworkExt> exts = ExtensionLoader.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
public void initFrameworkExts() {
Set<FrameworkExt> exts = this.getExtensionLoader(FrameworkExt.class).getSupportedExtensionInstances();
for (FrameworkExt ext : exts) {
ext.initialize();
}
}
@Deprecated
public static Environment getEnvironment() {
return defaultModel().getApplicationEnvironment();
}
public Environment getApplicationEnvironment() {
if (environment == null) {
environment = (Environment) LOADER.getExtension(Environment.NAME);
environment = (Environment) this.getExtensionLoader(FrameworkExt.class)
.getExtension(Environment.NAME);
}
return environment;
}
@Deprecated
public static ConfigManager getConfigManager() {
return defaultModel().getApplicationConfigManager();
}
public ConfigManager getApplicationConfigManager() {
if (configManager == null) {
configManager = (ConfigManager) LOADER.getExtension(ConfigManager.NAME);
configManager = (ConfigManager) this.getExtensionLoader(FrameworkExt.class)
.getExtension(ConfigManager.NAME);
}
return configManager;
}
@Deprecated
public static ServiceRepository getServiceRepository() {
return defaultModel().getApplicationServiceRepository();
}
public ServiceRepository getApplicationServiceRepository() {
if (serviceRepository == null) {
serviceRepository = (ServiceRepository) LOADER.getExtension(ServiceRepository.NAME);
serviceRepository = (ServiceRepository) this.getExtensionLoader(FrameworkExt.class)
.getExtension(ServiceRepository.NAME);
}
return serviceRepository;
}
@Deprecated
public static ExecutorRepository getExecutorRepository() {
return ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
return defaultModel().getApplicationExecutorRepository();
}
public static ApplicationConfig getApplicationConfig() {
return getConfigManager().getApplicationOrElseThrow();
}
public static String getName() {
return getApplicationConfig().getName();
public ExecutorRepository getApplicationExecutorRepository() {
return this.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
}
@Deprecated
//It will be remove at next version
private static String application;
public static ApplicationConfig getApplicationConfig() {
return defaultModel().getCurrentConfig();
}
public ApplicationConfig getCurrentConfig() {
return getApplicationConfigManager().getApplicationOrElseThrow();
}
@Deprecated
public static String getName() {
return defaultModel().getCurrentConfig().getName();
}
/**
*
* @deprecated Use {@link #getName()} instead. It will be remove at next version.
*/
@Deprecated
public static String getApplication() {
return application == null ? getName() : application;
return getName();
}
// Currently used by UT, it will be remove at next version.
@Deprecated
public static void setApplication(String application) {
ApplicationModel.application = application;
public String getApplicationName() {
return getCurrentConfig().getName();
}
public void addModule(ModuleModel model) {
if (!this.moduleModels.contains(model)) {
this.moduleModels.add(model);
}
}
public void removeModule(ModuleModel model) {
this.moduleModels.remove(model);
}
public List<ModuleModel> getModuleModels() {
return moduleModels;
}
public synchronized ModuleModel getDefaultModule() {
if (moduleModels.isEmpty()) {
this.addModule(new ModuleModel(this));
}
return moduleModels.get(0);
}
// only for unit test
@Deprecated
public static void reset() {
if (serviceRepository!=null){
serviceRepository.destroy();
serviceRepository = null;
if (defaultInstance != null) {
defaultInstance.destroy();
defaultInstance = null;
}
if (configManager != null) {
configManager.destroy();
configManager = null;
}
if (environment != null) {
environment.destroy();
environment = null;
}
ExtensionLoader.resetExtensionLoader(FrameworkExt.class);
LOADER = ExtensionLoader.getExtensionLoader(FrameworkExt.class);
}
@Override
public String toString() {
return "ApplicationModel";
}
}

View File

@ -16,9 +16,10 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface BuiltinServiceDetector {
Class<?> getService();

View File

@ -16,9 +16,7 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.BaseServiceMetadata;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.utils.ClassUtils;
import org.apache.dubbo.config.ReferenceConfigBase;
import java.lang.reflect.Method;
@ -34,15 +32,11 @@ import java.util.TreeSet;
/**
* This model is bound to your reference's configuration, for example, group, version or method level configuration.
*/
public class ConsumerModel {
private String serviceKey;
private final ServiceDescriptor serviceModel;
private final ReferenceConfigBase<?> referenceConfig;
public class ConsumerModel extends ServiceModel {
private final Set<String> apps = new TreeSet<>();
private Object proxyObject;
private final Map<String, AsyncMethodInfo> methodConfigs;
private Map<Method, ConsumerMethodModel> methodModels = new HashMap<>();
/**
* This constructor create an instance of ConsumerModel and passed objects should not be null.
@ -58,57 +52,43 @@ public class ConsumerModel {
ReferenceConfigBase<?> referenceConfig,
Map<String, AsyncMethodInfo> methodConfigs) {
super(proxyObject, serviceKey, serviceModel, referenceConfig);
Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
this.serviceKey = serviceKey;
this.proxyObject = proxyObject;
this.serviceModel = serviceModel;
this.referenceConfig = referenceConfig;
this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
}
/**
* Return the proxy object used by called while creating instance of ConsumerModel
*
* @return
*/
public Object getProxyObject() {
return proxyObject;
public ConsumerModel(String serviceKey,
Object proxyObject,
ServiceDescriptor serviceModel,
ReferenceConfigBase<?> referenceConfig,
ServiceMetadata metadata,
Map<String, AsyncMethodInfo> methodConfigs) {
super(proxyObject, serviceKey, serviceModel, referenceConfig, metadata);
Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
}
public void setProxyObject(Object proxyObject) {
this.proxyObject = proxyObject;
}
public ConsumerModel(String serviceKey,
Object proxyObject,
ServiceDescriptor serviceModel,
ReferenceConfigBase<?> referenceConfig,
ModuleModel moduleModel,
ServiceMetadata metadata,
Map<String, AsyncMethodInfo> methodConfigs) {
/**
* Return all method models for the current service
*
* @return method model list
*/
public Set<MethodDescriptor> getAllMethods() {
return serviceModel.getAllMethods();
}
super(proxyObject, serviceKey, serviceModel, referenceConfig, moduleModel, metadata);
Assert.notEmptyString(serviceKey, "Service name can't be null or blank");
public Class<?> getServiceInterfaceClass() {
return serviceModel.getServiceInterfaceClass();
}
public String getServiceKey() {
return serviceKey;
this.methodConfigs = methodConfigs == null ? new HashMap<>() : methodConfigs;
}
public AsyncMethodInfo getMethodConfig(String methodName) {
return methodConfigs.get(methodName);
}
public ServiceDescriptor getServiceModel() {
return serviceModel;
}
public ReferenceConfigBase getReferenceConfig() {
return referenceConfig;
}
public Set<String> getApps() {
return apps;
}
@ -117,41 +97,17 @@ public class ConsumerModel {
return methodConfigs.get(methodName);
}
/* *************** Start, metadata compatible **************** */
private ServiceMetadata serviceMetadata;
private Map<Method, ConsumerMethodModel> methodModels = new HashMap<>();
public ConsumerModel(String serviceKey,
Object proxyObject,
ServiceDescriptor serviceModel,
ReferenceConfigBase<?> referenceConfig,
ServiceMetadata metadata,
Map<String, AsyncMethodInfo> methodConfigs) {
this(serviceKey, proxyObject, serviceModel, referenceConfig, methodConfigs);
this.serviceMetadata = metadata;
}
public void setServiceKey(String serviceKey) {
this.serviceKey = serviceKey;
if (serviceMetadata != null) {
serviceMetadata.setServiceKey(serviceKey);
serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey));
}
}
public void initMethodModels() {
Class<?>[] interfaceList;
if (proxyObject == null) {
Class<?> serviceInterfaceClass = referenceConfig.getServiceInterfaceClass();
if (getProxyObject() == null) {
Class<?> serviceInterfaceClass = getReferenceConfig().getServiceInterfaceClass();
if (serviceInterfaceClass != null) {
interfaceList = new Class[]{serviceInterfaceClass};
} else {
interfaceList = new Class[0];
}
} else {
interfaceList = proxyObject.getClass().getInterfaces();
interfaceList = getProxyObject().getClass().getInterfaces();
}
for (Class<?> interfaceClass : interfaceList) {
for (Method method : interfaceClass.getMethods()) {
@ -160,18 +116,6 @@ public class ConsumerModel {
}
}
public ClassLoader getClassLoader() {
Class<?> serviceType = serviceMetadata.getServiceType();
return serviceType != null ? serviceType.getClassLoader() : ClassUtils.getClassLoader();
}
/**
* @return serviceMetadata
*/
public ServiceMetadata getServiceMetadata() {
return serviceMetadata;
}
/**
* Return method model for the given method on consumer side
*
@ -214,10 +158,4 @@ public class ConsumerModel {
public List<ConsumerMethodModel> getAllMethodModels() {
return new ArrayList<>(methodModels.values());
}
public String getServiceName() {
return this.serviceMetadata.getServiceKey();
}
}

View File

@ -0,0 +1,73 @@
/*
* 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.ExtensionDirector;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Model of dubbo framework, it can be shared with multiple applications.
*/
public class FrameworkModel extends ScopeModel {
protected static final Logger LOGGER = LoggerFactory.getLogger(FrameworkModel.class);
private volatile static FrameworkModel defaultInstance;
private List<ApplicationModel> applicationModels = Collections.synchronizedList(new ArrayList<>());
public FrameworkModel() {
super(null, new ExtensionDirector(null, ExtensionScope.FRAMEWORK));
postProcessAfterCreated();
}
public static FrameworkModel defaultModel() {
if (defaultInstance == null) {
synchronized (FrameworkModel.class) {
if (defaultInstance == null) {
defaultInstance = new FrameworkModel();
}
}
}
return defaultInstance;
}
public void addApplication(ApplicationModel model) {
if (!this.applicationModels.contains(model)) {
this.applicationModels.add(model);
}
}
public void removeApplication(ApplicationModel model) {
this.applicationModels.remove(model);
}
public List<ApplicationModel> getApplicationModels() {
return applicationModels;
}
@Override
public String toString() {
return "FrameworkModel";
}
}

View File

@ -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.model;
import org.apache.dubbo.common.extension.ExtensionDirector;
import org.apache.dubbo.common.extension.ExtensionScope;
/**
* Model of a service module
*/
public class ModuleModel extends ScopeModel {
private final ApplicationModel applicationModel;
public ModuleModel(ApplicationModel applicationModel) {
super(applicationModel, new ExtensionDirector(applicationModel.getExtensionDirector(), ExtensionScope.MODULE));
this.applicationModel = applicationModel;
applicationModel.addModule(this);
postProcessAfterCreated();
}
public ApplicationModel getApplicationModel() {
return applicationModel;
}
@Override
public String toString() {
return "ModuleModel";
}
}

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.BaseServiceMetadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.config.ServiceConfigBase;
@ -27,56 +26,57 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* ProviderModel is about published services
*/
public class ProviderModel {
private String serviceKey;
private final Object serviceInstance;
private final ServiceDescriptor serviceModel;
private final ServiceConfigBase<?> serviceConfig;
public class ProviderModel extends ServiceModel {
private final List<RegisterStatedURL> urls;
private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
public ProviderModel(String serviceKey,
Object serviceInstance,
ServiceDescriptor serviceModel,
ServiceConfigBase<?> serviceConfig) {
super(serviceInstance, serviceKey, serviceModel, serviceConfig);
if (null == serviceInstance) {
throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
}
this.serviceKey = serviceKey;
this.serviceInstance = serviceInstance;
this.serviceModel = serviceModel;
this.serviceConfig = serviceConfig;
this.urls = new ArrayList<>(1);
}
public String getServiceKey() {
return serviceKey;
public ProviderModel(String serviceKey,
Object serviceInstance,
ServiceDescriptor serviceModel,
ServiceConfigBase<?> serviceConfig,
ServiceMetadata serviceMetadata) {
super(serviceInstance, serviceKey, serviceModel, serviceConfig, serviceMetadata);
if (null == serviceInstance) {
throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
}
initMethod(serviceModel.getServiceInterfaceClass());
this.urls = new ArrayList<>(1);
}
public ProviderModel(String serviceKey,
Object serviceInstance,
ServiceDescriptor serviceModel,
ServiceConfigBase<?> serviceConfig,
ModuleModel moduleModel,
ServiceMetadata serviceMetadata) {
super(serviceInstance, serviceKey, serviceModel, serviceConfig, moduleModel, serviceMetadata);
if (null == serviceInstance) {
throw new IllegalArgumentException("Service[" + serviceKey + "]Target is NULL.");
}
public Class<?> getServiceInterfaceClass() {
return serviceModel.getServiceInterfaceClass();
initMethod(serviceModel.getServiceInterfaceClass());
this.urls = new ArrayList<>(1);
}
public Object getServiceInstance() {
return serviceInstance;
}
public Set<MethodDescriptor> getAllMethods() {
return serviceModel.getAllMethods();
}
public ServiceDescriptor getServiceModel() {
return serviceModel;
}
public ServiceConfigBase getServiceConfig() {
return serviceConfig;
return getProxyObject();
}
public List<RegisterStatedURL> getStatedUrl() {
@ -125,35 +125,6 @@ public class ProviderModel {
}
}
/* *************** Start, metadata compatible **************** */
private ServiceMetadata serviceMetadata;
private final Map<String, List<ProviderMethodModel>> methods = new HashMap<String, List<ProviderMethodModel>>();
public ProviderModel(String serviceKey,
Object serviceInstance,
ServiceDescriptor serviceModel,
ServiceConfigBase<?> serviceConfig,
ServiceMetadata serviceMetadata) {
this(serviceKey, serviceInstance, serviceModel, serviceConfig);
this.serviceMetadata = serviceMetadata;
initMethod(serviceModel.getServiceInterfaceClass());
}
public void setServiceKey(String serviceKey) {
this.serviceKey = serviceKey;
if (serviceMetadata != null) {
serviceMetadata.setServiceKey(serviceKey);
serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey));
}
}
public String getServiceName() {
return this.serviceMetadata.getServiceKey();
}
public List<ProviderMethodModel> getAllMethodModels() {
List<ProviderMethodModel> result = new ArrayList<ProviderMethodModel>();
for (List<ProviderMethodModel> models : methods.values()) {
@ -195,10 +166,4 @@ public class ProviderModel {
}
}
/**
* @return serviceMetadata
*/
public ServiceMetadata getServiceMetadata() {
return serviceMetadata;
}
}

View File

@ -0,0 +1,59 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.beans.factory.ScopeBeanFactory;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionDirector;
import java.util.Set;
public abstract class ScopeModel implements ExtensionAccessor {
private final ScopeModel parent;
private final ExtensionDirector extensionDirector;
private final ScopeBeanFactory beanFactory;
public ScopeModel(ScopeModel parent, ExtensionDirector extensionDirector) {
this.parent = parent;
this.extensionDirector = extensionDirector;
this.extensionDirector.addExtensionPostProcessor(new ScopeModelAwareExtensionProcessor(this));
this.beanFactory = new ScopeBeanFactory(parent != null ? parent.getBeanFactory() : null, extensionDirector);
}
public ExtensionDirector getExtensionDirector() {
return extensionDirector;
}
public ScopeBeanFactory getBeanFactory() {
return beanFactory;
}
public ScopeModel getParent() {
return parent;
}
protected void postProcessAfterCreated() {
Set<ScopeModelPostProcessor> scopeModelPostProcessors = getExtensionLoader(ScopeModelPostProcessor.class)
.getSupportedExtensionInstances();
for (ScopeModelPostProcessor processor : scopeModelPostProcessors) {
processor.postProcessScopeModel(this);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
/**
* An accessor for scope model, it can be use in interface default methods to get scope model.
*/
public interface ScopeModelAccessor {
ScopeModel getScopeModel();
default FrameworkModel getFrameworkModel() {
return ScopeModelUtil.getFrameworkModel(getScopeModel());
}
default ApplicationModel getApplicationModel() {
return ScopeModelUtil.getApplicationModel(getScopeModel());
}
default ModuleModel getModuleModel() {
return ScopeModelUtil.getModuleModel(getScopeModel());
}
}

View File

@ -0,0 +1,52 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
/**
* An interface to inject FrameworkModel/ApplicationModel/ModuleModel for SPI extensions and internal beans.
*/
public interface ScopeModelAware {
/**
* Override this method if you need get the scope model (maybe one of FrameworkModel/ApplicationModel/ModuleModel).
* @param scopeModel
*/
default void setScopeModel(ScopeModel scopeModel) {
}
/**
* Override this method if you just need framework model
* @param frameworkModel
*/
default void setFrameworkModel(FrameworkModel frameworkModel) {
}
/**
* Override this method if you just need application model
* @param applicationModel
*/
default void setApplicationModel(ApplicationModel applicationModel) {
}
/**
* Override this method if you just need module model
* @param moduleModel
*/
default void setModuleModel(ModuleModel moduleModel) {
}
}

View File

@ -0,0 +1,76 @@
/*
* 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.ExtensionPostProcessor;
public class ScopeModelAwareExtensionProcessor implements ExtensionPostProcessor {
private ScopeModel scopeModel;
private FrameworkModel frameworkModel;
private ApplicationModel applicationModel;
private ModuleModel moduleModel;
private volatile boolean inited;
public ScopeModelAwareExtensionProcessor(ScopeModel scopeModel) {
this.scopeModel = scopeModel;
}
private void init() {
if (inited) {
return;
}
// NOTE: Do not create a new model or use the default application/module model here!
// Only the visible and only matching scope model can be injected, that is, module -> application -> framework.
// The converse is a one-to-many relationship and cannot be injected.
// One framework may have multiple applications, and one application may have multiple modules.
// So, the spi extension/bean of application scope can be injected it's application model and framework model,
// but the spi extension/bean of framework scope cannot be injected an application or module model.
if (scopeModel instanceof FrameworkModel) {
frameworkModel = (FrameworkModel) scopeModel;
} else if (scopeModel instanceof ApplicationModel) {
applicationModel = (ApplicationModel) scopeModel;
frameworkModel = applicationModel.getFrameworkModel();
} else if (scopeModel instanceof ModuleModel) {
moduleModel = (ModuleModel) scopeModel;
applicationModel = moduleModel.getApplicationModel();
frameworkModel = applicationModel.getFrameworkModel();
}
inited = true;
}
@Override
public Object postProcessAfterInitialization(Object instance, String name) throws Exception {
init();
if (instance instanceof ScopeModelAware) {
ScopeModelAware modelAware = (ScopeModelAware) instance;
modelAware.setScopeModel(scopeModel);
if (this.moduleModel != null) {
modelAware.setModuleModel(this.moduleModel);
}
if (this.applicationModel != null) {
modelAware.setApplicationModel(this.applicationModel);
}
if (this.frameworkModel != null) {
modelAware.setFrameworkModel(this.frameworkModel);
}
}
return instance;
}
}

View File

@ -0,0 +1,34 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
/**
* A post-processor after scope model is created (one of FrameworkModel/ApplicationModel/ModuleModel)
*/
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface ScopeModelPostProcessor {
/**
* Post-process after a scope model is created.
* @param scopeModel
*/
void postProcessScopeModel(ScopeModel scopeModel);
}

View File

@ -0,0 +1,80 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
public class ScopeModelUtil {
public static ModuleModel getModuleModel(ScopeModel scopeModel) {
if (scopeModel == null) {
return ApplicationModel.defaultModel().getDefaultModule();
}
if (scopeModel instanceof ModuleModel) {
return (ModuleModel) scopeModel;
} else {
throw new IllegalArgumentException("Unable to get ModuleModel from" + scopeModel);
}
}
public static ApplicationModel getApplicationModel(ScopeModel scopeModel) {
if (scopeModel == null) {
return ApplicationModel.defaultModel();
}
if (scopeModel instanceof ApplicationModel) {
return (ApplicationModel) scopeModel;
} else if (scopeModel instanceof ModuleModel) {
ModuleModel moduleModel = (ModuleModel) scopeModel;
return moduleModel.getApplicationModel();
} else {
throw new IllegalArgumentException("Unable to get ApplicationModel from" + scopeModel);
}
}
public static FrameworkModel getFrameworkModel(ScopeModel scopeModel) {
if (scopeModel == null) {
return FrameworkModel.defaultModel();
}
if (scopeModel instanceof ApplicationModel) {
return ((ApplicationModel) scopeModel).getFrameworkModel();
} else if (scopeModel instanceof ModuleModel) {
ModuleModel moduleModel = (ModuleModel) scopeModel;
return moduleModel.getApplicationModel().getFrameworkModel();
} else if (scopeModel instanceof FrameworkModel) {
return (FrameworkModel) scopeModel;
} else {
throw new IllegalArgumentException("Unable to get FrameworkModel from" + scopeModel);
}
}
public static <T> ExtensionLoader<T> getExtensionLoader(Class<T> type, ScopeModel scopeModel) {
if(scopeModel != null) {
return scopeModel.getExtensionLoader(type);
} else {
SPI spi = type.getAnnotation(SPI.class);
switch (spi.scope()) {
case FRAMEWORK:
return FrameworkModel.defaultModel().getExtensionLoader(type);
case APPLICATION:
return ApplicationModel.defaultModel().getExtensionLoader(type);
default:
return ApplicationModel.defaultModel().getDefaultModule().getExtensionLoader(type);
}
}
}
}

View File

@ -0,0 +1,128 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.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;
import java.util.Set;
public class ServiceModel {
private String serviceKey;
private Object proxyObject;
private final ModuleModel moduleModel;
private final ServiceDescriptor serviceModel;
private final AbstractInterfaceConfig config;
private ServiceMetadata serviceMetadata;
public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config) {
this(proxyObject, serviceKey, serviceModel, config, null);
}
public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ServiceMetadata serviceMetadata) {
this(proxyObject, serviceKey, serviceModel, config, ScopeModelUtil.getModuleModel(config != null ? config.getScopeModel() : null), serviceMetadata);
}
public ServiceModel(Object proxyObject, String serviceKey, ServiceDescriptor serviceModel, AbstractInterfaceConfig config, ModuleModel moduleModel, ServiceMetadata serviceMetadata) {
this.proxyObject = proxyObject;
this.serviceKey = serviceKey;
this.serviceModel = serviceModel;
this.moduleModel = moduleModel;
this.config = config;
this.serviceMetadata = serviceMetadata;
}
public String getServiceKey() {
return serviceKey;
}
public void setProxyObject(Object proxyObject) {
this.proxyObject = proxyObject;
}
public Object getProxyObject() {
return proxyObject;
}
public ServiceDescriptor getServiceModel() {
return serviceModel;
}
public ClassLoader getClassLoader() {
Class<?> serviceType = serviceMetadata.getServiceType();
return serviceType != null ? serviceType.getClassLoader() : ClassUtils.getClassLoader();
}
/**
* Return all method models for the current service
*
* @return method model list
*/
public Set<MethodDescriptor> getAllMethods() {
return serviceModel.getAllMethods();
}
public Class<?> getServiceInterfaceClass() {
return serviceModel.getServiceInterfaceClass();
}
public AbstractInterfaceConfig getConfig() {
return config;
}
public ReferenceConfigBase<?> getReferenceConfig() {
if (config instanceof ReferenceConfigBase) {
return (ReferenceConfigBase<?>) config;
} else {
throw new IllegalArgumentException("Current ServiceModel is not a ConsumerModel");
}
}
public ServiceConfigBase<?> getServiceConfig() {
if (config instanceof ServiceConfigBase) {
return (ServiceConfigBase<?>) config;
} else {
throw new IllegalArgumentException("Current ServiceModel is not a ProviderModel");
}
}
public void setServiceKey(String serviceKey) {
this.serviceKey = serviceKey;
if (serviceMetadata != null) {
serviceMetadata.setServiceKey(serviceKey);
serviceMetadata.setGroup(BaseServiceMetadata.groupFromServiceKey(serviceKey));
}
}
public String getServiceName() {
return this.serviceMetadata.getServiceKey();
}
/**
* @return serviceMetadata
*/
public ServiceMetadata getServiceMetadata() {
return serviceMetadata;
}
public ModuleModel getModuleModel() {
return moduleModel;
}
}

View File

@ -19,7 +19,8 @@ package org.apache.dubbo.rpc.model;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.context.FrameworkExt;
import org.apache.dubbo.common.context.LifecycleAdapter;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.ExtensionAccessor;
import org.apache.dubbo.common.extension.ExtensionAccessorAware;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.StringUtils;
@ -30,14 +31,13 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import static org.apache.dubbo.common.BaseServiceMetadata.interfaceFromServiceKey;
import static org.apache.dubbo.common.BaseServiceMetadata.versionFromServiceKey;
public class ServiceRepository extends LifecycleAdapter implements FrameworkExt {
public class ServiceRepository extends LifecycleAdapter implements FrameworkExt, ExtensionAccessorAware {
public static final String NAME = "repository";
@ -55,10 +55,15 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
// useful to find a url quickly with serviceInterfaceName:version
private ConcurrentMap<String, Set<URL>> providerUrlsWithoutGroup = new ConcurrentHashMap<>();
private ExtensionAccessor extensionAccessor;
public ServiceRepository() {
}
@Override
public void initialize() throws IllegalStateException {
Set<BuiltinServiceDetector> builtinServices
= ExtensionLoader.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
= extensionAccessor.getExtensionLoader(BuiltinServiceDetector.class).getSupportedExtensionInstances();
if (CollectionUtils.isNotEmpty(builtinServices)) {
for (BuiltinServiceDetector service : builtinServices) {
registerService(service.getService());
@ -104,13 +109,16 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
ServiceDescriptor serviceDescriptor,
ReferenceConfigBase<?> rc,
Object proxy,
ServiceMetadata serviceMetadata,
Map<String, AsyncMethodInfo> methodConfigs) {
ServiceMetadata serviceMetadata) {
ConsumerModel consumerModel = new ConsumerModel(serviceMetadata.getServiceKey(), proxy, serviceDescriptor, rc,
serviceMetadata, methodConfigs);
serviceMetadata, null);
consumers.putIfAbsent(serviceKey, consumerModel);
}
public void registerConsumer(ConsumerModel consumerModel) {
consumers.putIfAbsent(consumerModel.getServiceKey(), consumerModel);
}
public void reRegisterConsumer(String newServiceKey, String serviceKey) {
ConsumerModel consumerModel = consumers.get(serviceKey);
consumerModel.setServiceKey(newServiceKey);
@ -124,12 +132,17 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
ServiceDescriptor serviceModel,
ServiceConfigBase<?> serviceConfig,
ServiceMetadata serviceMetadata) {
ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel, serviceConfig,
serviceMetadata);
ProviderModel providerModel = new ProviderModel(serviceKey, serviceInstance, serviceModel,
serviceConfig, serviceMetadata);
providers.putIfAbsent(serviceKey, providerModel);
providersWithoutGroup.putIfAbsent(keyWithoutGroup(serviceKey), providerModel);
}
public void registerProvider(ProviderModel providerModel) {
providers.putIfAbsent(providerModel.getServiceKey(), providerModel);
providersWithoutGroup.putIfAbsent(keyWithoutGroup(providerModel.getServiceKey()), providerModel);
}
private static String keyWithoutGroup(String serviceKey) {
String interfaceName = interfaceFromServiceKey(serviceKey);
String version = versionFromServiceKey(serviceKey);
@ -213,4 +226,9 @@ public class ServiceRepository extends LifecycleAdapter implements FrameworkExt
providers.clear();
providersWithoutGroup.clear();
}
@Override
public void setExtensionAccessor(ExtensionAccessor extensionAccessor) {
this.extensionAccessor = extensionAccessor;
}
}

View File

@ -1,2 +0,0 @@
adaptive=org.apache.dubbo.common.extension.factory.AdaptiveExtensionFactory
spi=org.apache.dubbo.common.extension.factory.SpiExtensionFactory

View File

@ -0,0 +1,3 @@
adaptive=org.apache.dubbo.common.extension.inject.AdaptiveExtensionInjector
spi=org.apache.dubbo.common.extension.inject.SpiExtensionInjector
scopeBean=org.apache.dubbo.common.beans.ScopeBeanExtensionInjector

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.common.config;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -31,14 +33,14 @@ public class ConfigurationUtilsTest {
@Test
public void testGetServerShutdownTimeout () {
System.setProperty(SHUTDOWN_WAIT_KEY, " 10000");
Assertions.assertEquals(10000, ConfigurationUtils.getServerShutdownTimeout());
Assertions.assertEquals(10000, ConfigurationUtils.getServerShutdownTimeout(ApplicationModel.defaultModel()));
System.clearProperty(SHUTDOWN_WAIT_KEY);
}
@Test
public void testGetProperty () {
System.setProperty(SHUTDOWN_WAIT_KEY, " 10000");
Assertions.assertEquals("10000", ConfigurationUtils.getProperty(SHUTDOWN_WAIT_KEY));
Assertions.assertEquals("10000", ConfigurationUtils.getProperty(ApplicationModel.defaultModel(), SHUTDOWN_WAIT_KEY));
System.clearProperty(SHUTDOWN_WAIT_KEY);
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.common.config;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import java.util.LinkedHashMap;
@ -31,7 +32,7 @@ public class EnvironmentTest {
@Test
public void testResolvePlaceholders1() {
Environment environment = ApplicationModel.getEnvironment();
Environment environment = ApplicationModel.defaultModel().getApplicationEnvironment();
Map<String, String> externalMap = new LinkedHashMap<>();
externalMap.put("zookeeper.address", "127.0.0.1");

View File

@ -16,8 +16,9 @@
*/
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.config.ConfigurationUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@ -31,6 +32,6 @@ public class FileSystemDynamicConfigurationFactoryTest {
@Test
public void testGetFactory() {
assertEquals(FileSystemDynamicConfigurationFactory.class, DynamicConfigurationFactory.getDynamicConfigurationFactory("file").getClass());
assertEquals(FileSystemDynamicConfigurationFactory.class, ConfigurationUtils.getDynamicConfigurationFactory(ApplicationModel.defaultModel(), "file").getClass());
}
}

View File

@ -0,0 +1,271 @@
/*
* 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.extension;
import org.apache.dubbo.common.extension.director.FooAppService;
import org.apache.dubbo.common.extension.director.FooFrameworkService;
import org.apache.dubbo.common.extension.director.FooModuleProvider;
import org.apache.dubbo.common.extension.director.FooModuleService;
import org.apache.dubbo.common.extension.director.impl.TestAppService;
import org.apache.dubbo.common.extension.director.impl.TestFrameworkService;
import org.apache.dubbo.common.extension.director.impl.TestModuleService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collection;
public class ExtensionDirectorTest {
String testFwSrvName = "testFwSrv";
String testAppSrvName = "testAppSrv";
String testMdSrvName = "testMdSrv";
String testAppProviderName = "testAppProvider";
String testModuleProviderName = "testModuleProvider";
String testFrameworkProviderName = "testFrameworkProvider";
@Test
public void testInheritanceAndScope() {
// Expecting:
// 1. SPI extension only be created in ExtensionDirector which matched scope
// 2. Child ExtensionDirector can get extension instance from parent
// 3. Parent ExtensionDirector can't get extension instance from child
ExtensionDirector fwExtensionDirector = new ExtensionDirector(null, ExtensionScope.FRAMEWORK);
ExtensionDirector appExtensionDirector = new ExtensionDirector(fwExtensionDirector, ExtensionScope.APPLICATION);
ExtensionDirector moduleExtensionDirector = new ExtensionDirector(appExtensionDirector, ExtensionScope.MODULE);
// test module extension loader
FooFrameworkService testFwSrvFromModule = moduleExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
FooAppService testAppSrvFromModule = moduleExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
FooModuleService testMdSrvFromModule = moduleExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertNotNull(testFwSrvFromModule);
Assertions.assertNotNull(testAppSrvFromModule);
Assertions.assertNotNull(testMdSrvFromModule);
// test app extension loader
FooFrameworkService testFwSrvFromApp = appExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
FooAppService testAppSrvFromApp = appExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
FooModuleService testMdSrvFromApp = appExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertSame(testFwSrvFromApp, testFwSrvFromModule);
Assertions.assertSame(testAppSrvFromApp, testAppSrvFromModule);
Assertions.assertNull(testMdSrvFromApp);
// test framework extension loader
FooFrameworkService testFwSrvFromFw = fwExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
FooAppService testAppSrvFromFw = fwExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
FooModuleService testMdSrvFromFw = fwExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertSame(testFwSrvFromFw, testFwSrvFromApp);
Assertions.assertNull(testAppSrvFromFw);
Assertions.assertNull(testMdSrvFromFw);
}
@Test
public void testPostProcessor() {
}
@Test
public void testModelAware() {
// Expecting:
// 1. Module scope SPI can be injected ModuleModel, ApplicationModel, FrameworkModel
// 2. Application scope SPI can be injected ApplicationModel, FrameworkModel, but not ModuleModel
// 3. Framework scope SPI can be injected FrameworkModel, but not ModuleModel, ApplicationModel
FrameworkModel frameworkModel = new FrameworkModel();
ApplicationModel applicationModel = new ApplicationModel(frameworkModel);
ModuleModel moduleModel = new ModuleModel(applicationModel);
ExtensionDirector moduleExtensionDirector = moduleModel.getExtensionDirector();
ExtensionDirector appExtensionDirector = applicationModel.getExtensionDirector();
ExtensionDirector fwExtensionDirector = frameworkModel.getExtensionDirector();
// check extension director inheritance
Assertions.assertSame(appExtensionDirector, moduleExtensionDirector.getParent());
Assertions.assertSame(fwExtensionDirector, appExtensionDirector.getParent());
Assertions.assertSame(null, fwExtensionDirector.getParent());
// check module extension aware
TestFrameworkService testFwSrvFromModule = (TestFrameworkService) moduleExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
TestAppService testAppSrvFromModule = (TestAppService) moduleExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
TestModuleService testMdSrvFromModule = (TestModuleService) moduleExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertSame(frameworkModel, testFwSrvFromModule.getFrameworkModel());
Assertions.assertSame(null, testFwSrvFromModule.getApplicationModel());
Assertions.assertSame(null, testFwSrvFromModule.getModuleModel());
Assertions.assertSame(frameworkModel, testAppSrvFromModule.getFrameworkModel());
Assertions.assertSame(applicationModel, testAppSrvFromModule.getApplicationModel());
Assertions.assertSame(null, testAppSrvFromModule.getModuleModel());
Assertions.assertSame(frameworkModel, testMdSrvFromModule.getFrameworkModel());
Assertions.assertSame(applicationModel, testMdSrvFromModule.getApplicationModel());
Assertions.assertSame(moduleModel, testMdSrvFromModule.getModuleModel());
// check app extension aware
TestFrameworkService testFwSrvFromApp = (TestFrameworkService) appExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
TestAppService testAppSrvFromApp = (TestAppService) appExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
TestModuleService testMdSrvFromApp = (TestModuleService) appExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertSame(testFwSrvFromApp, testFwSrvFromModule);
Assertions.assertSame(testAppSrvFromApp, testAppSrvFromModule);
Assertions.assertNull(testMdSrvFromApp);
// check framework extension aware
FooFrameworkService testFwSrvFromFw = fwExtensionDirector.getExtension(FooFrameworkService.class, testFwSrvName);
FooAppService testAppSrvFromFw = fwExtensionDirector.getExtension(FooAppService.class, testAppSrvName);
FooModuleService testMdSrvFromFw = fwExtensionDirector.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertSame(testFwSrvFromFw, testFwSrvFromApp);
Assertions.assertNull(testAppSrvFromFw);
Assertions.assertNull(testMdSrvFromFw);
}
@Test
public void testModelDataIsolation() {
//Model Tree
//frameworkModel1
// applicationModel11
// moduleModel111
// moduleModel112
// applicationModel12
// moduleModel121
//frameworkModel2
// applicationModel21
// moduleModel211
FrameworkModel frameworkModel1 = new FrameworkModel();
ApplicationModel applicationModel11 = new ApplicationModel(frameworkModel1);
ModuleModel moduleModel111 = new ModuleModel(applicationModel11);
ModuleModel moduleModel112 = new ModuleModel(applicationModel11);
ApplicationModel applicationModel12 = new ApplicationModel(frameworkModel1);
ModuleModel moduleModel121 = new ModuleModel(applicationModel12);
FrameworkModel frameworkModel2 = new FrameworkModel();
ApplicationModel applicationModel21 = new ApplicationModel(frameworkModel2);
ModuleModel moduleModel211 = new ModuleModel(applicationModel21);
// test model references
Collection<ApplicationModel> applicationsOfFw1 = frameworkModel1.getApplicationModels();
Assertions.assertEquals(2, applicationsOfFw1.size());
Assertions.assertTrue(applicationsOfFw1.contains(applicationModel11));
Assertions.assertTrue(applicationsOfFw1.contains(applicationModel12));
Assertions.assertFalse(applicationsOfFw1.contains(applicationModel21));
Collection<ModuleModel> modulesOfApp11 = applicationModel11.getModuleModels();
Assertions.assertEquals(2, modulesOfApp11.size());
Assertions.assertTrue(modulesOfApp11.contains(moduleModel111));
Assertions.assertTrue(modulesOfApp11.contains(moduleModel112));
// test isolation of FrameworkModel
FooFrameworkService frameworkService1 = frameworkModel1.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
FooFrameworkService frameworkService2 = frameworkModel2.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
Assertions.assertNotSame(frameworkService1, frameworkService2);
// test isolation of ApplicationModel
// applicationModel11 and applicationModel12 are shared frameworkModel1
FooFrameworkService frameworkService11 = applicationModel11.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
FooFrameworkService frameworkService12 = applicationModel12.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
Assertions.assertSame(frameworkService1, frameworkService11);
Assertions.assertSame(frameworkService1, frameworkService12);
// applicationModel11 and applicationModel12 are isolated in application scope
FooAppService applicationService11 = applicationModel11.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
FooAppService applicationService12 = applicationModel12.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
Assertions.assertNotSame(applicationService11, applicationService12);
// applicationModel11 and applicationModel21 are isolated in both framework and application scope
FooFrameworkService frameworkService21 = applicationModel21.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
FooAppService applicationService21 = applicationModel21.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
Assertions.assertNotSame(frameworkService11, frameworkService21);
Assertions.assertNotSame(applicationService11, applicationService21);
// test isolation of ModuleModel
FooModuleService moduleService111 = moduleModel111.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName);
FooModuleService moduleService112 = moduleModel112.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName);
// moduleModel111 and moduleModel112 are isolated in module scope
Assertions.assertNotSame(moduleService111, moduleService112);
// moduleModel111 and moduleModel112 are shared applicationModel11
FooAppService applicationService111 = moduleModel111.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
FooAppService applicationService112 = moduleModel112.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
Assertions.assertSame(applicationService111, applicationService112);
// moduleModel111 and moduleModel121 are isolated in application scope, but shared frameworkModel1
FooAppService applicationService121 = moduleModel121.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
Assertions.assertNotSame(applicationService111, applicationService121);
FooFrameworkService frameworkService111 = moduleModel111.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
FooFrameworkService frameworkService121 = moduleModel121.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
Assertions.assertSame(frameworkService111, frameworkService121);
// moduleModel111 and moduleModel211 are isolated in both framework and application scope
FooModuleService moduleService211 = moduleModel211.getExtensionDirector().getExtension(FooModuleService.class, testMdSrvName);
FooAppService applicationService211 = moduleModel211.getExtensionDirector().getExtension(FooAppService.class, testAppSrvName);
FooFrameworkService frameworkService211 = moduleModel211.getExtensionDirector().getExtension(FooFrameworkService.class, testFwSrvName);
Assertions.assertNotSame(moduleService111, moduleService211);
Assertions.assertNotSame(applicationService111, applicationService211);
Assertions.assertNotSame(frameworkService111, frameworkService211);
}
@Test
public void testInjection() {
// Expect:
// 1. Framework scope extension can be injected to extensions of Framework/Application/Module scope
// 2. Application scope extension can be injected to extensions of Application/Module scope, but not Framework scope
// 3. Module scope extension can be injected to extensions of Module scope, but not Framework/Application scope
FrameworkModel frameworkModel = new FrameworkModel();
ApplicationModel applicationModel = new ApplicationModel(frameworkModel);
ModuleModel moduleModel = new ModuleModel(applicationModel);
// check module service
TestModuleService moduleService = (TestModuleService) moduleModel.getExtensionDirector()
.getExtension(FooModuleService.class, testMdSrvName);
Assertions.assertNotNull(moduleService.getFrameworkService());
Assertions.assertNotNull(moduleService.getFrameworkProvider());
Assertions.assertNotNull(moduleService.getAppService());
Assertions.assertNotNull(moduleService.getAppProvider());
Assertions.assertNotNull(moduleService.getModuleProvider());
// check app service
TestAppService appService = (TestAppService) applicationModel.getExtensionDirector()
.getExtension(FooAppService.class, testAppSrvName);
Assertions.assertNotNull(appService.getFrameworkService());
Assertions.assertNotNull(appService.getFrameworkProvider());
Assertions.assertNotNull(appService.getAppProvider());
Assertions.assertNull(appService.getModuleProvider());
// check framework service
TestFrameworkService frameworkService = (TestFrameworkService) frameworkModel.getExtensionDirector()
.getExtension(FooFrameworkService.class, testFwSrvName);
Assertions.assertNotNull(frameworkService.getFrameworkProvider());
Assertions.assertNull(frameworkService.getAppProvider());
Assertions.assertNull(frameworkService.getModuleProvider());
}
}

View File

@ -61,6 +61,7 @@ import org.apache.dubbo.common.extension.injection.impl.InjectExtImpl;
import org.apache.dubbo.common.lang.Prioritized;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -70,7 +71,6 @@ import java.util.List;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.common.extension.ExtensionLoader.getLoadingStrategies;
import static org.hamcrest.CoreMatchers.allOf;
import static org.hamcrest.CoreMatchers.anyOf;
@ -84,6 +84,11 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.fail;
public class ExtensionLoaderTest {
private <T> ExtensionLoader<T> getExtensionLoader(Class<T> type) {
return ApplicationModel.defaultModel().getExtensionDirector().getExtensionLoader(type);
}
@Test
public void test_getExtensionLoader_Null() throws Exception {
try {
@ -266,7 +271,6 @@ public class ExtensionLoaderTest {
assertThat(ext, instanceOf(AddExt1_ManualAdd1.class));
assertEquals("Manual1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd1.class));
ExtensionLoader.resetExtensionLoader(AddExt1.class);
}
@Test
@ -277,7 +281,6 @@ public class ExtensionLoaderTest {
assertThat(ext, instanceOf(Ext9Empty.class));
assertEquals("ext9", getExtensionLoader(Ext9Empty.class).getExtensionName(Ext9EmptyImpl.class));
ExtensionLoader.resetExtensionLoader(Ext9Empty.class);
}
@Test
@ -299,7 +302,6 @@ public class ExtensionLoaderTest {
AddExt2 adaptive = loader.getAdaptiveExtension();
assertTrue(adaptive instanceof AddExt2_ManualAdaptive);
ExtensionLoader.resetExtensionLoader(AddExt2.class);
}
@Test
@ -338,7 +340,6 @@ public class ExtensionLoaderTest {
assertThat(ext, instanceOf(AddExt1_ManualAdd2.class));
assertEquals("impl1", getExtensionLoader(AddExt1.class).getExtensionName(AddExt1_ManualAdd2.class));
}
ExtensionLoader.resetExtensionLoader(AddExt1.class);
}
@Test
@ -352,7 +353,6 @@ public class ExtensionLoaderTest {
adaptive = loader.getAdaptiveExtension();
assertTrue(adaptive instanceof AddExt3_ManualAdaptive);
ExtensionLoader.resetExtensionLoader(AddExt3.class);
}
@Test
@ -559,7 +559,7 @@ public class ExtensionLoaderTest {
List<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(false),
new DubboInternalLoadingStrategyTest(false));
ExtensionLoader<DuplicatedWithoutOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedWithoutOverriddenExt.class);
ExtensionLoader<DuplicatedWithoutOverriddenExt> extensionLoader = getExtensionLoader(DuplicatedWithoutOverriddenExt.class);
try {
extensionLoader.getExtension("duplicated");
fail();
@ -577,7 +577,7 @@ public class ExtensionLoaderTest {
List<LoadingStrategy> loadingStrategies = ExtensionLoader.getLoadingStrategies();
ExtensionLoader.setLoadingStrategies(new DubboExternalLoadingStrategyTest(true),
new DubboInternalLoadingStrategyTest(true));
ExtensionLoader<DuplicatedOverriddenExt> extensionLoader = ExtensionLoader.getExtensionLoader(DuplicatedOverriddenExt.class);
ExtensionLoader<DuplicatedOverriddenExt> extensionLoader = getExtensionLoader(DuplicatedOverriddenExt.class);
DuplicatedOverriddenExt duplicatedOverriddenExt = extensionLoader.getExtension("duplicated");
assertEquals("DuplicatedOverriddenExt1", duplicatedOverriddenExt.echo());
//recover the loading strategies

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.APPLICATION)
public interface FooAppProvider {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.APPLICATION)
public interface FooAppService {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface FooFrameworkProvider {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.FRAMEWORK)
public interface FooFrameworkService {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.MODULE)
public interface FooModuleProvider {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.Adaptive;
import org.apache.dubbo.common.extension.ExtensionScope;
import org.apache.dubbo.common.extension.SPI;
@SPI(scope = ExtensionScope.MODULE)
public interface FooModuleService {
@Adaptive
void process(URL url);
}

View File

@ -0,0 +1,55 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director.impl;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ScopeModelAware;
import org.apache.dubbo.rpc.model.ModuleModel;
public class BaseTestService implements ScopeModelAware {
private FrameworkModel frameworkModel;
private ApplicationModel applicationModel;
private ModuleModel moduleModel;
@Override
public void setFrameworkModel(FrameworkModel frameworkModel) {
this.frameworkModel = frameworkModel;
}
@Override
public void setApplicationModel(ApplicationModel applicationModel) {
this.applicationModel = applicationModel;
}
@Override
public void setModuleModel(ModuleModel moduleModel) {
this.moduleModel = moduleModel;
}
public FrameworkModel getFrameworkModel() {
return frameworkModel;
}
public ApplicationModel getApplicationModel() {
return applicationModel;
}
public ModuleModel getModuleModel() {
return moduleModel;
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooAppProvider;
public class TestAppProvider implements FooAppProvider {
@Override
public void process(URL url) {
}
}

View File

@ -0,0 +1,72 @@
/*
* 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.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooAppProvider;
import org.apache.dubbo.common.extension.director.FooAppService;
import org.apache.dubbo.common.extension.director.FooFrameworkProvider;
import org.apache.dubbo.common.extension.director.FooFrameworkService;
import org.apache.dubbo.common.extension.director.FooModuleProvider;
public class TestAppService extends BaseTestService implements FooAppService {
private FooFrameworkService frameworkService;
private FooFrameworkProvider frameworkProvider;
private FooAppProvider appProvider;
private FooModuleProvider moduleProvider;
public FooFrameworkService getFrameworkService() {
return frameworkService;
}
public void setFrameworkService(FooFrameworkService frameworkService) {
this.frameworkService = frameworkService;
}
public FooAppProvider getAppProvider() {
return appProvider;
}
public void setAppProvider(FooAppProvider appProvider) {
this.appProvider = appProvider;
}
public FooModuleProvider getModuleProvider() {
return moduleProvider;
}
public void setModuleProvider(FooModuleProvider moduleProvider) {
this.moduleProvider = moduleProvider;
}
public FooFrameworkProvider getFrameworkProvider() {
return frameworkProvider;
}
public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) {
this.frameworkProvider = frameworkProvider;
}
@Override
public void process(URL url) {
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooFrameworkProvider;
public class TestFrameworkProvider implements FooFrameworkProvider {
@Override
public void process(URL url) {
}
}

View File

@ -0,0 +1,61 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooAppProvider;
import org.apache.dubbo.common.extension.director.FooFrameworkProvider;
import org.apache.dubbo.common.extension.director.FooFrameworkService;
import org.apache.dubbo.common.extension.director.FooModuleProvider;
public class TestFrameworkService extends BaseTestService implements FooFrameworkService {
private FooFrameworkProvider frameworkProvider;
private FooAppProvider appProvider;
private FooModuleProvider moduleProvider;
public FooFrameworkProvider getFrameworkProvider() {
return frameworkProvider;
}
public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) {
this.frameworkProvider = frameworkProvider;
}
public FooAppProvider getAppProvider() {
return appProvider;
}
public void setAppProvider(FooAppProvider appProvider) {
this.appProvider = appProvider;
}
public FooModuleProvider getModuleProvider() {
return moduleProvider;
}
public void setModuleProvider(FooModuleProvider moduleProvider) {
this.moduleProvider = moduleProvider;
}
@Override
public void process(URL url) {
}
}

View File

@ -0,0 +1,28 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooModuleProvider;
public class TestModuleProvider implements FooModuleProvider {
public void process(URL url) {
}
}

View File

@ -0,0 +1,83 @@
/*
* 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.extension.director.impl;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.director.FooAppProvider;
import org.apache.dubbo.common.extension.director.FooAppService;
import org.apache.dubbo.common.extension.director.FooFrameworkProvider;
import org.apache.dubbo.common.extension.director.FooFrameworkService;
import org.apache.dubbo.common.extension.director.FooModuleProvider;
import org.apache.dubbo.common.extension.director.FooModuleService;
public class TestModuleService extends BaseTestService implements FooModuleService {
private FooFrameworkService frameworkService;
private FooFrameworkProvider frameworkProvider;
private FooAppService appService;
private FooAppProvider appProvider;
private FooModuleProvider moduleProvider;
public FooFrameworkService getFrameworkService() {
return frameworkService;
}
public void setFrameworkService(FooFrameworkService frameworkService) {
this.frameworkService = frameworkService;
}
public FooAppProvider getAppProvider() {
return appProvider;
}
public void setAppProvider(FooAppProvider appProvider) {
this.appProvider = appProvider;
}
public FooModuleProvider getModuleProvider() {
return moduleProvider;
}
public void setModuleProvider(FooModuleProvider moduleProvider) {
this.moduleProvider = moduleProvider;
}
public FooFrameworkProvider getFrameworkProvider() {
return frameworkProvider;
}
public void setFrameworkProvider(FooFrameworkProvider frameworkProvider) {
this.frameworkProvider = frameworkProvider;
}
public FooAppService getAppService() {
return appService;
}
public void setAppService(FooAppService appService) {
this.appService = appService;
}
@Override
public void process(URL url) {
}
}

View File

@ -25,8 +25,8 @@ import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@ -36,7 +36,6 @@ import java.util.Collection;
import static java.util.Arrays.asList;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.config.context.ConfigManager.DUBBO_CONFIG_MODE;
import static org.apache.dubbo.rpc.model.ApplicationModel.getConfigManager;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
@ -50,7 +49,7 @@ import static org.junit.jupiter.api.Assertions.fail;
*/
public class ConfigManagerTest {
private ConfigManager configManager = getConfigManager();
private ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
@BeforeEach
public void init() {
@ -256,15 +255,16 @@ public class ConfigManagerTest {
try {
// test strict mode
ApplicationModel.reset();
Assertions.assertEquals(ConfigMode.STRICT, getConfigManager().getConfigMode());
ConfigManager configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
Assertions.assertEquals(ConfigMode.STRICT, configManager.getConfigMode());
System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.STRICT.name());
ApplicationModel.reset();
Assertions.assertEquals(ConfigMode.STRICT, getConfigManager().getConfigMode());
Assertions.assertEquals(ConfigMode.STRICT, configManager.getConfigMode());
getConfigManager().addConfig(applicationConfig1);
configManager.addConfig(applicationConfig1);
try {
getConfigManager().addConfig(applicationConfig2);
configManager.addConfig(applicationConfig2);
fail("strict mode cannot add two application configs");
} catch (Exception e) {
assertEquals(IllegalStateException.class, e.getClass());
@ -274,21 +274,23 @@ public class ConfigManagerTest {
// test override mode
System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.OVERRIDE.name());
ApplicationModel.reset();
Assertions.assertEquals(ConfigMode.OVERRIDE, getConfigManager().getConfigMode());
configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
Assertions.assertEquals(ConfigMode.OVERRIDE, configManager.getConfigMode());
getConfigManager().addConfig(applicationConfig1);
getConfigManager().addConfig(applicationConfig2);
assertEquals(applicationConfig2, getConfigManager().getApplicationOrElseThrow());
configManager.addConfig(applicationConfig1);
configManager.addConfig(applicationConfig2);
assertEquals(applicationConfig2, configManager.getApplicationOrElseThrow());
// test ignore mode
System.setProperty(DUBBO_CONFIG_MODE, ConfigMode.IGNORE.name());
ApplicationModel.reset();
Assertions.assertEquals(ConfigMode.IGNORE, getConfigManager().getConfigMode());
configManager = ApplicationModel.defaultModel().getApplicationConfigManager();
Assertions.assertEquals(ConfigMode.IGNORE, configManager.getConfigMode());
getConfigManager().addConfig(applicationConfig1);
getConfigManager().addConfig(applicationConfig2);
assertEquals(applicationConfig1, getConfigManager().getApplicationOrElseThrow());
configManager.addConfig(applicationConfig1);
configManager.addConfig(applicationConfig2);
assertEquals(applicationConfig1, configManager.getApplicationOrElseThrow());
} finally {
System.clearProperty(DUBBO_CONFIG_MODE);
}

Some files were not shown because too many files have changed in this diff Show More