[3.0] Refactor dubbo config (#7891)

fixes #7574
This commit is contained in:
Gong Dewei 2021-06-08 16:44:54 +08:00 committed by GitHub
parent 3cb9ac6564
commit d0454fdbef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
193 changed files with 4702 additions and 2513 deletions

View File

@ -13,7 +13,6 @@ env:
spring-boot.version:1.5.22.RELEASE;
spring-boot.version:2.4.1;
'
DUBBO_SPRING_BOOT_REF: '3.0.x'
jobs:
build-source:
@ -40,7 +39,7 @@ jobs:
- name: "Build Dubbo with Maven"
run: |
cd ./dubbo
./mvnw --batch-mode -U -e --no-transfer-progress clean source:jar install -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean source:jar install -Pjacoco,rat,checkstyle -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -Dmaven.test.skip=true -Dmaven.test.skip.exec=true
- name: "Calculate Dubbo Version"
id: dubbo-version
run: |
@ -73,13 +72,13 @@ jobs:
- name: "Test with Maven with Integration Tests"
timeout-minutes: 40
if: ${{ startsWith( matrix.os, 'ubuntu') }}
run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -Dmaven.wagon.httpconnectionManager.ttlSeconds=120 -Dmaven.wagon.http.retryHandler.count=5 -DskipTests=false -DskipIntegrationTests=false -Dcheckstyle.skip=false -Drat.skip=false -Dmaven.javadoc.skip=true
- name: "Test with Maven without Integration Tests"
env:
DISABLE_FILE_SYSTEM_TEST: true
timeout-minutes: 50
if: ${{ startsWith( matrix.os, 'windows') }}
run: ./mvnw --batch-mode -U -e --no-transfer-progress clean test verify -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"rat.skip=false" -D"maven.javadoc.skip=true"
run: ./mvnw --batch-mode --no-snapshot-updates -e --no-transfer-progress clean test verify -Pjacoco -D"http.keepAlive=false" -D"maven.wagon.http.pool=false" -D"maven.wagon.httpconnectionManager.ttlSeconds=120" -D"maven.wagon.http.retryHandler.count=5" -DskipTests=false -DskipIntegrationTests=true -D"checkstyle.skip=false" -D"rat.skip=false" -D"maven.javadoc.skip=true"
- name: "Pack rat file if failure"
if: failure()
run: 7z a ${{ github.workspace }}/rat.zip *rat.txt -r

View File

@ -21,20 +21,21 @@ import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
public class DefaultGovernanceRuleRepositoryImpl implements GovernanceRuleRepository {
private DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
dynamicConfiguration.addListener(key, group, listener);
}
@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
dynamicConfiguration.removeListener(key, group, listener);
}
@Override
public String getRule(String key, String group, long timeout) throws IllegalStateException {
DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
return dynamicConfiguration.getConfig(key, group, timeout);
}
}

View File

@ -113,6 +113,11 @@ public @interface Reference {
String[] parameters() default {};
/**
* Application associated name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
String module() default "";

View File

@ -113,6 +113,11 @@ public @interface Service {
String[] parameters() default {};
/**
* Application associated name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
String module() default "";

View File

@ -72,6 +72,16 @@ public final class Version {
return VERSION;
}
/**
* Compare versions
* @return the value {@code 0} if {@code version1 == version2};
* a value less than {@code 0} if {@code version1 < version2}; and
* a value greater than {@code 0} if {@code version1 > version2}
*/
public static int compare(String version1, String version2) {
return Integer.compare (getIntVersion(version1), getIntVersion(version2));
}
/**
* Check the framework release version number to decide if it's 2.7.0 or higher
*/

View File

@ -18,7 +18,6 @@ package org.apache.dubbo.common.config;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.Arrays;
import java.util.LinkedList;
@ -30,9 +29,6 @@ import java.util.List;
public class CompositeConfiguration implements Configuration {
private Logger logger = LoggerFactory.getLogger(CompositeConfiguration.class);
private String id;
private String prefix;
/**
* List holding all the configuration
*/
@ -42,16 +38,6 @@ public class CompositeConfiguration implements Configuration {
private boolean dynamicIncluded;
public CompositeConfiguration() {
this(null, null);
}
public CompositeConfiguration(String prefix, String id) {
if (StringUtils.isNotEmpty(prefix) && !prefix.endsWith(".")) {
this.prefix = prefix + ".";
} else {
this.prefix = prefix;
}
this.id = id;
}
public CompositeConfiguration(Configuration... configurations) {
@ -87,42 +73,17 @@ public class CompositeConfiguration implements Configuration {
@Override
public Object getInternalProperty(String key) {
Configuration firstMatchingConfiguration = null;
for (Configuration config : configList) {
try {
if (config.containsKey(key)) {
firstMatchingConfiguration = config;
break;
Object value = config.getProperty(key);
if (!ConfigurationUtils.isEmptyValue(value)) {
return value;
}
} catch (Exception e) {
logger.error("Error when trying to get value for key " + key + " from " + config + ", will continue to try the next one.");
}
}
if (firstMatchingConfiguration != null) {
return firstMatchingConfiguration.getProperty(key);
} else {
return null;
}
return null;
}
@Override
public boolean containsKey(String key) {
return configList.stream().anyMatch(c -> c.containsKey(key));
}
@Override
public Object getProperty(String key, Object defaultValue) {
Object value = null;
if (StringUtils.isNotEmpty(prefix)) {
if (StringUtils.isNotEmpty(id)) {
value = getInternalProperty(prefix + id + "." + key);
}
if (value == null) {
value = getInternalProperty(prefix + key);
}
} else {
value = getInternalProperty(key);
}
return value != null ? value : defaultValue;
}
}

View File

@ -18,6 +18,8 @@ package org.apache.dubbo.common.config;
import java.util.NoSuchElementException;
import static org.apache.dubbo.common.config.ConfigurationUtils.isEmptyValue;
/**
* Configuration interface, to fetch the value for the specified key.
*/
@ -133,7 +135,7 @@ public interface Configuration {
* key, {@code false} otherwise
*/
default boolean containsKey(String key) {
return getProperty(key) != null;
return !isEmptyValue(getProperty(key));
}

View File

@ -23,9 +23,13 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import java.io.IOException;
import java.io.StringReader;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVER_SHUTDOWN_TIMEOUT;
@ -137,4 +141,97 @@ public class ConfigurationUtils {
return map;
}
public static boolean isEmptyValue(Object value) {
return value == null ||
value instanceof String && StringUtils.isBlank((String) value);
}
/**
* Search props and extract sub properties.
* <pre>
* # properties
* dubbo.protocol.name=dubbo
* dubbo.protocol.port=1234
*
* # extract protocol props
* Map props = getSubProperties("dubbo.protocol.");
*
* # result
* props: {"name": "dubbo", "port" : "1234"}
*
* </pre>
* @param configMaps
* @param prefix
* @param <V>
* @return
*/
public static <V extends Object> Map<String, V> getSubProperties(Collection<Map<String, V>> configMaps, String prefix) {
if (!prefix.endsWith(".")) {
prefix += ".";
}
String finalPrefix = prefix;
Map<String, V> map = new LinkedHashMap<>();
for (Map<String, V> configMap : configMaps) {
configMap.forEach((key, val) -> {
if (StringUtils.startsWithIgnoreCase(key, finalPrefix) && !ConfigurationUtils.isEmptyValue(val)) {
String k = key.substring(finalPrefix.length());
// convert camelCase/snake_case to kebab-case
k = StringUtils.convertToSplitName(k, "-");
map.putIfAbsent(k, val);
}
});
}
return map;
}
public static <V extends Object> boolean hasSubProperties(Collection<Map<String, V>> configMaps, String prefix) {
if (!prefix.endsWith(".")) {
prefix += ".";
}
for (Map<String, V> configMap : configMaps) {
for (Map.Entry<String, V> entry : configMap.entrySet()) {
String key = entry.getKey();
if (StringUtils.startsWithIgnoreCase(key, prefix) && !ConfigurationUtils.isEmptyValue(entry.getValue())) {
return true;
}
}
}
return false;
}
/**
* Search props and extract config ids
* <pre>
* # properties
* dubbo.registries.registry1.address=xxx
* dubbo.registries.registry2.port=xxx
*
* # extract ids
* Set configIds = getSubIds("dubbo.registries.")
*
* # result
* configIds: ["registry1", "registry2"]
* </pre>
*
* @param configMaps
* @param prefix
* @return
*/
public static <V extends Object> Set<String> getSubIds(Collection<Map<String, V>> configMaps, String prefix) {
Set<String> ids = new LinkedHashSet<>();
for (Map<String, V> configMap : configMaps) {
configMap.forEach((key, val) -> {
if (StringUtils.startsWithIgnoreCase(key, prefix) && !ConfigurationUtils.isEmptyValue(val)) {
String k = key.substring(prefix.length());
int endIndex = k.indexOf(".");
if (endIndex > 0) {
String id = k.substring(0, endIndex);
ids.add(id);
}
}
});
}
return ids;
}
}

View File

@ -25,62 +25,60 @@ import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.context.ConfigConfigurationAdapter;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;
public class Environment extends LifecycleAdapter implements FrameworkExt {
private static final Logger logger = LoggerFactory.getLogger(Environment.class);
public static final String NAME = "environment";
private final PropertiesConfiguration propertiesConfiguration;
private final SystemConfiguration systemConfiguration;
private final EnvironmentConfiguration environmentConfiguration;
private final InmemoryConfiguration externalConfiguration;
private final InmemoryConfiguration appExternalConfiguration;
// dubbo properties in classpath
private PropertiesConfiguration propertiesConfiguration;
// java system props (-D)
private SystemConfiguration systemConfiguration;
// java system environment
private EnvironmentConfiguration environmentConfiguration;
// external config, such as config-center global/default config
private InmemoryConfiguration externalConfiguration;
// external app config, such as config-center app config
private InmemoryConfiguration appExternalConfiguration;
// local app config , such as Spring Environment/PropertySources/application.properties
private InmemoryConfiguration appConfiguration;
private CompositeConfiguration globalConfiguration;
private CompositeConfiguration dynamicGlobalConfiguration;
private Map<String, String> externalConfigurationMap = new HashMap<>();
private Map<String, String> appExternalConfigurationMap = new HashMap<>();
private boolean configCenterFirst = true;
private DynamicConfiguration dynamicConfiguration;
private String localMigrationRule;
private AtomicBoolean initialized = new AtomicBoolean(false);
public Environment() {
this.propertiesConfiguration = new PropertiesConfiguration();
this.systemConfiguration = new SystemConfiguration();
this.environmentConfiguration = new EnvironmentConfiguration();
this.externalConfiguration = new InmemoryConfiguration();
this.appExternalConfiguration = new InmemoryConfiguration();
}
@Override
public void initialize() throws IllegalStateException {
ConfigManager configManager = ApplicationModel.getConfigManager();
Optional<Collection<ConfigCenterConfig>> defaultConfigs = configManager.getDefaultConfigCenter();
defaultConfigs.ifPresent(configs -> {
for (ConfigCenterConfig config : configs) {
this.setExternalConfigMap(config.getExternalConfiguration());
this.setAppExternalConfigMap(config.getAppExternalConfiguration());
}
});
if (initialized.compareAndSet(false, true)) {
this.propertiesConfiguration = new PropertiesConfiguration();
this.systemConfiguration = new SystemConfiguration();
this.environmentConfiguration = new EnvironmentConfiguration();
this.externalConfiguration = new InmemoryConfiguration("ExternalConfig");
this.appExternalConfiguration = new InmemoryConfiguration("AppExternalConfig");
this.appConfiguration = new InmemoryConfiguration("AppConfig");
this.externalConfiguration.setProperties(externalConfigurationMap);
this.appExternalConfiguration.setProperties(appExternalConfigurationMap);
loadMigrationRule();
loadMigrationRule();
}
}
private void loadMigrationRule() {
@ -97,31 +95,50 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
@DisableInject
public void setExternalConfigMap(Map<String, String> externalConfiguration) {
if (externalConfiguration != null) {
this.externalConfigurationMap = externalConfiguration;
this.externalConfiguration.setProperties(externalConfiguration);
}
}
@DisableInject
public void setAppExternalConfigMap(Map<String, String> appExternalConfiguration) {
if (appExternalConfiguration != null) {
this.appExternalConfigurationMap = appExternalConfiguration;
this.appExternalConfiguration.setProperties(appExternalConfiguration);
}
}
public Map<String, String> getExternalConfigurationMap() {
return externalConfigurationMap;
@DisableInject
public void setAppConfigMap(Map<String, String> appConfiguration) {
if (appConfiguration != null) {
this.appConfiguration.setProperties(appConfiguration);
}
}
public Map<String, String> getAppExternalConfigurationMap() {
return appExternalConfigurationMap;
public Map<String, String> getExternalConfigMap() {
return externalConfiguration.getProperties();
}
public void updateExternalConfigurationMap(Map<String, String> externalMap) {
this.externalConfigurationMap.putAll(externalMap);
public Map<String, String> getAppExternalConfigMap() {
return appExternalConfiguration.getProperties();
}
public void updateAppExternalConfigurationMap(Map<String, String> externalMap) {
this.appExternalConfigurationMap.putAll(externalMap);
public Map<String, String> getAppConfigMap() {
return appConfiguration.getProperties();
}
public void updateExternalConfigMap(Map<String, String> externalMap) {
this.externalConfiguration.addProperties(externalMap);
}
public void updateAppExternalConfigMap(Map<String, String> externalMap) {
this.appExternalConfiguration.addProperties(externalMap);
}
/**
* Merge target map properties into app configuration
* @param map
*/
public void updateAppConfigMap(Map<String, String> map) {
this.appConfiguration.addProperties(map);
}
/**
@ -132,31 +149,23 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
* This method helps us to filter out the most priority values from various configuration sources.
*
* @param config
* @param prefix
* @return
*/
public synchronized CompositeConfiguration getPrefixedConfiguration(AbstractConfig config) {
CompositeConfiguration prefixedConfiguration = new CompositeConfiguration(config.getPrefix(), config.getId());
Configuration configuration = new ConfigConfigurationAdapter(config);
if (this.isConfigCenterFirst()) {
// The sequence would be: SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AbstractConfig -> PropertiesConfiguration
// Config center has the highest priority
prefixedConfiguration.addConfiguration(systemConfiguration);
prefixedConfiguration.addConfiguration(environmentConfiguration);
prefixedConfiguration.addConfiguration(appExternalConfiguration);
prefixedConfiguration.addConfiguration(externalConfiguration);
prefixedConfiguration.addConfiguration(configuration);
prefixedConfiguration.addConfiguration(propertiesConfiguration);
} else {
// The sequence would be: SystemConfiguration -> AbstractConfig -> AppExternalConfiguration -> ExternalConfiguration -> PropertiesConfiguration
// Config center has the highest priority
prefixedConfiguration.addConfiguration(systemConfiguration);
prefixedConfiguration.addConfiguration(environmentConfiguration);
prefixedConfiguration.addConfiguration(configuration);
prefixedConfiguration.addConfiguration(appExternalConfiguration);
prefixedConfiguration.addConfiguration(externalConfiguration);
prefixedConfiguration.addConfiguration(propertiesConfiguration);
}
return prefixedConfiguration;
public Configuration getPrefixedConfiguration(AbstractConfig config, String prefix) {
// The sequence would be: SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AppConfiguration -> AbstractConfig -> PropertiesConfiguration
Configuration instanceConfiguration = new ConfigConfigurationAdapter(config, prefix);
CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
compositeConfiguration.addConfiguration(systemConfiguration);
compositeConfiguration.addConfiguration(environmentConfiguration);
compositeConfiguration.addConfiguration(appExternalConfiguration);
compositeConfiguration.addConfiguration(externalConfiguration);
compositeConfiguration.addConfiguration(appConfiguration);
compositeConfiguration.addConfiguration(instanceConfiguration);
compositeConfiguration.addConfiguration(propertiesConfiguration);
return new PrefixedConfiguration(compositeConfiguration, prefix);
}
/**
@ -165,18 +174,50 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
* 2. The configuration exposed in this method is convenient for us to query the latest values from multiple
* prioritized sources, it also guarantees that configs changed dynamically can take effect on the fly.
*/
public Configuration getConfiguration() {
public CompositeConfiguration getConfiguration() {
if (globalConfiguration == null) {
globalConfiguration = new CompositeConfiguration();
globalConfiguration.addConfiguration(systemConfiguration);
globalConfiguration.addConfiguration(environmentConfiguration);
globalConfiguration.addConfiguration(appExternalConfiguration);
globalConfiguration.addConfiguration(externalConfiguration);
globalConfiguration.addConfiguration(appConfiguration);
globalConfiguration.addConfiguration(propertiesConfiguration);
}
return globalConfiguration;
}
/**
* Get configuration map list for target instance
* @param config
* @param prefix
* @return
*/
public List<Map<String, String>> getConfigurationMaps(AbstractConfig config, String prefix) {
// The sequence would be: SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AppConfiguration -> AbstractConfig -> PropertiesConfiguration
List<Map<String, String>> maps = new ArrayList<>();
maps.add(systemConfiguration.getProperties());
maps.add(environmentConfiguration.getProperties());
maps.add(appExternalConfiguration.getProperties());
maps.add(externalConfiguration.getProperties());
maps.add(appConfiguration.getProperties());
if (config != null) {
ConfigConfigurationAdapter configurationAdapter = new ConfigConfigurationAdapter(config, prefix);
maps.add(configurationAdapter.getProperties());
}
maps.add(propertiesConfiguration.getProperties());
return maps;
}
/**
* Get global configuration as map list
* @return
*/
public List<Map<String, String>> getConfigurationMaps() {
return getConfigurationMaps(null, null);
}
public Configuration getDynamicGlobalConfiguration() {
if (dynamicGlobalConfiguration == null) {
if (dynamicConfiguration == null) {
@ -192,15 +233,6 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
return dynamicGlobalConfiguration;
}
public boolean isConfigCenterFirst() {
return configCenterFirst;
}
@DisableInject
public void setConfigCenterFirst(boolean configCenterFirst) {
this.configCenterFirst = configCenterFirst;
}
public Optional<DynamicConfiguration> getDynamicConfiguration() {
return Optional.ofNullable(dynamicConfiguration);
}
@ -212,13 +244,31 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
@Override
public void destroy() throws IllegalStateException {
clearExternalConfigs();
clearAppExternalConfigs();
initialized.set(false);
systemConfiguration = null;
propertiesConfiguration = null;
environmentConfiguration = null;
externalConfiguration = null;
appExternalConfiguration = null;
appConfiguration = null;
globalConfiguration = null;
dynamicConfiguration = null;
dynamicGlobalConfiguration = null;
}
/**
* Reset environment.
* For test only.
*/
public void reset() {
destroy();
initialize();
}
public String resolvePlaceholders(String str) {
return ConfigUtils.replaceProperty(str, getConfiguration());
}
public PropertiesConfiguration getPropertiesConfiguration() {
return propertiesConfiguration;
}
@ -239,19 +289,12 @@ public class Environment extends LifecycleAdapter implements FrameworkExt {
return appExternalConfiguration;
}
public InmemoryConfiguration getAppConfiguration() {
return appConfiguration;
}
public String getLocalMigrationRule() {
return localMigrationRule;
}
// For test
public void clearExternalConfigs() {
this.externalConfiguration.clear();
this.externalConfigurationMap.clear();
}
// For test
public void clearAppExternalConfigs() {
this.appExternalConfiguration.clear();
this.appExternalConfigurationMap.clear();
}
}

View File

@ -18,6 +18,8 @@ package org.apache.dubbo.common.config;
import org.apache.dubbo.common.utils.StringUtils;
import java.util.Map;
/**
* Configuration from system environment
*/
@ -32,4 +34,7 @@ public class EnvironmentConfiguration implements Configuration {
return value;
}
public Map<String, String> getProperties() {
return System.getenv();
}
}

View File

@ -24,9 +24,22 @@ import java.util.Map;
*/
public class InmemoryConfiguration implements Configuration {
private String name;
// stores the configuration key-value pairs
private Map<String, String> store = new LinkedHashMap<>();
public InmemoryConfiguration() {
}
public InmemoryConfiguration(String name) {
this.name = name;
}
public InmemoryConfiguration(Map<String, String> properties) {
this.setProperties(properties);
}
@Override
public Object getInternalProperty(String key) {
return store.get(key);
@ -57,8 +70,8 @@ public class InmemoryConfiguration implements Configuration {
}
}
// for unit test
public void clear() {
this.store.clear();
public Map<String, String> getProperties() {
return store;
}
}

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.config;
import org.apache.dubbo.common.utils.StringUtils;
public class PrefixedConfiguration implements Configuration {
private String prefix;
private Configuration origin;
public PrefixedConfiguration(Configuration origin, String prefix) {
this.origin = origin;
this.prefix = prefix;
}
@Override
public Object getInternalProperty(String key) {
if (StringUtils.isBlank(prefix)) {
return origin.getInternalProperty(key);
}
Object value = origin.getInternalProperty(prefix + "." + key);
if (!ConfigurationUtils.isEmptyValue(value)) {
return value;
}
return null;
}
}

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.ConfigUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
@ -30,6 +31,7 @@ import java.util.Set;
public class PropertiesConfiguration implements Configuration {
public PropertiesConfiguration() {
ExtensionLoader<OrderedPropertiesProvider> propertiesProviderExtensionLoader = ExtensionLoader.getExtensionLoader(OrderedPropertiesProvider.class);
Set<String> propertiesProviderNames = propertiesProviderExtensionLoader.getSupportedExtensions();
if (propertiesProviderNames == null || propertiesProviderNames.isEmpty()) {
@ -54,11 +56,14 @@ public class PropertiesConfiguration implements Configuration {
properties.putAll(orderedPropertiesProvider.initProperties());
}
ConfigUtils.setProperties(properties);
}
@Override
public Object getInternalProperty(String key) {
return ConfigUtils.getProperty(key);
}
public Map<String, String> getProperties() {
return (Map) ConfigUtils.getProperties();
}
}

View File

@ -17,6 +17,8 @@
package org.apache.dubbo.common.config;
import java.util.Map;
/**
* FIXME: is this really necessary? PropertiesConfiguration should have already covered this:
*
@ -30,4 +32,7 @@ public class SystemConfiguration implements Configuration {
return System.getProperty(key);
}
public Map<String, String> getProperties() {
return (Map) System.getProperties();
}
}

View File

@ -205,6 +205,13 @@ public class ExtensionLoader<T> {
}
}
});
// 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();
}
private static ClassLoader findClassLoader() {

View File

@ -226,5 +226,14 @@ public class DefaultExecutorRepository implements ExecutorRepository {
});
}
});
// TODO shutdown all executor services
// for (ScheduledExecutorService executorService : scheduledExecutors.listItems()) {
// executorService.shutdown();
// }
//
// for (ExecutorService executorService : executorServiceRing.listItems()) {
// executorService.shutdown();
// }
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.common.utils;
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.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
@ -128,6 +130,10 @@ public class ConfigUtils {
}
public static String replaceProperty(String expression, Map<String, String> params) {
return replaceProperty(expression, new InmemoryConfiguration(params));
}
public static String replaceProperty(String expression, Configuration configuration) {
if (expression == null || expression.length() == 0 || expression.indexOf('$') < 0) {
return expression;
}
@ -136,11 +142,13 @@ public class ConfigUtils {
while (matcher.find()) {
String key = matcher.group(1);
String value = System.getProperty(key);
if (value == null && params != null) {
value = params.get(key);
if (value == null && configuration != null) {
Object val = configuration.getProperty(key);
value = (val != null) ? val.toString() : null;
}
if (value == null) {
value = "";
// maybe not placeholders, use origin express
value = matcher.group();
}
matcher.appendReplacement(sb, Matcher.quoteReplacement(value));
}
@ -148,7 +156,13 @@ public class ConfigUtils {
return sb.toString();
}
/**
* Get dubbo properties.
* It is not recommended to use this method to modify dubbo properties.
* @return
*/
public static Properties getProperties() {
//TODO remove global instance PROPERTIES from ConfigUtils
if (PROPERTIES == null) {
synchronized (ConfigUtils.class) {
if (PROPERTIES == null) {
@ -166,10 +180,18 @@ public class ConfigUtils {
return PROPERTIES;
}
/**
* This method should be called before Dubbo starting.
* It is not recommended to use this method to modify dubbo properties.
*/
public static void setProperties(Properties properties) {
PROPERTIES = properties;
}
/**
* This method should be called before Dubbo starting.
* It is not recommended to use this method to modify dubbo properties.
*/
public static void addProperties(Properties properties) {
if (properties != null) {
getProperties().putAll(properties);
@ -186,7 +208,10 @@ public class ConfigUtils {
if (value != null && value.length() > 0) {
return value;
}
Properties properties = getProperties();
return getProperty(getProperties(), key, defaultValue);
}
public static String getProperty(Properties properties, String key, String defaultValue) {
return replaceProperty(properties.getProperty(key, defaultValue), (Map) properties);
}

View File

@ -23,6 +23,7 @@ import javassist.NotFoundException;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@ -44,6 +45,7 @@ import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -1306,6 +1308,25 @@ public final class ReflectUtils {
return propertyValue;
}
/**
* Check target bean class whether has specify method
* @param beanClass
* @param methodName
* @return
*/
public static boolean hasMethod(Class<?> beanClass, String methodName) {
try {
BeanInfo beanInfo = Introspector.getBeanInfo(beanClass);
Optional<MethodDescriptor> descriptor = Stream.of(beanInfo.getMethodDescriptors())
.filter(methodDescriptor -> methodName.equals(methodDescriptor.getName()))
.findFirst();
return descriptor.isPresent();
} catch (Exception e) {
}
return false;
}
/**
* Resolve the types of the specified values
*
@ -1347,4 +1368,26 @@ public final class ReflectUtils {
method.setAccessible(true);
}
}
/**
* Get all field names of target type
* @param type
* @return
*/
public static Set<String> getAllFieldNames(Class<?> type) {
Set<String> fieldNames = new HashSet<>();
for (Field field : type.getDeclaredFields()) {
fieldNames.add(field.getName());
}
Set<Class<?>> allSuperClasses = ClassUtils.getAllSuperClasses(type);
for (Class<?> aClass : allSuperClasses) {
for (Field field : aClass.getDeclaredFields()) {
fieldNames.add(field.getName());
}
}
return fieldNames;
}
}

View File

@ -425,6 +425,15 @@ public final class StringUtils {
return true;
}
/**
* Check the cs String whether contains non whitespace characters.
* @param cs
* @return
*/
public static boolean hasText(CharSequence cs) {
return !isBlank(cs);
}
/**
* is empty string.
*
@ -894,6 +903,15 @@ public final class StringUtils {
if (isEmpty(camelName)) {
return camelName;
}
if (!isWord(camelName)) {
// convert Ab-Cd-Ef to ab-cd-ef
if (isSplitCase(camelName, split.charAt(0))) {
return camelName.toLowerCase();
}
// not camel case
return camelName;
}
StringBuilder buf = null;
for (int i = 0; i < camelName.length(); i++) {
char ch = camelName.charAt(i);
@ -912,7 +930,64 @@ public final class StringUtils {
buf.append(ch);
}
}
return buf == null ? camelName : buf.toString();
return buf == null ? camelName.toLowerCase() : buf.toString().toLowerCase();
}
private static boolean isSplitCase(String str, char separator) {
if (str == null) {
return false;
}
return str.chars().allMatch(ch -> (ch == separator) || isWord((char)ch) );
}
private static boolean isWord(String str) {
if (str == null) {
return false;
}
return str.chars().allMatch(ch -> isWord((char)ch));
}
private static boolean isWord(char ch) {
if ((ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
(ch >= '0' && ch <= '9')) {
return true;
}
return false;
}
/**
* Convert snake_case or SNAKE_CASE to kebab-case.
* <p>
* NOTE: Return itself if it's not a snake case.
* @param snakeName
* @param split
* @return
*/
public static String snakeToSplitName(String snakeName, String split) {
String lowerCase = snakeName.toLowerCase();
if (isSnakeCase(snakeName)) {
return replace(lowerCase, "_", split);
}
return snakeName;
}
protected static boolean isSnakeCase(String str) {
return str.contains("_") || str.equals(str.toLowerCase()) || str.equals(str.toUpperCase());
}
/**
* Convert camelCase or snake_case/SNAKE_CASE to kebab-case
* @param str
* @param split
* @return
*/
public static String convertToSplitName(String str, String split) {
if (isSnakeCase(str)) {
return snakeToSplitName(str, split);
} else {
return camelToSplitName(str, split);
}
}
public static String toArgumentString(Object[] args) {
@ -1051,11 +1126,14 @@ public final class StringUtils {
}
/**
* Decode parameters string to map
* @param rawParameters format like '[{a:b},{c:d}]'
* @return
*/
public static Map<String, String> parseParameters(String rawParameters) {
if (StringUtils.isBlank(rawParameters)) {
return Collections.emptyMap();
}
Matcher matcher = PARAMETERS_PATTERN.matcher(rawParameters);
if (!matcher.matches()) {
return Collections.emptyMap();
@ -1074,6 +1152,32 @@ public final class StringUtils {
return parameters;
}
/**
* Encode parameters map to string, like '[{a:b},{c:d}]'
* @param params
* @return
*/
public static String encodeParameters(Map<String, String> params) {
if (params == null || params.isEmpty()) {
return null;
}
StringBuilder sb = new StringBuilder();
sb.append("[");
params.forEach((key,value) -> {
// {key:value},
if (hasText(value)) {
sb.append("{").append(key).append(":").append(value).append("},");
}
});
// delete last separator ','
if (sb.charAt(sb.length() - 1) == ',') {
sb.deleteCharAt(sb.length()-1);
}
sb.append("]");
return sb.toString();
}
public static int decodeHexNibble(final char c) {
// Character.digit() is not used here, as it addresses a larger
// set of characters (both ASCII and full-width latin letters).
@ -1106,4 +1210,18 @@ public final class StringUtils {
String another = arrayToDelimitedString(others, COMMA_SEPARATOR);
return isEmpty(another) ? one : one + COMMA_SEPARATOR + another;
}
/**
* Test str whether starts with the prefix ignore case.
* @param str
* @param prefix
* @return
*/
public static boolean startsWithIgnoreCase(String str, String prefix) {
if (str == null || prefix == null || str.length() < prefix.length()) {
return false;
}
// return str.substring(0, prefix.length()).equalsIgnoreCase(prefix);
return str.regionMatches(true, 0, prefix, 0, prefix.length());
}
}

View File

@ -17,8 +17,9 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.CompositeConfiguration;
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.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -33,16 +34,25 @@ import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.AsyncMethodInfo;
import javax.annotation.PostConstruct;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.beans.PropertyDescriptor;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
@ -59,31 +69,19 @@ public abstract class AbstractConfig implements Serializable {
private static final long serialVersionUID = 4267533505537413570L;
/**
* The legacy properties container
* The field names cache of config class
*/
private static final Map<String, String> LEGACY_PROPERTIES = new HashMap<String, String>();
private static final Map<Class, Set<String>> fieldNamesCache = new ConcurrentHashMap<>();
/**
* The suffix container
*/
private static final String[] SUFFIXES = new String[]{"Config", "Bean", "ConfigBase"};
static {
LEGACY_PROPERTIES.put("dubbo.protocol.name", "dubbo.service.protocol");
LEGACY_PROPERTIES.put("dubbo.protocol.host", "dubbo.service.server.host");
LEGACY_PROPERTIES.put("dubbo.protocol.port", "dubbo.service.server.port");
LEGACY_PROPERTIES.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size");
LEGACY_PROPERTIES.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout");
LEGACY_PROPERTIES.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
LEGACY_PROPERTIES.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
LEGACY_PROPERTIES.put("dubbo.service.url", "dubbo.service.address");
}
/**
* The config id
*/
protected String id;
protected String prefix;
private String id;
protected final AtomicBoolean refreshed = new AtomicBoolean(false);
@ -92,16 +90,6 @@ public abstract class AbstractConfig implements Serializable {
*/
protected Boolean isDefault;
private static String convertLegacyValue(String key, String value) {
if (value != null && value.length() > 0) {
if ("dubbo.service.max.retry.providers".equals(key)) {
return String.valueOf(Integer.parseInt(value) - 1);
} else if ("dubbo.service.allow.no.provider".equals(key)) {
return String.valueOf(!Boolean.parseBoolean(value));
}
}
return value;
}
public static String getTagName(Class<?> cls) {
String tag = cls.getSimpleName();
@ -114,57 +102,25 @@ public abstract class AbstractConfig implements Serializable {
return StringUtils.camelToSplitName(tag, "-");
}
public static String getPluralTagName(Class<?> cls) {
String tagName = getTagName(cls);
if (tagName.endsWith("y")) {
// e.g. registry -> registries
return tagName.substring(0, tagName.length() - 1) + "ies";
} else if (tagName.endsWith("s")) {
// e.g. metrics -> metricses
return tagName + "es";
}
return tagName + "s";
}
public static void appendParameters(Map<String, String> parameters, Object config) {
appendParameters(parameters, config, null);
}
@SuppressWarnings("unchecked")
public static void appendParameters(Map<String, String> parameters, Object config, String prefix) {
if (config == null) {
return;
}
Method[] methods = config.getClass().getMethods();
for (Method method : methods) {
try {
String name = method.getName();
if (MethodUtils.isGetter(method)) {
Parameter parameter = method.getAnnotation(Parameter.class);
if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
continue;
}
String key;
if (parameter != null && parameter.key().length() > 0) {
key = parameter.key();
} else {
key = calculatePropertyFromGetter(name);
}
Object value = method.invoke(config);
String str = String.valueOf(value).trim();
if (value != null && str.length() > 0) {
if (parameter != null && parameter.escaped()) {
str = URL.encode(str);
}
if (parameter != null && parameter.append()) {
String pre = parameters.get(key);
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
}
}
if (prefix != null && prefix.length() > 0) {
key = prefix + "." + key;
}
parameters.put(key, str);
} else if (parameter != null && parameter.required()) {
throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
}
} else if (isParametersGetter(method)) {
Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]);
parameters.putAll(convert(map, prefix));
}
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
appendParameters0(parameters, config, prefix, true);
}
/**
@ -172,41 +128,83 @@ public abstract class AbstractConfig implements Serializable {
* @param parameters
* @param config
*/
@Deprecated
protected static void appendAttributes(Map<String, Object> parameters, Object config) {
appendAttributes(parameters, config, null);
public static void appendAttributes(Map<String, String> parameters, Object config) {
appendParameters0(parameters, config, null, false);
}
@Deprecated
protected static void appendAttributes(Map<String, Object> parameters, Object config, String prefix) {
private static void appendParameters0(Map<String, String> parameters, Object config, String prefix, boolean asParameters) {
if (config == null) {
return;
}
Method[] methods = config.getClass().getMethods();
for (Method method : methods) {
// If asParameters=false, it means as attributes, ignore @Parameter annotation except 'append' and 'attribute'
// How to select the appropriate one from multiple getter methods of the property?
// e.g. Using String getGeneric() or Boolean isGeneric()? Judge by field type ?
// Currently use @Parameter.attribute() to determine whether it is an attribute.
BeanInfo beanInfo = getBeanInfo(config.getClass());
for (MethodDescriptor methodDescriptor : beanInfo.getMethodDescriptors()) {
Method method = methodDescriptor.getMethod();
try {
Parameter parameter = method.getAnnotation(Parameter.class);
if (parameter == null || !parameter.attribute()) {
continue;
}
String name = method.getName();
if (MethodUtils.isGetter(method)) {
String key;
if (parameter.key().length() > 0) {
key = parameter.key();
} else {
key = calculateAttributeFromGetter(name);
if (method.getReturnType() == Object.class ) {
continue;
}
String key = calculatePropertyFromGetter(name);
Parameter parameter = method.getAnnotation(Parameter.class);
if (asParameters) {
if (parameter != null && parameter.excluded()) {
continue;
}
if (parameter != null && parameter.key().length() > 0) {
key = parameter.key();
}
} else { // as attributes
// filter non attribute
if (parameter != null && !parameter.attribute()) {
continue;
}
}
Object value = method.invoke(config);
if (value != null) {
String str = String.valueOf(value).trim();
if (value != null && str.length() > 0) {
if (asParameters && parameter != null && parameter.escaped()) {
str = URL.encode(str);
}
if (parameter != null && parameter.append()) {
String pre = parameters.get(key);
if (pre != null && pre.length() > 0) {
str = pre + "," + str;
//Remove duplicate values
Set<String> set = StringUtils.splitToSet(str, ',');
str = StringUtils.join(set, ",");
}
}
if (prefix != null && prefix.length() > 0) {
key = prefix + "." + key;
}
parameters.put(key, value);
parameters.put(key, str);
} else if (asParameters && parameter != null && parameter.required()) {
throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
}
} else if (isParametersGetter(method)) {
Map<String, String> map = (Map<String, String>) method.invoke(config);
map = convert(map, prefix);
if (asParameters) {
// put all parameters to url
parameters.putAll(map);
} else {
// encode parameters to string for config overriding, see AbstractConfig#refresh()
String key = calculatePropertyFromGetter(name);
String encodeParameters = StringUtils.encodeParameters(map);
if (encodeParameters != null) {
parameters.put(key, encodeParameters);
}
}
}
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
throw new IllegalStateException("Append parameters failed: " + e.getMessage(), e);
}
}
}
@ -264,20 +262,9 @@ public abstract class AbstractConfig implements Serializable {
}).collect(Collectors.toSet());
}
private static String extractPropertyName(Class<?> clazz, Method setter) throws Exception {
String propertyName = setter.getName().substring("set".length());
Method getter = null;
try {
getter = clazz.getMethod("get" + propertyName);
} catch (NoSuchMethodException e) {
getter = clazz.getMethod("is" + propertyName);
}
Parameter parameter = getter.getAnnotation(Parameter.class);
if (parameter != null && StringUtils.isNotEmpty(parameter.key()) && parameter.useKeyAsProperty()) {
propertyName = parameter.key();
} else {
propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
}
private static String extractPropertyName(String setter) throws Exception {
String propertyName = setter.substring("set".length());
propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
return propertyName;
}
@ -348,14 +335,14 @@ public abstract class AbstractConfig implements Serializable {
String value = entry.getValue();
result.put(pre + key, value);
// For compatibility, key like "registry-type" will has a duplicate key "registry.type"
if (Arrays.binarySearch(Constants.DOT_COMPATIBLE_KEYS, key) != -1) {
if (Arrays.binarySearch(Constants.DOT_COMPATIBLE_KEYS, key) >= 0) {
result.put(pre + key.replace('-', '.'), value);
}
}
return result;
}
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = true)
public String getId() {
return id;
}
@ -415,92 +402,130 @@ public abstract class AbstractConfig implements Serializable {
}
/**
* Should be called after Config was fully initialized.
* // FIXME: this method should be completely replaced by appendParameters
*
* @return
* @see AbstractConfig#appendParameters(Map, Object, String)
* <p>
* Notice! This method should include all properties in the returning map, treat @Parameter differently compared to appendParameters.
* <b>The new instance of the AbstractConfig subclass should return empty metadata.</b>
* The purpose is is to get the attributes set by the user instead of the default value when the {@link #refresh()} method handles attribute overrides.
* </p>
*
* <p><b>The default value of the field should be set in the {@link #checkDefault()} method</b>,
* which will be called at the end of {@link #refresh()}, so that it will not affect the behavior of attribute overrides.</p>
*
* <p></p>
* Should be called after Config was fully initialized.
* <p>
* Notice! This method should include all properties in the returning map, treat @Parameter differently compared to appendParameters?
* </p>
* // FIXME: this method should be completely replaced by appendParameters?
* // -- Url parameter may use key, but props override only use property name. So replace it with appendAttributes().
*
* @see AbstractConfig#checkDefault()
* @see AbstractConfig#appendParameters(Map, Object, String)
*/
public Map<String, String> getMetaData() {
Map<String, String> metaData = new HashMap<>();
Method[] methods = this.getClass().getMethods();
for (Method method : methods) {
try {
String name = method.getName();
if (MethodUtils.isMetaMethod(method)) {
String key;
Parameter parameter = method.getAnnotation(Parameter.class);
if (parameter != null && parameter.key().length() > 0 && parameter.useKeyAsProperty()) {
key = parameter.key();
} else {
key = calculateAttributeFromGetter(name);
}
// treat url and configuration differently, the value should always present in configuration though it may not need to present in url.
//if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
if (method.getReturnType() == Object.class) {
metaData.put(key, null);
continue;
}
/**
* Attributes annotated as deprecated should not override newly added replacement.
*/
if (MethodUtils.isDeprecated(method) && metaData.get(key) != null) {
continue;
}
Object value = method.invoke(this);
String str = String.valueOf(value).trim();
if (value != null && str.length() > 0) {
metaData.put(key, str);
} else {
metaData.put(key, null);
}
} else if (isParametersGetter(method)) {
Map<String, String> map = (Map<String, String>) method.invoke(this, new Object[0]);
metaData.putAll(convert(map, ""));
}
} catch (Exception e) {
throw new IllegalStateException(e.getMessage(), e);
}
}
appendAttributes(metaData, this);
return metaData;
}
@Parameter(excluded = true)
public String getPrefix() {
return StringUtils.isNotEmpty(prefix) ? prefix : (CommonConstants.DUBBO + "." + getTagName(this.getClass()));
protected static BeanInfo getBeanInfo(Class cls) {
BeanInfo beanInfo = null;
try {
beanInfo = Introspector.getBeanInfo(cls);
} catch (IntrospectionException e) {
throw new IllegalStateException(e.getMessage(), e);
}
return beanInfo;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
private static boolean isWritableProperty(BeanInfo beanInfo, String key) {
for (PropertyDescriptor propertyDescriptor : beanInfo.getPropertyDescriptors()) {
if (key.equals(propertyDescriptor.getName())) {
return propertyDescriptor.getWriteMethod() != null;
}
}
return false;
}
@Parameter(excluded = true, attribute = false)
public List<String> getPrefixes() {
List<String> prefixes = new ArrayList<>();
if (StringUtils.hasText(this.getId())) {
// dubbo.{tag-name}s.id
prefixes.add(CommonConstants.DUBBO + "." + getPluralTagName(this.getClass()) + "." + this.getId());
}
// check name
String name = ReflectUtils.getProperty(this, "getName");
if (StringUtils.hasText(name)) {
String prefix = CommonConstants.DUBBO + "." + getPluralTagName(this.getClass()) + "." + name;
if (!prefixes.contains(prefix)) {
prefixes.add(prefix);
}
}
// dubbo.{tag-name}
prefixes.add(getTypePrefix(this.getClass()));
return prefixes;
}
public static String getTypePrefix(Class<? extends AbstractConfig> cls) {
return CommonConstants.DUBBO + "." + getTagName(cls);
}
/**
* Dubbo config property override
*/
public void refresh() {
refreshed.set(true);
Environment env = ApplicationModel.getEnvironment();
try {
CompositeConfiguration compositeConfiguration = env.getPrefixedConfiguration(this);
// check and init before do refresh
preProcessRefresh();
Environment environment = ApplicationModel.getEnvironment();
List<Map<String, String>> configurationMaps = environment.getConfigurationMaps();
// Search props starts with PREFIX in order
String preferredPrefix = null;
for (String prefix : getPrefixes()) {
if (ConfigurationUtils.hasSubProperties(configurationMaps, prefix)) {
preferredPrefix = prefix;
break;
}
}
if (preferredPrefix == null) {
preferredPrefix = getPrefixes().get(0);
}
// Extract sub props (which key was starts with preferredPrefix)
Collection<Map<String, String>> instanceConfigMaps = environment.getConfigurationMaps(this, preferredPrefix);
Map<String, String> subProperties = ConfigurationUtils.getSubProperties(instanceConfigMaps, preferredPrefix);
InmemoryConfiguration subPropsConfiguration = new InmemoryConfiguration(subProperties);
// loop methods, get override value and set the new value back to method
Method[] methods = getClass().getMethods();
for (Method method : methods) {
if (MethodUtils.isSetter(method)) {
String propertyName = extractPropertyName(method.getName());
// convert camelCase/snake_case to kebab-case
String kebabPropertyName = StringUtils.convertToSplitName(propertyName, "-");
try {
String value = StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method)));
String value = StringUtils.trim(subPropsConfiguration.getString(kebabPropertyName));
// isTypeMatch() is called to avoid duplicate and incorrect update, for example, we have two 'setGeneric' methods in ReferenceConfig.
if (StringUtils.isNotEmpty(value) && ClassUtils.isTypeMatch(method.getParameterTypes()[0], value)) {
if (StringUtils.hasText(value) && ClassUtils.isTypeMatch(method.getParameterTypes()[0], value) &&
!isIgnoredAttribute(getClass(), propertyName)) {
value = environment.resolvePlaceholders(value);
method.invoke(this, ClassUtils.convertPrimitive(method.getParameterTypes()[0], value));
}
} catch (NoSuchMethodException e) {
} catch (Exception e) {
logger.info("Failed to override the property " + method.getName() + " in " +
this.getClass().getSimpleName() +
", please make sure every property has getter/setter method provided.");
}
} else if (isParametersSetter(method)) {
String value = StringUtils.trim(compositeConfiguration.getString(extractPropertyName(getClass(), method)));
if (StringUtils.isNotEmpty(value)) {
String propertyName = extractPropertyName(method.getName());
String value = StringUtils.trim(subPropsConfiguration.getString(propertyName));
if (StringUtils.hasText(value)) {
Map<String, String> map = invokeGetParameters(getClass(), this);
map = map == null ? new HashMap<>() : map;
map.putAll(convert(StringUtils.parseParameters(value), ""));
@ -508,12 +533,75 @@ public abstract class AbstractConfig implements Serializable {
}
}
}
// process extra refresh of sub class, e.g. refresh method configs
processExtraRefresh(preferredPrefix, subPropsConfiguration);
} catch (Exception e) {
logger.error("Failed to override ", e);
logger.error("Failed to override field value of config bean: "+this, e);
throw new IllegalStateException("Failed to override field value of config bean: "+this, e);
}
postProcessRefresh();
}
@Parameter(excluded = true)
private boolean isIgnoredAttribute(Class<? extends AbstractConfig> clazz, String propertyName) {
Method getter = null;
String capitalizePropertyName = propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
try {
getter = clazz.getMethod("get" + capitalizePropertyName);
} catch (NoSuchMethodException e) {
try {
getter = clazz.getMethod("is" + capitalizePropertyName);
} catch (NoSuchMethodException ex) {
}
}
if (getter == null) {
// no getter method
return true;
}
Parameter parameter = getter.getAnnotation(Parameter.class);
if (parameter != null && !parameter.attribute()) {
// not an attribute
return true;
}
return false;
}
protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
// process extra refresh
}
protected void preProcessRefresh() {
// pre-process refresh
}
protected void postProcessRefresh() {
// post-process refresh
checkDefault();
}
/**
* Check and set default value for some fields.
* <p>
* This method will be called at the end of {@link #refresh()}, as a post-initializer.
* </p>
* <p>NOTE: </p>
* <p>
* To distinguish between user-set property values and default property values,
* do not initialize default value at field declare statement. <b>If the field has a default value,
* it should be set in the checkDefault() method</b>, which will be called at the end of {@link #refresh()},
* so that it will not affect the behavior of attribute overrides.</p>
*
* @see AbstractConfig#getMetaData()
* @see AbstractConfig#appendAttributes(Map, Object)
*/
protected void checkDefault() {
}
@Parameter(excluded = true, attribute = false)
public boolean isRefreshed() {
return refreshed.get();
}
@ -521,6 +609,9 @@ public abstract class AbstractConfig implements Serializable {
@Override
public String toString() {
try {
Set<String> fieldNames = getFieldNames(this.getClass());
StringBuilder buf = new StringBuilder();
buf.append("<dubbo:");
buf.append(getTagName(getClass()));
@ -531,10 +622,14 @@ public abstract class AbstractConfig implements Serializable {
String name = method.getName();
String key = calculateAttributeFromGetter(name);
try {
getClass().getDeclaredField(key);
} catch (NoSuchFieldException e) {
// ignore
// Fixes #4992, endless recursive call when NetUtils method fails.
if (!fieldNames.contains(key)) {
continue;
}
// filter non attribute
Parameter parameter = method.getAnnotation(Parameter.class);
if (parameter != null && !parameter.attribute()) {
continue;
}
@ -559,10 +654,14 @@ public abstract class AbstractConfig implements Serializable {
}
}
private static Set<String> getFieldNames(Class<?> configClass) {
return fieldNamesCache.computeIfAbsent(configClass, ReflectUtils::getAllFieldNames);
}
/**
* FIXME check @Parameter(required=true) and any conditions that need to match.
*/
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
return true;
}
@ -570,26 +669,39 @@ public abstract class AbstractConfig implements Serializable {
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj.getClass().getName().equals(this.getClass().getName()))) {
if (obj == null || obj.getClass() != this.getClass()) {
return false;
}
if (obj == this) {
return true;
}
Method[] methods = this.getClass().getMethods();
for (Method method1 : methods) {
if (MethodUtils.isGetter(method1)) {
Parameter parameter = method1.getAnnotation(Parameter.class);
if (parameter != null && parameter.excluded()) {
BeanInfo beanInfo = getBeanInfo(this.getClass());
for (MethodDescriptor methodDescriptor : beanInfo.getMethodDescriptors()) {
Method method = methodDescriptor.getMethod();
if (MethodUtils.isGetter(method)) {
// filter non attribute
Parameter parameter = method.getAnnotation(Parameter.class);
if (parameter != null && !parameter.attribute()) {
continue;
}
String propertyName = calculateAttributeFromGetter(method.getName());
// ignore compare 'id' value
if (Constants.ID.equals(propertyName)) {
continue;
}
// filter non writable property
if (!isWritableProperty(beanInfo, propertyName)) {
continue;
}
try {
Method method2 = obj.getClass().getMethod(method1.getName(), method1.getParameterTypes());
Object value1 = method1.invoke(this, new Object[]{});
Object value2 = method2.invoke(obj, new Object[]{});
Object value1 = method.invoke(this);
Object value2 = method.invoke(obj);
if (!Objects.equals(value1, value2)) {
return false;
}
} catch (Exception e) {
return true;
throw new IllegalStateException("compare config instances failed", e);
}
}
}
@ -621,7 +733,7 @@ public abstract class AbstractConfig implements Serializable {
continue;
}
try {
Object value = method.invoke(this, new Object[]{});
Object value = method.invoke(this);
hashCode = 31 * hashCode + value.hashCode();
} catch (Exception ignored) {
//ignored

View File

@ -18,7 +18,7 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.utils.Assert;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.ReflectUtils;
@ -193,7 +193,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
/**
* Check whether the registry config is exists, and then conversion it to {@link RegistryConfig}
*/
public void checkRegistry() {
protected void checkRegistry() {
convertRegistryIdsToRegistries();
for (RegistryConfig registryConfig : registries) {
@ -213,57 +213,29 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
}
/**
* Check whether the remote service interface and the methods meet with Dubbo's requirements.it mainly check, if the
* methods configured in the configuration file are included in the interface of remote service
*
* @param interfaceClass the interface of remote service
* @param methods the methods configured
*/
public void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
// interface cannot be null
Assert.notNull(interfaceClass, new IllegalStateException("interface not allow null!"));
// to verify interfaceClass is an interface
if (!interfaceClass.isInterface()) {
throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
}
// check if methods exist in the remote service interface
if (CollectionUtils.isNotEmpty(methods)) {
for (MethodConfig methodBean : methods) {
methodBean.setService(interfaceClass.getName());
methodBean.setServiceId(this.getId());
methodBean.refresh();
String methodName = methodBean.getName();
if (StringUtils.isEmpty(methodName)) {
throw new IllegalStateException("<dubbo:method> name attribute is required! Please check: " +
"<dubbo:service interface=\"" + interfaceClass.getName() + "\" ... >" +
"<dubbo:method name=\"\" ... /></<dubbo:reference>");
}
boolean hasMethod = Arrays.stream(interfaceClass.getMethods()).anyMatch(method -> method.getName().equals(methodName));
if (!hasMethod) {
throw new IllegalStateException("The interface " + interfaceClass.getName()
+ " not found method " + methodName);
}
@Override
protected void processExtraRefresh(String preferredPrefix, InmemoryConfiguration subPropsConfiguration) {
List<MethodConfig> methodConfigs = this.getMethods();
if (methodConfigs != null && methodConfigs.size() > 0) {
for (MethodConfig methodConfig : methodConfigs) {
methodConfig.setParentPrefix(preferredPrefix);
methodConfig.refresh();
}
}
}
/**
* Legitimacy check of stub, note that: the local will deprecated, and replace with <code>stub</code>
*
* @param interfaceClass for provider side, it is the {@link Class} of the service that will be exported; for consumer
* side, it is the {@link Class} of the remote service interface
*/
public void checkStubAndLocal(Class<?> interfaceClass) {
protected void checkStubAndLocal(Class<?> interfaceClass) {
verifyStubAndLocal(local, "Local", interfaceClass);
verifyStubAndLocal(stub, "Stub", interfaceClass);
}
public void verifyStubAndLocal(String className, String label, Class<?> interfaceClass){
private void verifyStubAndLocal(String className, String label, Class<?> interfaceClass){
if (ConfigUtils.isNotEmpty(className)) {
Class<?> localClass = ConfigUtils.isDefault(className) ?
ReflectUtils.forName(interfaceClass.getName() + label) : ReflectUtils.forName(className);
@ -292,10 +264,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (CollectionUtils.isEmpty(registries)) {
List<RegistryConfig> registryConfigs = ApplicationModel.getConfigManager().getDefaultRegistries();
if (registryConfigs.isEmpty()) {
registryConfigs = new ArrayList<>();
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.refresh();
registryConfigs.add(registryConfig);
throw new IllegalStateException("Default registry is not initialized");
} else {
registryConfigs = new ArrayList<>(registryConfigs);
}
@ -310,19 +279,10 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
if (globalRegistry.isPresent()) {
tmpRegistries.add(globalRegistry.get());
} else {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(id);
registryConfig.refresh();
tmpRegistries.add(registryConfig);
throw new IllegalStateException("Registry not found: " + id);
}
}
});
if (tmpRegistries.size() > ids.length) {
throw new IllegalStateException("Too much registries found, the registries assigned to this service " +
"are :" + registryIds + ", but got " + tmpRegistries.size() + " registries!");
}
setRegistries(tmpRegistries);
}
@ -332,7 +292,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
return CollectionUtils.isEmpty(registries) && StringUtils.isEmpty(registryIds);
}
public void completeCompoundConfigs(AbstractInterfaceConfig interfaceConfig) {
protected void completeCompoundConfigs(AbstractInterfaceConfig interfaceConfig) {
if (interfaceConfig != null) {
if (application == null) {
setApplication(interfaceConfig.getApplication());
@ -486,14 +446,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setApplication(ApplicationConfig application) {
this.application = application;
if (application != null) {
ConfigManager configManager = ApplicationModel.getConfigManager();
// FIXME, revert this change after spring bean initialization process fixed.
if (!configManager.getApplication().isPresent()
|| !configManager.getApplication().get().getName().equalsIgnoreCase(application.getName())) {
configManager.setApplication(application);
} else {
application.refresh();
}
ApplicationModel.getConfigManager().setApplication(application);
}
}
@ -508,11 +461,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setModule(ModuleConfig module) {
this.module = module;
if (module != null) {
ConfigManager configManager = ApplicationModel.getConfigManager();
configManager.getModule().orElseGet(() -> {
configManager.setModule(module);
return module;
});
ApplicationModel.getConfigManager().setModule(module);
}
}
@ -574,11 +523,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setMonitor(MonitorConfig monitor) {
this.monitor = monitor;
if (monitor != null) {
ConfigManager configManager = ApplicationModel.getConfigManager();
configManager.getMonitor().orElseGet(() -> {
configManager.setMonitor(monitor);
return monitor;
});
ApplicationModel.getConfigManager().setMonitor(monitor);
}
}
@ -684,15 +629,11 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setMetrics(MetricsConfig metrics) {
this.metrics = metrics;
if (metrics != null) {
ConfigManager configManager = ApplicationModel.getConfigManager();
configManager.getMetrics().orElseGet(() -> {
configManager.setMetrics(metrics);
return metrics;
});
ApplicationModel.getConfigManager().setMetrics(metrics);
}
}
@Parameter(key = TAG_KEY, useKeyAsProperty = false)
@Parameter(key = TAG_KEY)
public String getTag() {
return tag;
}
@ -713,7 +654,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
return ApplicationModel.getConfigManager().getSsl().orElse(null);
}
public void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
protected void initServiceMetadata(AbstractInterfaceConfig interfaceConfig) {
serviceMetadata.setVersion(getVersion(interfaceConfig));
serviceMetadata.setGroup(getGroup(interfaceConfig));
serviceMetadata.setDefaultGroup(getGroup(interfaceConfig));
@ -750,8 +691,5 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
public void setInterface(String interfaceName) {
this.interfaceName = interfaceName;
// if (StringUtils.isEmpty(id)) {
// id = interfaceName;
// }
}
}

View File

@ -63,7 +63,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
protected String reconnect;
protected Boolean sticky = false;
protected Boolean sticky;
/**
* Whether to support event in stub.
@ -80,6 +80,14 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
protected String router;
@Override
protected void checkDefault() {
super.checkDefault();
if (sticky == null) {
sticky = false;
}
}
public Boolean isCheck() {
return check;
}
@ -97,7 +105,7 @@ public abstract class AbstractReferenceConfig extends AbstractInterfaceConfig {
}
@Deprecated
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public Boolean isGeneric() {
return this.generic != null ? ProtocolUtils.isGeneric(generic) : null;
}

View File

@ -48,7 +48,7 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
/**
* whether the service is deprecated
*/
protected Boolean deprecated = false;
protected Boolean deprecated; // false;
/**
* The time delay register service (milliseconds)
@ -75,7 +75,7 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
* after the service registered,and it needs to be disabled manually; if you want to disable the service, you also need
* manual processing
*/
protected Boolean dynamic = true;
protected Boolean dynamic; // true;
/**
* Whether to use token
@ -117,6 +117,17 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
*/
private String serialization;
@Override
protected void checkDefault() {
super.checkDefault();
if (deprecated == null) {
deprecated = false;
}
if (dynamic == null) {
dynamic = true;
}
}
public String getVersion() {
return version;
}

View File

@ -191,16 +191,30 @@ public class ApplicationConfig extends AbstractConfig {
setName(name);
}
@Parameter(key = APPLICATION_KEY, required = true, useKeyAsProperty = false)
@Override
protected void checkDefault() {
super.checkDefault();
if (protocol == null) {
protocol = DUBBO;
}
if (hostname == null) {
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
LOGGER.warn("Failed to get the hostname of current instance.", e);
hostname = "UNKNOWN";
}
}
}
@Parameter(key = APPLICATION_KEY, required = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
if (StringUtils.isEmpty(id)) {
id = name;
}
//this.updateIdIfAbsent(name);
}
@Parameter(key = "application.version")
@ -420,19 +434,11 @@ public class ApplicationConfig extends AbstractConfig {
@Parameter(excluded = true)
public String getHostname() {
if (hostname == null) {
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException e) {
LOGGER.warn("Failed to get the hostname of current instance.", e);
hostname = "UNKNOWN";
}
}
return hostname;
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
return !StringUtils.isEmpty(name);
}
@ -491,7 +497,7 @@ public class ApplicationConfig extends AbstractConfig {
@Parameter(excluded = true, key="application-protocol")
public String getProtocol() {
return protocol == null ? DUBBO : protocol;
return protocol;
}
public void setProtocol(String protocol) {
@ -554,11 +560,14 @@ public class ApplicationConfig extends AbstractConfig {
Map<String, String> extraParameters = adapter.getExtraAttributes(inputParameters);
if (CollectionUtils.isNotEmptyMap(extraParameters)) {
extraParameters.forEach((key, value) -> {
String prefix = this.getPrefix() + ".";
if (key.startsWith(prefix)) {
key = key.substring(prefix.length());
for (String prefix : this.getPrefixes()) {
prefix += ".";
if (key.startsWith(prefix)) {
key = key.substring(prefix.length());
}
parameters.put(key, value);
break;
}
parameters.put(key, value);
});
}
}

View File

@ -52,25 +52,28 @@ public class ConfigCenterConfig extends AbstractConfig {
but it's real meaning depends on the actual Config Center you use.
*/
private String namespace = CommonConstants.DUBBO;
private String namespace; // CommonConstants.DUBBO;
/* The group of the config center, generally it's used to identify an isolated space for a batch of config items,
but it's real meaning depends on the actual Config Center you use.
*/
private String group = CommonConstants.DUBBO;
private String group; // CommonConstants.DUBBO;
private String username;
private String password;
private Long timeout = 3000L;
private Long timeout; // 3000L;
// If the Config Center is given the highest priority, it will override all the other configurations
private Boolean highestPriority = true;
/**
* If the Config Center is given the highest priority, it will override all the other configurations
* @deprecated no longer used
*/
private Boolean highestPriority; // true;
// Decide the behaviour when initial connection try fails, 'true' means interrupt the whole process once fail.
private Boolean check = true;
private Boolean check; // true;
/* Used to specify the key that your properties file mapping to, most of the time you do not need to change this parameter.
Notice that for Apollo, this parameter is meaningless, set the 'namespace' is enough.
*/
private String configFile = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
private String configFile; // CommonConstants.DEFAULT_DUBBO_PROPERTIES;
/* the .properties file under 'configFile' is global shared while .properties under this one is limited only to this application
*/
@ -91,6 +94,30 @@ public class ConfigCenterConfig extends AbstractConfig {
public ConfigCenterConfig() {
}
@Override
protected void checkDefault() {
super.checkDefault();
if (namespace == null) {
namespace = CommonConstants.DUBBO;
}
if (group == null) {
group = CommonConstants.DUBBO;
}
if (timeout == null) {
timeout = 3000L;
}
// if (highestPriority == null) {
// highestPriority = true;
// }
if (check == null) {
check = true;
}
if (configFile == null) {
configFile = CommonConstants.DEFAULT_DUBBO_PROPERTIES;
}
}
public URL toUrl() {
Map<String, String> map = new HashMap<>();
appendParameters(map, this);
@ -145,7 +172,6 @@ public class ConfigCenterConfig extends AbstractConfig {
URL url = URL.valueOf(address);
setUsername(url.getUsername());
setPassword(url.getPassword());
updateIdIfAbsent(url.getProtocol());
updateProtocolIfAbsent(url.getProtocol());
updatePortIfAbsent(url.getPort());
updateParameters(url.getParameters());
@ -194,11 +220,13 @@ public class ConfigCenterConfig extends AbstractConfig {
this.check = check;
}
@Deprecated
@Parameter(key = CONFIG_ENABLE_KEY)
public Boolean isHighestPriority() {
return highestPriority;
}
@Deprecated
public void setHighestPriority(Boolean highestPriority) {
this.highestPriority = highestPriority;
}
@ -254,7 +282,7 @@ public class ConfigCenterConfig extends AbstractConfig {
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
if (StringUtils.isEmpty(address)) {
return false;

View File

@ -30,9 +30,13 @@ public interface Constants {
String LAYER_KEY = "layer";
// General
/**
* General
* Config id
*/
String ID = "id";
/**
* Application name;
*/

View File

@ -24,8 +24,6 @@ import org.apache.dubbo.config.support.Parameter;
import java.util.HashMap;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
import static org.apache.dubbo.common.constants.CommonConstants.PROPERTIES_CHAR_SEPARATOR;
import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
/**
@ -36,11 +34,6 @@ import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
public class MetadataReportConfig extends AbstractConfig {
private static final long serialVersionUID = 55233L;
/**
* the value is : metadata-report
*/
private static final String PREFIX_TAG = StringUtils.camelToSplitName(
MetadataReportConfig.class.getSimpleName().substring(0, MetadataReportConfig.class.getSimpleName().length() - 6), PROPERTIES_CHAR_SEPARATOR);
// Register center address
private String address;
@ -197,13 +190,7 @@ public class MetadataReportConfig extends AbstractConfig {
}
@Override
@Parameter(excluded = true)
public String getPrefix() {
return StringUtils.isNotEmpty(prefix) ? prefix : (DUBBO + "." + PREFIX_TAG);
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
return StringUtils.isNotEmpty(address);
}

View File

@ -16,8 +16,6 @@
*/
package org.apache.dubbo.config;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.support.Parameter;
@ -117,15 +115,17 @@ public class MethodConfig extends AbstractMethodConfig {
private List<ArgumentConfig> arguments;
/**
* TODO remove service and serviceId
* These properties come from MethodConfig's parent Config module, they will neither be collected directly from xml or API nor be delivered to url
*/
private String service;
private String serviceId;
@Parameter(excluded = true)
public String getName() {
return name;
}
/**
* The preferred prefix of parent
*/
private String parentPrefix;
public MethodConfig() {
}
@ -191,6 +191,34 @@ public class MethodConfig extends AbstractMethodConfig {
return Collections.emptyList();
}
/**
* Get method prefixes
* @return
*/
@Override
@Parameter(excluded = true)
public List<String> getPrefixes() {
// parent prefix + method name
if (parentPrefix != null) {
List<String> prefixes = new ArrayList<>();
prefixes.add(parentPrefix + "." +this.getName());
return prefixes;
} else {
throw new IllegalStateException("The parent prefix of MethodConfig is null");
}
}
@Override
public void addIntoConfigManager() {
// Don't add MethodConfig to ConfigManager
// super.addIntoConfigManager();
}
@Parameter(excluded = true)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
// FIXME, add id strategy in ConfigManager
@ -323,7 +351,7 @@ public class MethodConfig extends AbstractMethodConfig {
this.isReturn = isReturn;
}
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public String getService() {
return service;
}
@ -332,7 +360,7 @@ public class MethodConfig extends AbstractMethodConfig {
this.service = service;
}
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public String getServiceId() {
return serviceId;
}
@ -341,16 +369,12 @@ public class MethodConfig extends AbstractMethodConfig {
this.serviceId = serviceId;
}
/**
* service and name must not be null.
*
* @return
*/
@Override
@Parameter(excluded = true)
public String getPrefix() {
return CommonConstants.DUBBO + "." + service
+ (StringUtils.isEmpty(serviceId) ? "" : ("." + serviceId))
+ "." + getName();
public void setParentPrefix(String parentPrefix) {
this.parentPrefix = parentPrefix;
}
@Parameter(excluded = true, attribute = false)
public String getParentPrefix() {
return parentPrefix;
}
}

View File

@ -17,7 +17,6 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.support.Parameter;
import java.util.ArrayList;
@ -76,9 +75,7 @@ public class ModuleConfig extends AbstractConfig {
public void setName(String name) {
this.name = name;
if (StringUtils.isEmpty(id)) {
id = name;
}
//this.updateIdIfAbsent(name);
}
@Parameter(key = "module.version")

View File

@ -139,7 +139,7 @@ public class MonitorConfig extends AbstractConfig {
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
return StringUtils.isNotEmpty(address) || RegistryConstants.REGISTRY_PROTOCOL.equals(protocol);
}

View File

@ -21,9 +21,8 @@ import org.apache.dubbo.config.support.Parameter;
import java.util.Map;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
import static org.apache.dubbo.common.constants.CommonConstants.SSL_ENABLED_KEY;
import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
/**
* ProtocolConfig
@ -212,6 +211,29 @@ public class ProtocolConfig extends AbstractConfig {
setPort(port);
}
@Override
protected void checkDefault() {
super.checkDefault();
if (name == null) {
name = DUBBO_PROTOCOL;
}
}
// @Override
// public List<String> getPrefixes() {
// List<String> prefixes = new ArrayList<>();
// if (StringUtils.hasText(this.getId())) {
// // dubbo.protocols.{protocol-id}
// prefixes.add(CommonConstants.DUBBO + "." + getPluralTagName(this.getClass()) + "." + this.getId());
// } else if (StringUtils.hasText(this.getName()) && !StringUtils.isEquals(this.getId(), this.getName())) {
// // dubbo.protocols.{protocol-name}
// prefixes.add(CommonConstants.DUBBO + "." + getPluralTagName(this.getClass()) + "." + this.getName());
// }
// // dubbo.protocol
// prefixes.add(getTypePrefix());
// return prefixes;
// }
@Parameter(excluded = true)
public String getName() {
return name;
@ -219,7 +241,7 @@ public class ProtocolConfig extends AbstractConfig {
public final void setName(String name) {
this.name = name;
this.updateIdIfAbsent(name);
//this.updateIdIfAbsent(name);
}
@Parameter(excluded = true)
@ -524,19 +546,7 @@ public class ProtocolConfig extends AbstractConfig {
}
@Override
public void refresh() {
if (StringUtils.isEmpty(this.getName())) {
this.setName(DUBBO_VERSION_KEY);
}
super.refresh();
if (StringUtils.isNotEmpty(this.getId())) {
this.setPrefix(PROTOCOLS_SUFFIX);
super.refresh();
}
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
return StringUtils.isNotEmpty(name);
}

View File

@ -29,6 +29,10 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
@ -81,6 +85,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
}
public boolean shouldCheck() {
checkDefault();
Boolean shouldCheck = isCheck();
if (shouldCheck == null && getConsumer() != null) {
shouldCheck = getConsumer().isCheck();
@ -93,6 +98,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
}
public boolean shouldInit() {
checkDefault();
Boolean shouldInit = isInit();
if (shouldInit == null && getConsumer() != null) {
shouldInit = getConsumer().isInit();
@ -104,14 +110,39 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
return shouldInit;
}
public void checkDefault() throws IllegalStateException {
@Override
protected void preProcessRefresh() {
super.preProcessRefresh();
if (consumer == null) {
consumer = ApplicationModel.getConfigManager()
.getDefaultConsumer()
.orElse(new ConsumerConfig());
.orElseThrow(() -> new IllegalArgumentException("Default consumer is not initialized"));
}
}
@Override
@Parameter(excluded = true, attribute = false)
public List<String> getPrefixes() {
List<String> prefixes = new ArrayList<>();
// dubbo.reference.{interface-name}
prefixes.add(DUBBO + ".reference." + interfaceName);
return prefixes;
}
@Override
public Map<String, String> getMetaData() {
Map<String, String> metaData = new HashMap<>();
ConsumerConfig consumer = this.getConsumer();
// consumer should be inited at preProcessRefresh()
if (isRefreshed() && consumer == null) {
throw new IllegalStateException("Consumer is not initialized");
}
// use consumer attributes as default value
appendAttributes(metaData, consumer);
appendAttributes(metaData, this);
return metaData;
}
/**
* Get actual interface class of this reference.
* The actual service type of remote provider.
@ -220,13 +251,7 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
return serviceMetadata;
}
@Override
@Parameter(excluded = true)
public String getPrefix() {
return DUBBO + ".reference." + interfaceName;
}
public void resolveFile() {
protected void resolveFile() {
String resolve = System.getProperty(interfaceName);
String resolveFile = null;
if (StringUtils.isEmpty(resolve)) {
@ -268,13 +293,12 @@ public abstract class ReferenceConfigBase<T> extends AbstractReferenceConfig {
setRegistryIds(consumer.getRegistryIds());
}
}
super.computeValidRegistryIds();
}
@Parameter(excluded = true)
public String getUniqueServiceName() {
return URL.buildKey(interfaceName, getGroup(), getVersion());
return interfaceName != null ? URL.buildKey(interfaceName, getGroup(), getVersion()) : null;
}
@Override

View File

@ -30,7 +30,6 @@ import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PUBLI
import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PUBLISH_INTERFACE_KEY;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
import static org.apache.dubbo.common.utils.PojoUtils.updatePropertyIfAbsent;
import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
/**
* RegistryConfig
@ -208,6 +207,7 @@ public class RegistryConfig extends AbstractConfig {
public void setProtocol(String protocol) {
this.protocol = protocol;
// protocol as id is inappropriate, registries's protocol may be duplicated
// this.updateIdIfAbsent(protocol);
}
@ -228,11 +228,6 @@ public class RegistryConfig extends AbstractConfig {
updatePropertyIfAbsent(this::getProtocol, this::setProtocol, url.getProtocol());
updatePropertyIfAbsent(this::getPort, this::setPort, url.getPort());
// setUsername(url.getUsername());
// setPassword(url.getPassword());
// updateIdIfAbsent(url.getProtocol());
// updateProtocolIfAbsent(url.getProtocol());
// updatePortIfAbsent(url.getPort());
Map<String, String> params = url.getParameters();
if (CollectionUtils.isNotEmptyMap(params)) {
params.remove(BACKUP_KEY);
@ -529,16 +524,7 @@ public class RegistryConfig extends AbstractConfig {
}
@Override
public void refresh() {
super.refresh();
if (StringUtils.isNotEmpty(this.getId())) {
this.setPrefix(REGISTRIES_SUFFIX);
super.refresh();
}
}
@Override
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isValid() {
// empty protocol will default to 'dubbo'
return !StringUtils.isEmpty(address);

View File

@ -28,8 +28,12 @@ import org.apache.dubbo.rpc.support.ProtocolUtils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
@ -166,7 +170,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return (delay == null && provider != null) ? provider.getDelay() : delay;
}
public void checkRef() {
protected void checkRef() {
// reference should not be null, and is the implementation of the given interface
if (ref == null) {
throw new IllegalStateException("ref not allow null!");
@ -190,23 +194,37 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return ref.getClass();
}
public void checkDefault() throws IllegalStateException {
@Override
protected void preProcessRefresh() {
super.preProcessRefresh();
convertProviderIdToProvider();
if (provider == null) {
provider = ApplicationModel.getConfigManager()
.getDefaultProvider()
.orElse(new ProviderConfig());
.orElseThrow(() -> new IllegalArgumentException("Default provider is not initialized"));
}
}
public void checkProtocol() {
@Override
public Map<String, String> getMetaData() {
Map<String, String> metaData = new HashMap<>();
ProviderConfig provider = this.getProvider();
// provider should be inited at preProcessRefresh()
if (isRefreshed() && provider == null) {
throw new IllegalStateException("Provider is not initialized");
}
// use provider attributes as default value
appendAttributes(metaData, provider);
// Finally, put the service's attributes, overriding previous attributes
appendAttributes(metaData, this);
return metaData;
}
protected void checkProtocol() {
if (provider != null && notHasSelfProtocolProperty()) {
setProtocols(provider.getProtocols());
setProtocolIds(provider.getProtocolIds());
}
if (CollectionUtils.isEmpty(protocols) && provider != null) {
setProtocols(provider.getProtocols());
}
convertProtocolIdsToProtocols();
}
@ -214,7 +232,7 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return CollectionUtils.isEmpty(protocols) && StringUtils.isEmpty(protocolIds);
}
public void completeCompoundConfigs() {
protected void completeCompoundConfigs() {
super.completeCompoundConfigs(provider);
if (provider != null) {
if (notHasSelfProtocolProperty()) {
@ -227,39 +245,33 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
}
}
private void convertProtocolIdsToProtocols() {
protected void convertProviderIdToProvider() {
if (provider == null && StringUtils.hasText(providerIds)) {
provider = ApplicationModel.getConfigManager().getProvider(providerIds)
.orElseThrow(() -> new IllegalStateException("Provider config not found: " + providerIds));
}
}
protected void convertProtocolIdsToProtocols() {
if (StringUtils.isEmpty(protocolIds)) {
if (CollectionUtils.isEmpty(protocols)) {
List<ProtocolConfig> protocolConfigs = ApplicationModel.getConfigManager().getDefaultProtocols();
if (protocolConfigs.isEmpty()) {
protocolConfigs = new ArrayList<>(1);
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setDefault(true);
protocolConfig.refresh();
protocolConfigs.add(protocolConfig);
ApplicationModel.getConfigManager().addProtocol(protocolConfig);
throw new IllegalStateException("The default protocol has not been initialized.");
}
setProtocols(protocolConfigs);
}
} else {
String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds);
String[] idsArray = COMMA_SPLIT_PATTERN.split(protocolIds);
Set<String> idsSet = new LinkedHashSet<>(Arrays.asList(idsArray));
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
Arrays.stream(arr).forEach(id -> {
if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
Optional<ProtocolConfig> globalProtocol = ApplicationModel.getConfigManager().getProtocol(id);
if (globalProtocol.isPresent()) {
tmpProtocols.add(globalProtocol.get());
} else {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setId(id);
protocolConfig.refresh();
tmpProtocols.add(protocolConfig);
}
for (String id : idsSet) {
Optional<ProtocolConfig> globalProtocol = ApplicationModel.getConfigManager().getProtocol(id);
if (globalProtocol.isPresent()) {
tmpProtocols.add(globalProtocol.get());
} else {
throw new IllegalStateException("Protocol not found: "+id);
}
});
if (tmpProtocols.size() > arr.length) {
throw new IllegalStateException("Too much protocols found, the protocols comply to this service are :" + protocolIds + " but got " + protocols
.size() + " registries!");
}
setProtocols(tmpProtocols);
}
@ -366,31 +378,34 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
return serviceMetadata;
}
/**
* @deprecated Replace to getProtocols()
*/
@Deprecated
public List<ProviderConfig> getProviders() {
return convertProtocolToProvider(protocols);
}
/**
* @deprecated Replace to setProtocols()
*/
@Deprecated
public void setProviders(List<ProviderConfig> providers) {
this.protocols = convertProviderToProtocol(providers);
}
// /**
// * @deprecated Replace to getProtocols()
// */
// @Deprecated
// public List<ProviderConfig> getProviders() {
// return convertProtocolToProvider(protocols);
// }
//
// /**
// * @deprecated Replace to setProtocols()
// */
// @Deprecated
// public void setProviders(List<ProviderConfig> providers) {
// this.protocols = convertProviderToProtocol(providers);
// }
@Override
@Parameter(excluded = true)
public String getPrefix() {
return DUBBO + ".service." + interfaceName;
@Parameter(excluded = true, attribute = false)
public List<String> getPrefixes() {
List<String> prefixes = new ArrayList<>();
// dubbo.service.{interface-name}
prefixes.add(DUBBO + ".service." + interfaceName);
return prefixes;
}
@Parameter(excluded = true)
public String getUniqueServiceName() {
return URL.buildKey(interfaceName, getGroup(), getVersion());
return interfaceName != null ? URL.buildKey(interfaceName, getGroup(), getVersion()) : null;
}
@Override
@ -409,7 +424,6 @@ public abstract class ServiceConfigBase<T> extends AbstractServiceConfig {
setRegistries(provider.getRegistries());
setRegistryIds(provider.getRegistryIds());
}
super.computeValidRegistryIds();
}

View File

@ -270,7 +270,9 @@ public @interface DubboReference {
/**
* Application associated name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
/**

View File

@ -236,7 +236,9 @@ public @interface DubboService {
/**
* Application spring bean name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
/**

View File

@ -234,7 +234,9 @@ public @interface Reference {
/**
* Application associated name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
/**

View File

@ -236,7 +236,9 @@ public @interface Service {
/**
* Application spring bean name
* @deprecated Do not set it and use the global Application Config
*/
@Deprecated
String application() default "";
/**

View File

@ -30,13 +30,15 @@ public class ConfigConfigurationAdapter implements Configuration {
private Map<String, String> metaData;
public ConfigConfigurationAdapter(AbstractConfig config) {
Map<String, String> configMetadata = config.getMetaData();
metaData = new HashMap<>(configMetadata.size(), 1.0f);
for (Map.Entry<String, String> entry : configMetadata.entrySet()) {
String prefix = config.getPrefix().endsWith(".") ? config.getPrefix() : config.getPrefix() + ".";
String id = StringUtils.isEmpty(config.getId()) ? "" : config.getId() + ".";
metaData.put(prefix + id + entry.getKey(), entry.getValue());
public ConfigConfigurationAdapter(AbstractConfig config, String prefix) {
Map<String, String> configMetadata = config.getMetaData();
if (StringUtils.hasText(prefix)) {
metaData = new HashMap<>(configMetadata.size(), 1.0f);
for (Map.Entry<String, String> entry : configMetadata.entrySet()) {
metaData.put(prefix + "." + entry.getKey(), entry.getValue());
}
} else {
metaData = configMetadata;
}
}
@ -45,4 +47,7 @@ public class ConfigConfigurationAdapter implements Configuration {
return metaData.get(key);
}
public Map<String, String> getProperties() {
return metaData;
}
}

View File

@ -18,14 +18,18 @@ package org.apache.dubbo.config.context;
import org.apache.dubbo.common.context.FrameworkExt;
import org.apache.dubbo.common.context.LifecycleAdapter;
import org.apache.dubbo.common.extension.DisableInject;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConcurrentHashSet;
import org.apache.dubbo.common.utils.ReflectUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
@ -35,18 +39,16 @@ import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfigBase;
import org.apache.dubbo.config.SslConfig;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@ -54,27 +56,36 @@ import java.util.stream.Collectors;
import static java.lang.Boolean.TRUE;
import static java.util.Collections.emptyMap;
import static java.util.Collections.unmodifiableSet;
import static java.util.Optional.ofNullable;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
import static org.apache.dubbo.common.utils.ReflectUtils.getProperty;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.config.AbstractConfig.getTagName;
import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
public static final String NAME = "config";
public static final String BEAN_NAME = "dubboConfigManager";
private static final String CONFIG_NAME_READ_METHOD = "getName";
private final ReadWriteLock lock = new ReentrantReadWriteLock();
final Map<String, Map<String, AbstractConfig>> configsCache = newMap();
private static Map<Class, AtomicInteger> configIdIndexes = new ConcurrentHashMap<>();
private static volatile boolean configWarnLogEnabled = false;
private static Map<String, Boolean> warnLogStatus = new ConcurrentHashMap<>();
private static Set<Class<? extends AbstractConfig>> uniqueConfigTypes = new ConcurrentHashSet<>();
static {
// init unique config types
uniqueConfigTypes.add(ApplicationConfig.class);
uniqueConfigTypes.add(ModuleConfig.class);
uniqueConfigTypes.add(MonitorConfig.class);
uniqueConfigTypes.add(MetricsConfig.class);
uniqueConfigTypes.add(SslConfig.class);
}
public ConfigManager() {
try {
@ -83,18 +94,24 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
configWarnLogEnabled = Boolean.parseBoolean(rawWarn);
}
} catch (Exception e) {
logger.warn("Illegal 'dubbo.application.config.warn'config, only boolean value is accepted.", e);
logger.warn("Illegal 'dubbo.application.config.warn' config, only boolean value is accepted.", e);
}
}
// ApplicationConfig correlative methods
/**
* Set application config
* @param application
* @return current application config instance
*/
@DisableInject
public void setApplication(ApplicationConfig application) {
addConfig(application, true);
}
public Optional<ApplicationConfig> getApplication() {
return ofNullable(getConfig(getTagName(ApplicationConfig.class)));
return ofNullable(getSingleConfig(getTagName(ApplicationConfig.class)));
}
public ApplicationConfig getApplicationOrElseThrow() {
@ -103,38 +120,42 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
// MonitorConfig correlative methods
@DisableInject
public void setMonitor(MonitorConfig monitor) {
addConfig(monitor, true);
}
public Optional<MonitorConfig> getMonitor() {
return ofNullable(getConfig(getTagName(MonitorConfig.class)));
return ofNullable(getSingleConfig(getTagName(MonitorConfig.class)));
}
// ModuleConfig correlative methods
@DisableInject
public void setModule(ModuleConfig module) {
addConfig(module, true);
}
public Optional<ModuleConfig> getModule() {
return ofNullable(getConfig(getTagName(ModuleConfig.class)));
return ofNullable(getSingleConfig(getTagName(ModuleConfig.class)));
}
@DisableInject
public void setMetrics(MetricsConfig metrics) {
addConfig(metrics, true);
}
public Optional<MetricsConfig> getMetrics() {
return ofNullable(getConfig(getTagName(MetricsConfig.class)));
return ofNullable(getSingleConfig(getTagName(MetricsConfig.class)));
}
@DisableInject
public void setSsl(SslConfig sslConfig) {
addConfig(sslConfig, true);
}
public Optional<SslConfig> getSsl() {
return ofNullable(getConfig(getTagName(SslConfig.class)));
return ofNullable(getSingleConfig(getTagName(SslConfig.class)));
}
// ConfigCenterConfig correlative methods
@ -155,8 +176,8 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return Optional.ofNullable(defaults);
}
public ConfigCenterConfig getConfigCenter(String id) {
return getConfig(getTagName(ConfigCenterConfig.class), id);
public Optional<ConfigCenterConfig> getConfigCenter(String id) {
return getConfig(ConfigCenterConfig.class, id);
}
public Collection<ConfigCenterConfig> getConfigCenters() {
@ -196,7 +217,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public Optional<ProviderConfig> getProvider(String id) {
return ofNullable(getConfig(getTagName(ProviderConfig.class), id));
return getConfig(ProviderConfig.class, id);
}
/**
@ -225,7 +246,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public Optional<ConsumerConfig> getConsumer(String id) {
return ofNullable(getConfig(getTagName(ConsumerConfig.class), id));
return getConfig(ConsumerConfig.class, id);
}
/**
@ -255,28 +276,22 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
}
public Optional<ProtocolConfig> getProtocol(String id) {
return ofNullable(getConfig(getTagName(ProtocolConfig.class), id));
public Optional<ProtocolConfig> getProtocol(String idOrName) {
return getConfig(ProtocolConfig.class, idOrName);
}
public List<ProtocolConfig> getDefaultProtocols() {
return getDefaultConfigs(getConfigsMap(getTagName(ProtocolConfig.class)));
return getDefaultConfigs(ProtocolConfig.class);
}
public <C extends AbstractConfig> List<C> getDefaultConfigs(Class<C> cls) {
return getDefaultConfigs(getConfigsMap(getTagName(cls)));
}
public Collection<ProtocolConfig> getProtocols() {
return getConfigs(getTagName(ProtocolConfig.class));
}
public Set<String> getProtocolIds() {
Set<String> protocolIds = new HashSet<>();
protocolIds.addAll(getSubProperties(ApplicationModel.getEnvironment()
.getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
protocolIds.addAll(getSubProperties(ApplicationModel.getEnvironment()
.getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
return unmodifiableSet(protocolIds);
}
// RegistryConfig correlative methods
@ -291,7 +306,21 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public Optional<RegistryConfig> getRegistry(String id) {
return ofNullable(getConfig(getTagName(RegistryConfig.class), id));
return getConfig(RegistryConfig.class, id);
}
/**
* Get config instance by id or by name
* @param cls Config type
* @param idOrName the id or name of the config
* @return
*/
public <T extends AbstractConfig> Optional<T> getConfig(Class<T> cls, String idOrName) {
T config = getConfigById(getTagName(cls), idOrName);
if (config == null ) {
config = getConfigByName(cls, idOrName);
}
return ofNullable(config);
}
public List<RegistryConfig> getDefaultRegistries() {
@ -302,16 +331,6 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
return getConfigs(getTagName(RegistryConfig.class));
}
public Set<String> getRegistryIds() {
Set<String> registryIds = new HashSet<>();
registryIds.addAll(getSubProperties(ApplicationModel.getEnvironment().getExternalConfigurationMap(),
REGISTRIES_SUFFIX));
registryIds.addAll(getSubProperties(ApplicationModel.getEnvironment().getAppExternalConfigurationMap(),
REGISTRIES_SUFFIX));
return unmodifiableSet(registryIds);
}
// ServiceConfig correlative methods
public void addService(ServiceConfigBase<?> serviceConfig) {
@ -327,7 +346,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public <T> ServiceConfigBase<T> getService(String id) {
return getConfig(getTagName(ServiceConfigBase.class), id);
return getConfig(ServiceConfigBase.class, id).orElse(null);
}
// ReferenceConfig correlative methods
@ -345,14 +364,7 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
public <T> ReferenceConfigBase<T> getReference(String id) {
return getConfig(getTagName(ReferenceConfigBase.class), id);
}
protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
return properties.keySet().stream().filter(k -> k.contains(prefix)).map(k -> {
k = k.substring(prefix.length());
return k.substring(0, k.indexOf("."));
}).collect(Collectors.toSet());
return getConfig(ReferenceConfigBase.class, id).orElse(null);
}
public void refreshAll() {
@ -361,11 +373,15 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
getApplication().ifPresent(ApplicationConfig::refresh);
getMonitor().ifPresent(MonitorConfig::refresh);
getModule().ifPresent(ModuleConfig::refresh);
getMetrics().ifPresent(MetricsConfig::refresh);
getSsl().ifPresent(SslConfig::refresh);
getProtocols().forEach(ProtocolConfig::refresh);
getRegistries().forEach(RegistryConfig::refresh);
getProviders().forEach(ProviderConfig::refresh);
getConsumers().forEach(ConsumerConfig::refresh);
getConfigCenters().forEach(ConfigCenterConfig::refresh);
getMetadataConfigs().forEach(MetadataReportConfig::refresh);
});
}
@ -382,12 +398,15 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
Map<String, AbstractConfig> configs = configsCache.get(getTagName(config.getClass()));
if (CollectionUtils.isNotEmptyMap(configs)) {
configs.remove(getId(config));
configs.values().removeIf(c -> config == c);
}
}
public void clear() {
write(this.configsCache::clear);
write(() -> {
this.configsCache.clear();
configIdIndexes.clear();
});
}
/**
@ -405,35 +424,97 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
* @param config the dubbo {@link AbstractConfig config}
*/
public void addConfig(AbstractConfig config) {
addConfig(config, false);
}
protected void addConfig(AbstractConfig config, boolean unique) {
if (config == null) {
return;
}
write(() -> {
addConfig(config, isUniqueConfig(config));
}
private boolean isUniqueConfig(AbstractConfig config) {
return uniqueConfigTypes.contains(config.getClass());
}
protected <T extends AbstractConfig> T addConfig(AbstractConfig config, boolean unique) {
if (config == null) {
return null;
}
// ignore MethodConfig
if (config instanceof MethodConfig) {
return null;
}
return (T) write(() -> {
Map<String, AbstractConfig> configsMap = configsCache.computeIfAbsent(getTagName(config.getClass()), type -> newMap());
addIfAbsent(config, configsMap, unique);
return addIfAbsent(config, configsMap, unique);
});
}
protected <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
public <C extends AbstractConfig> Map<String, C> getConfigsMap(Class<C> cls) {
return getConfigsMap(getTagName(cls));
}
private <C extends AbstractConfig> Map<String, C> getConfigsMap(String configType) {
return (Map<String, C>) read(() -> configsCache.getOrDefault(configType, emptyMap()));
}
protected <C extends AbstractConfig> Collection<C> getConfigs(String configType) {
private <C extends AbstractConfig> Collection<C> getConfigs(String configType) {
return (Collection<C>) read(() -> getConfigsMap(configType).values());
}
protected <C extends AbstractConfig> C getConfig(String configType, String id) {
public <C extends AbstractConfig> Collection<C> getConfigs(Class<C> configType) {
return (Collection<C>) read(() -> getConfigsMap(getTagName(configType)).values());
}
/**
* Get config by id
* @param configType
* @param id
* @return
*/
private <C extends AbstractConfig> C getConfigById(String configType, String id) {
return read(() -> {
Map<String, C> configsMap = (Map) configsCache.getOrDefault(configType, emptyMap());
return configsMap.get(id);
});
}
protected <C extends AbstractConfig> C getConfig(String configType) throws IllegalStateException {
/**
* Get config by name if existed
* @param cls
* @param name
* @return
*/
private <C extends AbstractConfig> C getConfigByName(Class<? extends C> cls, String name) {
return read(() -> {
String configType = getTagName(cls);
Map<String, C> configsMap = (Map) configsCache.getOrDefault(configType, emptyMap());
if (configsMap.isEmpty()) {
return null;
}
// try find config by name
if (ReflectUtils.hasMethod(cls, CONFIG_NAME_READ_METHOD)) {
List<C> list = configsMap.values().stream()
.filter(cfg -> name.equals(getConfigName(cfg)))
.collect(Collectors.toList());
if (list.size() > 1) {
throw new IllegalStateException("Found more than one config by name: " + name +
", instances: " + list + ". Please remove redundant configs or get config by id.");
} else if (list.size() == 1) {
return list.get(0);
}
}
return null;
});
}
private <C extends AbstractConfig> String getConfigName(C config) {
try {
return (String) ReflectUtils.getProperty(config, CONFIG_NAME_READ_METHOD);
} catch (Exception e) {
return null;
}
}
protected <C extends AbstractConfig> C getSingleConfig(String configType) throws IllegalStateException {
return read(() -> {
Map<String, C> configsMap = (Map) configsCache.getOrDefault(configType, emptyMap());
int size = configsMap.size();
@ -441,22 +522,8 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
// throw new IllegalStateException("No such " + configType.getName() + " is found");
return null;
} else if (size > 1) {
AtomicReference<C> defaultConfig = new AtomicReference<>();
configsMap.forEach((str, config) -> {
if (Boolean.TRUE.equals(config.isDefault())) {
defaultConfig.compareAndSet(null, config);
}
});
if (defaultConfig.get() != null) {
return defaultConfig.get();
}
if (configWarnLogEnabled && warnLogStatus.get(configType) == null) {
logger.warn("Expected single matching of " + configType + ", but found " + size + " instances, will randomly pick the first one.");
warnLogStatus.put(configType, true);
}
throw new IllegalStateException("Expected single instance of " + configType + ", but found " + size +
" instances, please remove redundant configs. instances: "+configsMap.values());
}
return configsMap.values().iterator().next();
@ -501,23 +568,52 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) throws IllegalStateException {
if (oldOne != null && !oldOne.equals(newOne)) {
if (!isEquals(oldOne, newOne)) {
String configName = oldOne.getClass().getSimpleName();
if (configWarnLogEnabled) {
logger.warn("Duplicate Config found for " + configName + ", only one unique " + configName + " is allowed for one application.");
throw new IllegalStateException("Duplicate Configs found for " + configName + ", only one unique " + configName +
" is allowed for one application. old: "+oldOne+", new: "+newOne);
}
}
private static boolean isEquals(AbstractConfig oldOne, AbstractConfig newOne) {
if (oldOne == newOne) {
return true;
}
if (oldOne == null || newOne == null) {
return false;
}
if (oldOne.getClass() != newOne.getClass()) {
return false;
}
// make both are refreshed or none is refreshed
if (oldOne.isRefreshed() || newOne.isRefreshed()) {
if (!oldOne.isRefreshed()) {
oldOne.refresh();
}
if (!newOne.isRefreshed()) {
newOne.refresh();
}
}
return oldOne.equals(newOne);
}
private static Map newMap() {
return new HashMap<>();
}
static <C extends AbstractConfig> void addIfAbsent(C config, Map<String, C> configsMap, boolean unique)
/**
* Add config
* @param config
* @param configsMap
* @param unique
* @return the existing equivalent config or the new adding config
* @throws IllegalStateException
*/
static <C extends AbstractConfig> C addIfAbsent(C config, Map<String, C> configsMap, boolean unique)
throws IllegalStateException {
if (config == null || configsMap == null) {
return;
return config;
}
if (unique) { // check duplicate
@ -526,39 +622,84 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
});
}
// find by value
// TODO Is there a problem with ignoring duplicate but different ReferenceConfig instances?
Optional<C> prevConfig = configsMap.values().stream()
.filter(val -> isEquals(val, config))
.findFirst();
if (prevConfig.isPresent()) {
if (prevConfig.get() == config) {
// the new one is same as existing one
return prevConfig.get();
}
if (unique) {
// unique config just need single instance, use prev equivalent instance is ok
if (logger.isInfoEnabled()) {
logger.info("Ignore duplicated config: " + config);
}
return prevConfig.get();
}
// throw new IllegalStateException("An equivalent config instance already exists, please remove the redundant configuration. " +
// "prev: " + prevConfig.get() + ", new: " + config);
// logger.warn("An equivalent config instance already exists, ignore the new instance. prev: " + prevConfig.get() +
// ", new: " + config);
// return;
}
String key = getId(config);
if (key == null) {
// generate key for non-default config compatible with API usages
key = generateConfigId(config);
}
C existedConfig = configsMap.get(key);
if (existedConfig != null && !config.equals(existedConfig)) {
if (configWarnLogEnabled) {
//TODO throw exception
if (logger.isWarnEnabled()) {
String type = config.getClass().getSimpleName();
logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
"you can try to give each %s a different id : %s", type, type, type, type, config));
}
}
if (isEquals(existedConfig, config)) {
String type = config.getClass().getSimpleName();
throw new IllegalStateException(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
"you can try to give each %s a different id, key: %s, prev: %s, new: %s", type, type, type, type, key, existedConfig, config));
} else {
configsMap.put(key, config);
}
return config;
}
public static <C extends AbstractConfig> String generateConfigId(C config) {
int idx = configIdIndexes.computeIfAbsent(config.getClass(), clazz -> new AtomicInteger(0)).incrementAndGet();
return config.getClass().getSimpleName() + "#" + idx;
}
static <C extends AbstractConfig> String getId(C config) {
String id = config.getId();
return isNotEmpty(id) ? id : isDefaultConfig(config) ?
config.getClass().getSimpleName() + "#" + DEFAULT_KEY : null;
return isNotEmpty(id) ? id : null;
}
static <C extends AbstractConfig> boolean isDefaultConfig(C config) {
Boolean isDefault = getProperty(config, "isDefault");
return isDefault == null || TRUE.equals(isDefault);
static <C extends AbstractConfig> Boolean isDefaultConfig(C config) {
// If no isDefault() method, it is considered that each can be used as default
if (!ReflectUtils.hasMethod(config.getClass(), "isDefault")) {
return true;
}
Boolean isDefault = ReflectUtils.getProperty(config, "isDefault");
return isDefault;
}
static <C extends AbstractConfig> List<C> getDefaultConfigs(Map<String, C> configsMap) {
return configsMap.values()
// find isDefault() == TRUE
List<C> list = configsMap.values()
.stream()
.filter(ConfigManager::isDefaultConfig)
.filter(c -> TRUE.equals(ConfigManager.isDefaultConfig(c)))
.collect(Collectors.toList());
if (list.size() > 0) {
return list;
}
// find isDefault() == null
list = configsMap.values()
.stream()
.filter(c -> ConfigManager.isDefaultConfig(c) == null)
.collect(Collectors.toList());
return list;
}
}

View File

@ -30,33 +30,34 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD})
public @interface Parameter {
/**
* Specify the parameter key when append parameters to url
*/
String key() default "";
/**
* If required=true, the value must not be empty when append to url
*/
boolean required() default false;
/**
* If excluded=true, ignore it when append parameters to url
*/
boolean excluded() default false;
/**
* if escaped=true, escape it when append parameters to url
*/
boolean escaped() default false;
boolean attribute() default false;
boolean append() default false;
/**
* If attribute=false, ignore it when processing refresh()/getMetadata()/equals()/toString()
*/
boolean attribute() default true;
/**
* if {@link #key()} is specified, it will be used as the key for the annotated property when generating url.
* by default, this key will also be used to retrieve the config value:
* <pre>
* {@code
* class ExampleConfig {
* // Dubbo will try to get "dubbo.example.alias_for_item=xxx" from .properties, if you want to use the original property
* // "dubbo.example.item=xxx", you need to set useKeyAsProperty=false.
* @Parameter(key = "alias_for_item")
* public getItem();
* }
* }
*
* </pre>
* If append=true, append new value to exist value instead of overriding it.
*/
boolean useKeyAsProperty() default true;
boolean append() default false;
}

View File

@ -127,7 +127,7 @@ public class ApplicationModel {
public static void reset() {
getServiceRepository().destroy();
getConfigManager().destroy();
getEnvironment().destroy();
getEnvironment().reset();
}
}

View File

@ -16,8 +16,40 @@
*/
package org.apache.dubbo.common.config;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.Test;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
*
*/
public class EnvironmentTest {
@Test
public void testResolvePlaceholders1() {
Environment environment = ApplicationModel.getEnvironment();
Map<String, String> externalMap = new LinkedHashMap<>();
externalMap.put("zookeeper.address", "127.0.0.1");
externalMap.put("zookeeper.port", "2181");
environment.updateAppExternalConfigMap(externalMap);
Map<String, String> sysprops = new LinkedHashMap<>();
sysprops.put("zookeeper.address", "192.168.10.1");
System.getProperties().putAll(sysprops);
try {
String s = environment.resolvePlaceholders("zookeeper://${zookeeper.address}:${zookeeper.port}");
assertEquals("zookeeper://192.168.10.1:2181", s);
} finally {
for (String key : sysprops.keySet()) {
System.clearProperty(key);
}
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.config;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.LinkedHashMap;
import java.util.Map;
public class PrefixedConfigurationTest {
@Test
public void testPrefixedConfiguration() {
Map<String,String> props = new LinkedHashMap<>();
props.put("dubbo.protocol.name", "dubbo");
props.put("dubbo.protocol.port", "1234");
props.put("dubbo.protocols.rest.port", "2345");
InmemoryConfiguration inmemoryConfiguration = new InmemoryConfiguration();
inmemoryConfiguration.addProperties(props);
// prefixed over InmemoryConfiguration
PrefixedConfiguration prefixedConfiguration = new PrefixedConfiguration(inmemoryConfiguration, "dubbo.protocol");
Assertions.assertEquals("dubbo", prefixedConfiguration.getProperty("name"));
Assertions.assertEquals("1234", prefixedConfiguration.getProperty("port"));
prefixedConfiguration = new PrefixedConfiguration(inmemoryConfiguration, "dubbo.protocols.rest");
Assertions.assertEquals("2345", prefixedConfiguration.getProperty("port"));
// prefixed over composite configuration
CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
compositeConfiguration.addConfiguration(inmemoryConfiguration);
prefixedConfiguration = new PrefixedConfiguration(compositeConfiguration, "dubbo.protocols.rest");
Assertions.assertEquals("2345", prefixedConfiguration.getProperty("port"));
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.dubbo.common.utils;
import org.apache.dubbo.common.config.CompositeConfiguration;
import org.apache.dubbo.common.config.InmemoryConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.threadpool.ThreadPool;
@ -112,9 +114,31 @@ public class ConfigUtilsTest {
@Test
public void testReplaceProperty() throws Exception {
String s = ConfigUtils.replaceProperty("1${a.b.c}2${a.b.c}3", Collections.singletonMap("a.b.c", "ABC"));
assertEquals(s, "1ABC2ABC3");
assertEquals( "1ABC2ABC3", s);
s = ConfigUtils.replaceProperty("1${a.b.c}2${a.b.c}3", Collections.<String, String>emptyMap());
assertEquals(s, "123");
assertEquals("1${a.b.c}2${a.b.c}3", s);
}
@Test
public void testReplaceProperty2() {
InmemoryConfiguration configuration1 = new InmemoryConfiguration();
configuration1.getProperties().put("zookeeper.address", "127.0.0.1");
InmemoryConfiguration configuration2 = new InmemoryConfiguration();
configuration2.getProperties().put("zookeeper.port", "2181");
CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
compositeConfiguration.addConfiguration(configuration1);
compositeConfiguration.addConfiguration(configuration2);
String s = ConfigUtils.replaceProperty("zookeeper://${zookeeper.address}:${zookeeper.port}", compositeConfiguration);
assertEquals("zookeeper://127.0.0.1:2181", s);
// should not replace inner class name
String interfaceName = "dubbo.service.io.grpc.examples.helloworld.DubboGreeterGrpc$IGreeter";
s = ConfigUtils.replaceProperty(interfaceName, compositeConfiguration);
Assertions.assertEquals(interfaceName, s);
}
@Test

View File

@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -33,6 +34,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
import static org.apache.dubbo.common.utils.StringUtils.splitToList;
import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
import static org.apache.dubbo.common.utils.StringUtils.startsWithIgnoreCase;
import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
@ -337,8 +339,44 @@ public class StringUtilsTest {
public void testCamelToSplitName() throws Exception {
assertEquals("ab-cd-ef", StringUtils.camelToSplitName("abCdEf", "-"));
assertEquals("ab-cd-ef", StringUtils.camelToSplitName("AbCdEf", "-"));
assertEquals("ab-cd-ef", StringUtils.camelToSplitName("ab-cd-ef", "-"));
assertEquals("abcdef", StringUtils.camelToSplitName("abcdef", "-"));
//assertEquals("name", StringUtils.camelToSplitName("NAME", "-"));
assertEquals("ab-cd-ef", StringUtils.camelToSplitName("ab-cd-ef", "-"));
assertEquals("ab-cd-ef", StringUtils.camelToSplitName("Ab-Cd-Ef", "-"));
assertEquals("Ab_Cd_Ef", StringUtils.camelToSplitName("Ab_Cd_Ef", "-"));
assertEquals("AB_CD_EF", StringUtils.camelToSplitName("AB_CD_EF", "-"));
assertEquals("ab.cd.ef", StringUtils.camelToSplitName("AbCdEf", "."));
//assertEquals("ab.cd.ef", StringUtils.camelToSplitName("ab-cd-ef", "."));
}
@Test
public void testSnakeCaseToSplitName() throws Exception {
assertEquals("ab-cd-ef", StringUtils.snakeToSplitName("ab_Cd_Ef", "-"));
assertEquals("ab-cd-ef", StringUtils.snakeToSplitName("Ab_Cd_Ef", "-"));
assertEquals("ab-cd-ef", StringUtils.snakeToSplitName("ab_cd_ef", "-"));
assertEquals("ab-cd-ef", StringUtils.snakeToSplitName("AB_CD_EF", "-"));
assertEquals("abcdef", StringUtils.snakeToSplitName("abcdef", "-"));
assertEquals("qosEnable", StringUtils.snakeToSplitName("qosEnable", "-"));
assertEquals("name", StringUtils.snakeToSplitName("NAME", "-"));
}
@Test
public void testConvertToSplitName() {
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("ab_Cd_Ef", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("Ab_Cd_Ef", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("ab_cd_ef", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("AB_CD_EF", "-"));
assertEquals("abcdef", StringUtils.convertToSplitName("abcdef", "-"));
assertEquals("qos-enable", StringUtils.convertToSplitName("qosEnable", "-"));
assertEquals("name", StringUtils.convertToSplitName("NAME", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("abCdEf", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("AbCdEf", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("ab-cd-ef", "-"));
assertEquals("ab-cd-ef", StringUtils.convertToSplitName("Ab-Cd-Ef", "-"));
}
@Test
@ -377,20 +415,59 @@ public class StringUtilsTest {
assertEquals(2, legalMap.size());
assertEquals("value2", legalMap.get("key2"));
String str = StringUtils.encodeParameters(legalMap);
assertEqualsWithoutSpaces(legalStr, str);
String legalSpaceStr = "[{key1: value1}, {key2 :value2}]";
Map<String, String> legalSpaceMap = StringUtils.parseParameters(legalSpaceStr);
assertEquals(2, legalSpaceMap.size());
assertEquals("value2", legalSpaceMap.get("key2"));
str = StringUtils.encodeParameters(legalSpaceMap);
assertEqualsWithoutSpaces(legalSpaceStr, str);
String legalSpecialStr = "[{key-1: value*.1}, {key.2 :value*.-_2}]";
Map<String, String> legalSpecialMap = StringUtils.parseParameters(legalSpecialStr);
assertEquals(2, legalSpecialMap.size());
assertEquals("value*.1", legalSpecialMap.get("key-1"));
assertEquals("value*.-_2", legalSpecialMap.get("key.2"));
str = StringUtils.encodeParameters(legalSpecialMap);
assertEqualsWithoutSpaces(legalSpecialStr, str);
String illegalStr = "[{key=value},{aa:bb}]";
Map<String, String> illegalMap = StringUtils.parseParameters(illegalStr);
assertEquals(0, illegalMap.size());
str = StringUtils.encodeParameters(illegalMap);
assertEquals(null, str);
String emptyMapStr = "[]";
Map<String, String> emptyMap = StringUtils.parseParameters(emptyMapStr);
assertEquals(0, emptyMap.size());
}
@Test
public void testEncodeParameters() {
Map<String, String> nullValueMap = new LinkedHashMap<>();
nullValueMap.put("client", null);
String str = StringUtils.encodeParameters(nullValueMap);
assertEquals("[]", str);
Map<String, String> blankValueMap = new LinkedHashMap<>();
blankValueMap.put("client", " ");
str = StringUtils.encodeParameters(nullValueMap);
assertEquals("[]", str);
blankValueMap = new LinkedHashMap<>();
blankValueMap.put("client", "");
str = StringUtils.encodeParameters(nullValueMap);
assertEquals("[]", str);
}
private void assertEqualsWithoutSpaces(String expect, String actual) {
assertEquals(expect.replaceAll(" ", ""), actual.replaceAll(" ", ""));
}
/**
@ -418,4 +495,11 @@ public class StringUtilsTest {
assertEquals("one,two,three", value);
}
@Test
public void testStartsWithIgnoreCase() {
assertTrue(startsWithIgnoreCase("dubbo.application.name", "dubbo.application."));
assertTrue(startsWithIgnoreCase("dubbo.Application.name", "dubbo.application."));
assertTrue(startsWithIgnoreCase("Dubbo.application.name", "dubbo.application."));
}
}

View File

@ -55,6 +55,19 @@ public class VersionTest {
Assertions.assertEquals(Version.HIGHEST_PROTOCOL_VERSION, Version.getIntVersion("2.0.99"));
Assertions.assertEquals(2070000, Version.getIntVersion("2.7.0.RC1"));
Assertions.assertEquals(2070000, Version.getIntVersion("2.7.0-SNAPSHOT"));
Assertions.assertEquals(3000000, Version.getIntVersion("3.0.0-SNAPSHOT"));
Assertions.assertEquals(3010000, Version.getIntVersion("3.1.0"));
}
@Test
public void testCompare() {
Assertions.assertEquals(0, Version.compare("3.0.0", "3.0.0"));
Assertions.assertEquals(0, Version.compare("3.0.0-SNAPSHOT", "3.0.0"));
Assertions.assertEquals(1, Version.compare("3.0.0.1", "3.0.0"));
Assertions.assertEquals(1, Version.compare("3.1.0", "3.0.0"));
Assertions.assertEquals(1, Version.compare("3.1.2.3", "3.0.0"));
Assertions.assertEquals(-1, Version.compare("2.9.9.9", "3.0.0"));
Assertions.assertEquals(-1, Version.compare("2.6.3.1", "3.0.0"));
}
@Test

View File

@ -36,6 +36,7 @@ import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
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;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
@ -74,12 +75,10 @@ public class ConfigManagerTest {
// protocols
assertTrue(configManager.getProtocols().isEmpty());
assertTrue(configManager.getDefaultProtocols().isEmpty());
assertTrue(configManager.getProtocolIds().isEmpty());
// registries
assertTrue(configManager.getRegistries().isEmpty());
assertTrue(configManager.getDefaultRegistries().isEmpty());
assertTrue(configManager.getRegistryIds().isEmpty());
// services and references
assertTrue(configManager.getServices().isEmpty());
@ -139,7 +138,9 @@ public class ConfigManagerTest {
assertEquals(config, configs.iterator().next());
assertTrue(configManager.getDefaultProvider().isPresent());
config = new ProviderConfig();
config.setId(DEFAULT_KEY);
config.setQueues(10);
configManager.addProvider(config);
assertTrue(configManager.getDefaultProvider().isPresent());
configs = configManager.getProviders();
@ -156,7 +157,9 @@ public class ConfigManagerTest {
assertEquals(config, configs.iterator().next());
assertTrue(configManager.getDefaultConsumer().isPresent());
config = new ConsumerConfig();
config.setId(DEFAULT_KEY);
config.setThreads(10);
configManager.addConsumer(config);
assertTrue(configManager.getDefaultConsumer().isPresent());
configs = configManager.getConsumers();
@ -218,10 +221,10 @@ public class ConfigManagerTest {
assertFalse(ConfigManager.isDefaultConfig(providerConfig));
ProviderConfig providerConfig1 = new ProviderConfig();
assertTrue(ConfigManager.isDefaultConfig(providerConfig1));
assertNull(ConfigManager.isDefaultConfig(providerConfig1));
ProviderConfig providerConfig3 = new ProviderConfig();
providerConfig.setDefault(true);
providerConfig3.setDefault(true);
assertTrue(ConfigManager.isDefaultConfig(providerConfig3));
ProtocolConfig protocolConfig = new ProtocolConfig();

View File

@ -35,14 +35,14 @@ public class ConfigTest {
@AfterEach
public void tearDown() {
ApplicationModel.reset();
DubboBootstrap.reset();
}
@BeforeEach
public void setup() {
// In IDE env, make sure adding the following argument to VM options
System.setProperty("java.net.preferIPv4Stack", "true");
ApplicationModel.reset();
DubboBootstrap.reset();
}
@Test

View File

@ -117,14 +117,14 @@ public class MethodConfigTest {
assertEquals(methodInfo.getOninvokeMethod(), Person.class.getMethod("setName", String.class));
}
@Test
//@Test
public void testOnreturn() throws Exception {
MethodConfig method = new MethodConfig();
method.setOnreturn("on-return-object");
assertThat(method.getOnreturn(), equalTo((Object) "on-return-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_RETURN_INSTANCE_KEY, (Object) "on-return-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_RETURN_INSTANCE_KEY, (Object) "on-return-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -135,22 +135,22 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOnreturnMethod("on-return-method");
assertThat(method.getOnreturnMethod(), equalTo("on-return-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_RETURN_METHOD_KEY, (Object) "on-return-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_RETURN_METHOD_KEY, (Object) "on-return-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
}
@Test
//@Test
public void testOnthrow() throws Exception {
MethodConfig method = new MethodConfig();
method.setOnthrow("on-throw-object");
assertThat(method.getOnthrow(), equalTo((Object) "on-throw-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_THROW_INSTANCE_KEY, (Object) "on-throw-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_THROW_INSTANCE_KEY, (Object) "on-throw-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -161,22 +161,22 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOnthrowMethod("on-throw-method");
assertThat(method.getOnthrowMethod(), equalTo("on-throw-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_THROW_METHOD_KEY, (Object) "on-throw-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_THROW_METHOD_KEY, (Object) "on-throw-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
}
@Test
//@Test
public void testOninvoke() throws Exception {
MethodConfig method = new MethodConfig();
method.setOninvoke("on-invoke-object");
assertThat(method.getOninvoke(), equalTo((Object) "on-invoke-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -187,9 +187,9 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOninvokeMethod("on-invoke-method");
assertThat(method.getOninvokeMethod(), equalTo("on-invoke-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));

View File

@ -40,7 +40,7 @@ public class ModuleConfigTest {
ModuleConfig module = new ModuleConfig();
module.setName("module-name");
assertThat(module.getName(), equalTo("module-name"));
assertThat(module.getId(), equalTo("module-name"));
assertThat(module.getId(), equalTo(null));
Map<String, String> parameters = new HashMap<String, String>();
ModuleConfig.appendParameters(parameters, module);
assertThat(parameters, hasEntry("module", "module-name"));

View File

@ -39,7 +39,7 @@ public class ProtocolConfigTest {
Map<String, String> parameters = new HashMap<String, String>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(protocol.getName(), equalTo("name"));
assertThat(protocol.getId(), equalTo("name"));
assertThat(protocol.getId(), equalTo(null));
assertThat(parameters.isEmpty(), is(true));
}

View File

@ -18,7 +18,6 @@
package org.apache.dubbo.config;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.service.DemoService;
import org.apache.dubbo.service.DemoServiceImpl;
@ -38,12 +37,12 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() {
ApplicationModel.reset();
DubboBootstrap.reset();
}
@AfterEach
public void tearDown() {
ApplicationModel.reset();
DubboBootstrap.reset();
}
@Test

View File

@ -20,6 +20,7 @@ package org.apache.dubbo.generic;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder;
import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.definition.model.MethodDefinition;
@ -36,6 +37,7 @@ import org.apache.dubbo.service.DemoServiceImpl;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.fastjson.JSON;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
@ -46,6 +48,11 @@ import java.util.Map;
public class GenericServiceTest {
@BeforeEach
public void beforeEach() {
DubboBootstrap.reset();
}
@Test
public void testGeneric() {
DemoService server = new DemoServiceImpl();
@ -91,6 +98,10 @@ public class GenericServiceTest {
@Test
public void testGenericCompatible() {
DubboBootstrap.getInstance()
.application("test-app")
.initialize();
DemoService server = new DemoServiceImpl();
ProxyFactory proxyFactory = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
@ -101,7 +112,7 @@ public class GenericServiceTest {
ReferenceConfig<com.alibaba.dubbo.rpc.service.GenericService> oldReferenceConfig = new ReferenceConfig<>();
oldReferenceConfig.setGeneric(true);
oldReferenceConfig.setInterface(DemoService.class.getName());
oldReferenceConfig.checkAndUpdateSubConfigs();
oldReferenceConfig.refresh();
Invoker invoker = protocol.refer(oldReferenceConfig.getInterfaceClass(), url);
com.alibaba.dubbo.rpc.service.GenericService client = (com.alibaba.dubbo.rpc.service.GenericService) proxyFactory.getProxy(invoker, true);

View File

@ -16,7 +16,6 @@
*/
package org.apache.dubbo.config;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@ -25,8 +24,6 @@ import org.apache.dubbo.config.event.DubboShutdownHookRegisteredEvent;
import org.apache.dubbo.config.event.DubboShutdownHookUnregisteredEvent;
import org.apache.dubbo.event.Event;
import org.apache.dubbo.event.EventDispatcher;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.Protocol;
import java.util.concurrent.atomic.AtomicBoolean;
@ -66,12 +63,14 @@ public class DubboShutdownHook extends Thread {
@Override
public void run() {
if (logger.isInfoEnabled()) {
logger.info("Run shutdown hook now.");
}
if (destroyed.compareAndSet(false, true)) {
if (logger.isInfoEnabled()) {
logger.info("Run shutdown hook now.");
}
callback();
doDestroy();
callback();
doDestroy();
}
}
/**
@ -123,27 +122,4 @@ public class DubboShutdownHook extends Thread {
return registered.get();
}
public static void destroyAll() {
if (destroyed.compareAndSet(false, true)) {
AbstractRegistryFactory.destroyAll();
destroyProtocols();
}
}
/**
* Destroy all the protocols.
*/
public static void destroyProtocols() {
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
for (String protocolName : loader.getLoadedExtensions()) {
try {
Protocol protocol = loader.getLoadedExtension(protocolName);
if (protocol != null) {
protocol.destroy();
}
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
}
}

View File

@ -230,21 +230,44 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
dispatch(new ReferenceConfigDestroyedEvent(this));
}
public synchronized void init() {
protected synchronized void init() {
if (initialized) {
return;
}
// Using DubboBootstrap API will associate bootstrap when registering reference.
// Loading by Spring context will associate bootstrap in afterPropertiesSet() method.
// Initializing bootstrap here only for compatible with old API usages.
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
bootstrap.initialize();
bootstrap.reference(this);
}
checkAndUpdateSubConfigs();
// check bootstrap state
if (!bootstrap.isInitialized()) {
throw new IllegalStateException("DubboBootstrap is not initialized");
}
if (!this.isRefreshed()) {
this.refresh();
}
//init serivceMetadata
initServiceMetadata(consumer);
serviceMetadata.setServiceType(getActualInterface());
// TODO, uncomment this line once service key is unified
serviceMetadata.setServiceKey(URL.buildKey(interfaceName, group, version));
ServiceRepository repository = ApplicationModel.getServiceRepository();
ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass);
repository.registerConsumer(
serviceMetadata.getServiceKey(),
serviceDescriptor,
this,
null,
serviceMetadata);
checkStubAndLocal(interfaceClass);
ConfigValidationUtils.checkMock(interfaceClass, this);
Map<String, String> map = new HashMap<String, String>();
map.put(SIDE_KEY, CONSUMER_SIDE);
@ -453,20 +476,19 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
* This method should be called right after the creation of this class's instance, before any property in other config modules is used.
* Check each config modules are created properly and override their properties if necessary.
*/
public void checkAndUpdateSubConfigs() {
protected void checkAndUpdateSubConfigs() {
if (StringUtils.isEmpty(interfaceName)) {
throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
}
completeCompoundConfigs(consumer);
// get consumer's global configuration
checkDefault();
completeCompoundConfigs();
// init some null configuration.
List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
.getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
configInitializers.forEach(e -> e.initReferConfig(this));
this.refresh();
if (getGeneric() == null && getConsumer() != null) {
setGeneric(getConsumer().getGeneric());
}
@ -479,28 +501,31 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, getMethods());
//checkInterfaceAndMethods(interfaceClass, getMethods());
}
initServiceMetadata(consumer);
serviceMetadata.setServiceType(getActualInterface());
// TODO, uncomment this line once service key is unified
serviceMetadata.setServiceKey(URL.buildKey(interfaceName, group, version));
ServiceRepository repository = ApplicationModel.getServiceRepository();
ServiceDescriptor serviceDescriptor = repository.registerService(interfaceClass);
repository.registerConsumer(
serviceMetadata.getServiceKey(),
serviceDescriptor,
this,
null,
serviceMetadata);
checkStubAndLocal(interfaceClass);
ConfigValidationUtils.checkMock(interfaceClass, this);
resolveFile();
ConfigValidationUtils.validateReferenceConfig(this);
postProcessConfig();
}
@Override
protected void postProcessRefresh() {
super.postProcessRefresh();
checkAndUpdateSubConfigs();
}
protected void completeCompoundConfigs() {
super.completeCompoundConfigs(consumer);
if (consumer != null) {
if (StringUtils.isEmpty(registryIds)) {
setRegistryIds(consumer.getRegistryIds());
}
}
}
/**
* Figure out should refer the service in the same JVM from configurations. The default behavior is true

View File

@ -107,7 +107,7 @@ import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
public class ServiceConfig<T> extends ServiceConfigBase<T> {
public static final Logger logger = LoggerFactory.getLogger(ServiceConfig.class);
private static final Logger logger = LoggerFactory.getLogger(ServiceConfig.class);
/**
* A random port cache, the different protocols who has no port specified have different random port
@ -151,12 +151,12 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
super(service);
}
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isExported() {
return exported;
}
@Parameter(excluded = true)
@Parameter(excluded = true, attribute = false)
public boolean isUnexported() {
return unexported;
}
@ -189,13 +189,23 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
return;
}
// Using DubboBootstrap API will associate bootstrap when registering service.
// Loading by Spring context will associate bootstrap in afterPropertiesSet() method.
// Initializing bootstrap here only for compatible with old API usages.
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
bootstrap.initialize();
bootstrap.service(this);
}
checkAndUpdateSubConfigs();
// check bootstrap state
if (!bootstrap.isInitialized()) {
throw new IllegalStateException("DubboBootstrap is not initialized");
}
if (!this.isRefreshed()) {
this.refresh();
}
initServiceMetadata(provider);
serviceMetadata.setServiceType(getInterfaceClass());
@ -225,10 +235,12 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
}
private void checkAndUpdateSubConfigs() {
// Use default configs defined explicitly with global scope
completeCompoundConfigs();
checkDefault();
checkProtocol();
// init some null configuration.
List<ConfigInitializer> configInitializers = ExtensionLoader.getExtensionLoader(ConfigInitializer.class)
.getActivateExtension(URL.valueOf("configInitializer://"), (String[]) null);
@ -238,7 +250,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
if (!isOnlyInJvm()) {
checkRegistry();
}
this.refresh();
if (StringUtils.isEmpty(interfaceName)) {
throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
@ -256,7 +267,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
} catch (ClassNotFoundException e) {
throw new IllegalStateException(e.getMessage(), e);
}
checkInterfaceAndMethods(interfaceClass, getMethods());
//checkInterfaceAndMethods(interfaceClass, getMethods());
checkRef();
generic = Boolean.FALSE.toString();
}
@ -294,6 +305,11 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
postProcessConfig();
}
@Override
protected void postProcessRefresh() {
super.postProcessRefresh();
checkAndUpdateSubConfigs();
}
protected synchronized void doExport() {
if (unexported) {

View File

@ -22,6 +22,7 @@ import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.logger.Logger;
@ -30,7 +31,9 @@ import org.apache.dubbo.common.threadpool.concurrent.ScheduledCompletableFuture;
import org.apache.dubbo.common.threadpool.manager.ExecutorRepository;
import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.ConsumerConfig;
@ -42,6 +45,7 @@ import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.ReferenceConfigBase;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.ServiceConfigBase;
@ -70,13 +74,17 @@ import org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils;
import org.apache.dubbo.registry.client.metadata.store.InMemoryWritableMetadataService;
import org.apache.dubbo.registry.client.metadata.store.RemoteMetadataServiceImpl;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
@ -95,6 +103,7 @@ import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
@ -183,6 +192,8 @@ public class DubboBootstrap {
private List<CompletableFuture<Object>> asyncReferringFutures = new ArrayList<>();
private static boolean ignoreConfigState;
/**
* See {@link ApplicationModel} and {@link ExtensionLoader} for why DubboBootstrap is designed to be singleton.
*/
@ -199,19 +210,38 @@ public class DubboBootstrap {
/**
* Try reset dubbo status for new instance.
* For testing purposes only
*
* @deprecated For testing purposes only
*/
@Deprecated
public static void reset() {
if (instance != null) {
instance.destroy();
reset(true);
}
/**
* Try reset dubbo status for new instance.
*
* @deprecated For testing purposes only
*/
@Deprecated
public static void reset(boolean destroy) {
ConfigUtils.setProperties(null);
DubboBootstrap.ignoreConfigState = true;
if (destroy) {
if (instance != null) {
instance.destroy();
instance = null;
}
MetadataReportInstance.reset();
AbstractRegistryFactory.reset();
ExtensionLoader.destroyAll();
//ExtensionLoader.resetExtensionLoader(GovernanceRuleRepository.class);
} else {
instance = null;
}
ApplicationModel.reset();
MetadataReportInstance.destroy();
AbstractMetadataReportFactory.clear();
ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
ExtensionLoader.resetExtensionLoader(MetadataReportFactory.class);
ExtensionLoader.destroyAll();
ShutdownHookCallbacks.INSTANCE.clear();
}
private DubboBootstrap() {
@ -222,6 +252,10 @@ public class DubboBootstrap {
ShutdownHookCallbacks.INSTANCE.addCallback(DubboBootstrap.this::destroy);
}
public ConfigManager getConfigManager() {
return configManager;
}
public void unRegisterShutdownHook() {
DubboShutdownHook.getDubboShutdownHook().unregister();
}
@ -378,6 +412,7 @@ public class DubboBootstrap {
}
public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
serviceConfig.setBootstrap(this);
configManager.addService(serviceConfig);
return this;
}
@ -402,6 +437,7 @@ public class DubboBootstrap {
}
public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
referenceConfig.setBootstrap(this);
configManager.addReference(referenceConfig);
return this;
}
@ -527,11 +563,10 @@ public class DubboBootstrap {
}
ApplicationModel.initFrameworkExts();
startConfigCenter();
loadRemoteConfigs();
loadConfigsFromProps();
checkGlobalConfigs();
@ -546,73 +581,119 @@ public class DubboBootstrap {
}
private void checkGlobalConfigs() {
// check Application
ConfigValidationUtils.validateApplicationConfig(getApplication());
// check config types (ignore metadata-center)
List<Class<? extends AbstractConfig>> multipleConfigTypes = Arrays.asList(
ApplicationConfig.class,
ProtocolConfig.class,
RegistryConfig.class,
MetadataReportConfig.class,
ProviderConfig.class,
ConsumerConfig.class,
MonitorConfig.class,
ModuleConfig.class,
MetricsConfig.class,
SslConfig.class);
// check Metadata
Collection<MetadataReportConfig> metadatas = configManager.getMetadataConfigs();
if (CollectionUtils.isEmpty(metadatas)) {
MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
metadataReportConfig.refresh();
if (metadataReportConfig.isValid()) {
configManager.addMetadataReport(metadataReportConfig);
metadatas = configManager.getMetadataConfigs();
for (Class<? extends AbstractConfig> configType : multipleConfigTypes) {
checkDefaultAndValidateConfigs(configType);
}
// check port conflicts
Map<Integer, ProtocolConfig> protocolPortMap = new LinkedHashMap<>();
for (ProtocolConfig protocol : configManager.getProtocols()) {
Integer port = protocol.getPort();
if (port == null || port == -1) {
continue;
}
}
if (CollectionUtils.isNotEmpty(metadatas)) {
for (MetadataReportConfig metadataReportConfig : metadatas) {
metadataReportConfig.refresh();
ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
ProtocolConfig prevProtocol = protocolPortMap.get(port);
if (prevProtocol != null) {
throw new IllegalStateException("Duplicated port used by protocol configs, port: " + port +
", configs: " + Arrays.asList(prevProtocol, protocol));
}
protocolPortMap.put(port, protocol);
}
// check Provider
Collection<ProviderConfig> providers = configManager.getProviders();
if (CollectionUtils.isEmpty(providers)) {
configManager.getDefaultProvider().orElseGet(() -> {
ProviderConfig providerConfig = new ProviderConfig();
configManager.addProvider(providerConfig);
providerConfig.refresh();
return providerConfig;
});
// check reference and service
for (ReferenceConfigBase<?> reference : configManager.getReferences()) {
reference.refresh();
}
for (ProviderConfig providerConfig : configManager.getProviders()) {
ConfigValidationUtils.validateProviderConfig(providerConfig);
for (ServiceConfigBase service : configManager.getServices()) {
service.refresh();
}
// check Consumer
Collection<ConsumerConfig> consumers = configManager.getConsumers();
if (CollectionUtils.isEmpty(consumers)) {
configManager.getDefaultConsumer().orElseGet(() -> {
ConsumerConfig consumerConfig = new ConsumerConfig();
configManager.addConsumer(consumerConfig);
consumerConfig.refresh();
return consumerConfig;
});
}
for (ConsumerConfig consumerConfig : configManager.getConsumers()) {
ConfigValidationUtils.validateConsumerConfig(consumerConfig);
}
private <T extends AbstractConfig> void checkDefaultAndValidateConfigs(Class<T> configType) {
boolean needValid = (configType == MetadataReportConfig.class);
try {
if (shouldAddDefaultConfig(configType)) {
T config = configType.newInstance();
config.refresh();
if (!needValid || config.isValid()) {
configManager.addConfig(config);
} else {
logger.info("Ignore invalid config: " + config);
}
}
} catch (Exception e) {
throw new IllegalStateException("Add default config failed: " + configType.getSimpleName(), e);
}
// check Monitor
ConfigValidationUtils.validateMonitorConfig(getMonitor());
// check Metrics
ConfigValidationUtils.validateMetricsConfig(getMetrics());
// check Module
ConfigValidationUtils.validateModuleConfig(getModule());
// check Ssl
ConfigValidationUtils.validateSslConfig(getSsl());
//validate configs
Collection<T> configs = configManager.getConfigs(configType);
for (T config : configs) {
validateConfig(config);
}
// check required default
if (configType != MetadataReportConfig.class && configs.isEmpty()) {
throw new IllegalStateException("Default config not found for " + configType.getSimpleName());
}
}
private <T extends AbstractConfig> void validateConfig(T config) {
if (config instanceof ProtocolConfig) {
ConfigValidationUtils.validateProtocolConfig((ProtocolConfig) config);
} else if (config instanceof RegistryConfig) {
ConfigValidationUtils.validateRegistryConfig((RegistryConfig) config);
} else if (config instanceof MetadataReportConfig) {
ConfigValidationUtils.validateMetadataConfig((MetadataReportConfig) config);
} else if (config instanceof ProviderConfig) {
ConfigValidationUtils.validateProviderConfig((ProviderConfig) config);
} else if (config instanceof ConsumerConfig) {
ConfigValidationUtils.validateConsumerConfig((ConsumerConfig) config);
} else if (config instanceof ApplicationConfig) {
ConfigValidationUtils.validateApplicationConfig((ApplicationConfig) config);
} else if (config instanceof MonitorConfig) {
ConfigValidationUtils.validateMonitorConfig((MonitorConfig) config);
} else if (config instanceof ModuleConfig) {
ConfigValidationUtils.validateModuleConfig((ModuleConfig) config);
} else if (config instanceof MetricsConfig) {
ConfigValidationUtils.validateMetricsConfig((MetricsConfig) config);
} else if (config instanceof SslConfig) {
ConfigValidationUtils.validateSslConfig((SslConfig) config);
}
}
private <T extends AbstractConfig> boolean shouldAddDefaultConfig(Class<T> clazz) {
return configManager.getDefaultConfigs(clazz).isEmpty();
}
private void startConfigCenter() {
// load application config
loadConfigs(ApplicationConfig.class);
// load config centers
loadConfigs(ConfigCenterConfig.class);
useRegistryAsConfigCenterIfNecessary();
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
// check Config Center
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
if (CollectionUtils.isEmpty(configCenters)) {
ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
configCenterConfig.refresh();
ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
if (configCenterConfig.isValid()) {
configManager.addConfigCenter(configCenterConfig);
configCenters = configManager.getConfigCenters();
@ -627,10 +708,16 @@ public class DubboBootstrap {
if (CollectionUtils.isNotEmpty(configCenters)) {
CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
for (ConfigCenterConfig configCenter : configCenters) {
// Pass config from ConfigCenterBean to environment
environment.updateExternalConfigMap(configCenter.getExternalConfiguration());
environment.updateAppExternalConfigMap(configCenter.getAppExternalConfiguration());
// Fetch config from remote config center
compositeDynamicConfiguration.addConfiguration(prepareEnvironment(configCenter));
}
environment.setDynamicConfiguration(compositeDynamicConfiguration);
}
configManager.refreshAll();
}
@ -674,12 +761,19 @@ public class DubboBootstrap {
return;
}
configManager
.getDefaultRegistries()
.stream()
.filter(this::isUsedRegistryAsConfigCenter)
.map(this::registryAsConfigCenter)
.forEach(configManager::addConfigCenter);
// load registry
loadConfigs(RegistryConfig.class);
List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
if (defaultRegistries.size() > 0) {
defaultRegistries
.stream()
.filter(this::isUsedRegistryAsConfigCenter)
.map(this::registryAsConfigCenter)
.forEach(configManager::addConfigCenter);
logger.info("use registry as config-center: " + configManager.getConfigCenters());
}
}
private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
@ -724,13 +818,16 @@ public class DubboBootstrap {
return;
}
configManager
.getDefaultRegistries()
.stream()
.filter(this::isUsedRegistryAsMetadataCenter)
.map(this::registryAsMetadataCenter)
.forEach(configManager::addMetadataReport);
List<RegistryConfig> defaultRegistries = configManager.getDefaultRegistries();
if (defaultRegistries.size() > 0) {
defaultRegistries
.stream()
.filter(this::isUsedRegistryAsMetadataCenter)
.map(this::registryAsMetadataCenter)
.forEach(configManager::addMetadataReport);
logger.info("use registry as metadata-center: " + configManager.getMetadataConfigs());
}
}
private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
@ -831,40 +928,120 @@ public class DubboBootstrap {
return metadataAddressBuilder.toString();
}
private void loadRemoteConfigs() {
// registry ids to registry configs
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Set<String> registryIds = configManager.getRegistryIds();
registryIds.forEach(id -> {
if (tmpRegistries.stream().noneMatch(reg -> reg.getId().equals(id))) {
tmpRegistries.add(configManager.getRegistry(id).orElseGet(() -> {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setId(id);
registryConfig.refresh();
return registryConfig;
}));
}
});
private void loadConfigsFromProps() {
configManager.addRegistries(tmpRegistries);
// application config has load before starting config center
// load dubbo.applications.xxx
loadConfigs(ApplicationConfig.class);
// protocol ids to protocol configs
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
Set<String> protocolIds = configManager.getProtocolIds();
protocolIds.forEach(id -> {
if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
tmpProtocols.add(configManager.getProtocol(id).orElseGet(() -> {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setId(id);
protocolConfig.refresh();
return protocolConfig;
}));
}
});
// load dubbo.modules.xxx
loadConfigs(ModuleConfig.class);
// load dubbo.monitors.xxx
loadConfigs(MonitorConfig.class);
// load dubbo.metricses.xxx
loadConfigs(MetricsConfig.class);
// load multiple config types:
// load dubbo.protocols.xxx
loadConfigs(ProtocolConfig.class);
// load dubbo.registries.xxx
loadConfigs(RegistryConfig.class);
// load dubbo.providers.xxx
loadConfigs(ProviderConfig.class);
// load dubbo.consumers.xxx
loadConfigs(ConsumerConfig.class);
// load dubbo.metadata-report.xxx
loadConfigs(MetadataReportConfig.class);
// config centers has bean loaded before starting config center
//loadConfigs(ConfigCenterConfig.class);
configManager.addProtocols(tmpProtocols);
}
private <T extends AbstractConfig> void loadConfigs(Class<T> cls) {
// load multiple configs with id
Set<String> configIds = this.getConfigIds(cls);
configIds.forEach(id -> {
if (!configManager.getConfig(cls, id).isPresent()) {
T config = null;
try {
config = cls.newInstance();
config.setId(id);
} catch (Exception e) {
throw new IllegalStateException("create config instance failed, id: " + id + ", type:" + cls.getSimpleName());
}
String key = null;
boolean addDefaultNameConfig = false;
try {
// add default name config (same as id), e.g. dubbo.protocols.rest.port=1234
key = DUBBO + "." + AbstractConfig.getPluralTagName(cls) + "." + id + ".name";
if (ConfigUtils.getProperties().getProperty(key) == null) {
ConfigUtils.getProperties().setProperty(key, id);
addDefaultNameConfig = true;
}
config.refresh();
configManager.addConfig(config);
} catch (Exception e) {
logger.error("load config failed, id: " + id + ", type:" + cls.getSimpleName(), e);
throw new IllegalStateException("load config failed, id: " + id + ", type:" + cls.getSimpleName());
} finally {
if (addDefaultNameConfig && key != null) {
ConfigUtils.getProperties().remove(key);
}
}
}
});
// If none config of the type, try load single config
if (configManager.getConfigs(cls).isEmpty()) {
// load single config
Environment env = ApplicationModel.getEnvironment();
List<Map<String, String>> configurationMaps = env.getConfigurationMaps();
if (ConfigurationUtils.hasSubProperties(configurationMaps, AbstractConfig.getTypePrefix(cls))) {
T config = null;
try {
config = cls.newInstance();
config.refresh();
} catch (Exception e) {
throw new IllegalStateException("create default config instance failed, type:" + cls.getSimpleName());
}
configManager.addConfig(config);
}
}
}
/**
* Search props and extract config ids of specify type.
* <pre>
* # properties
* dubbo.registries.registry1.address=xxx
* dubbo.registries.registry2.port=xxx
*
* # extract
* Set configIds = getConfigIds(RegistryConfig.class)
*
* # result
* configIds: ["registry1", "registry2"]
* </pre>
*
* @param clazz config type
* @return ids of specify config type
*/
private Set<String> getConfigIds(Class<? extends AbstractConfig> clazz) {
String prefix = CommonConstants.DUBBO + "." + AbstractConfig.getPluralTagName(clazz) + ".";
Environment environment = ApplicationModel.getEnvironment();
return ConfigurationUtils.getSubIds(environment.getConfigurationMaps(), prefix);
}
/**
* Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
@ -881,6 +1058,10 @@ public class DubboBootstrap {
public DubboBootstrap start() {
if (started.compareAndSet(false, true)) {
startup.set(false);
initialized.set(false);
shutdown.set(false);
awaited.set(false);
initialize();
if (logger.isInfoEnabled()) {
logger.info(NAME + " is starting...");
@ -908,16 +1089,14 @@ public class DubboBootstrap {
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
onStart();
}).start();
} else {
startup.set(true);
if (logger.isInfoEnabled()) {
logger.info(NAME + " is ready.");
}
ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
onStart();
}
if (logger.isInfoEnabled()) {
logger.info(NAME + " has started.");
@ -1040,9 +1219,8 @@ public class DubboBootstrap {
);
}
try {
environment.setConfigCenterFirst(configCenter.isHighestPriority());
environment.updateExternalConfigurationMap(parseProperties(configContent));
environment.updateAppExternalConfigurationMap(parseProperties(appConfigContent));
environment.updateExternalConfigMap(parseProperties(configContent));
environment.updateAppExternalConfigMap(parseProperties(appConfigContent));
} catch (IOException e) {
throw new IllegalStateException("Failed to parse configurations from Config Center.", e);
}
@ -1065,10 +1243,13 @@ public class DubboBootstrap {
}
private void exportServices() {
configManager.getServices().forEach(sc -> {
for (ServiceConfigBase sc : configManager.getServices()) {
// TODO, compatible with ServiceConfig.export()
ServiceConfig serviceConfig = (ServiceConfig) sc;
serviceConfig.setBootstrap(this);
if (!serviceConfig.isRefreshed()) {
serviceConfig.refresh();
}
if (exportAsync) {
ExecutorService executor = executorRepository.getServiceExporterExecutor();
@ -1085,7 +1266,7 @@ public class DubboBootstrap {
sc.export();
exportedServices.add(sc);
}
});
}
}
private void unexportServices() {
@ -1112,6 +1293,9 @@ public class DubboBootstrap {
// TODO, compatible with ReferenceConfig.refer()
ReferenceConfig referenceConfig = (ReferenceConfig) rc;
referenceConfig.setBootstrap(this);
if (!referenceConfig.isRefreshed()) {
referenceConfig.refresh();
}
if (rc.shouldInit()) {
if (referAsync) {
@ -1212,32 +1396,58 @@ public class DubboBootstrap {
if (destroyLock.tryLock()
&& shutdown.compareAndSet(false, true)) {
try {
DubboShutdownHook.destroyAll();
if (started.compareAndSet(true, false)
&& destroyed.compareAndSet(false, true)) {
unregisterServiceInstance();
unexportMetadataService();
unexportServices();
unreferServices();
if (destroyed.compareAndSet(false, true)) {
if (started.compareAndSet(true, false)) {
unregisterServiceInstance();
unexportMetadataService();
unexportServices();
unreferServices();
}
destroyRegistries();
destroyProtocols();
destroyServiceDiscoveries();
destroyExecutorRepository();
destroyMetadataReports();
// check config
checkConfigState();
clear();
shutdown();
release();
ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(this));
onStop();
}
destroyDynamicConfigurations();
ShutdownHookCallbacks.INSTANCE.clear();
} finally {
initialized.set(false);
startup.set(false);
destroyLock.unlock();
}
}
}
private void onStart() {
ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
exts.getSupportedExtensionInstances().forEach(ext -> ext.onStart(this));
}
private void onStop() {
ExtensionLoader<DubboBootstrapStartStopListener> exts = getExtensionLoader(DubboBootstrapStartStopListener.class);
exts.getSupportedExtensionInstances().forEach(ext -> ext.onStop(this));
}
private void checkConfigState() {
// config manager should not be cleared at this moment
if (!ignoreConfigState && !configManager.getApplication().isPresent()) {
logger.error("Dubbo config was cleaned prematurely");
throw new IllegalStateException("Dubbo config was cleaned prematurely");
}
}
private void destroyExecutorRepository() {
ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension().destroyAll();
}
@ -1246,6 +1456,23 @@ public class DubboBootstrap {
AbstractRegistryFactory.destroyAll();
}
/**
* Destroy all the protocols.
*/
private void destroyProtocols() {
ExtensionLoader<Protocol> loader = ExtensionLoader.getExtensionLoader(Protocol.class);
for (String protocolName : loader.getLoadedExtensions()) {
try {
Protocol protocol = loader.getLoadedExtension(protocolName);
if (protocol != null) {
protocol.destroy();
}
} catch (Throwable t) {
logger.warn(t.getMessage(), t);
}
}
}
private void destroyServiceDiscoveries() {
getServiceDiscoveries().forEach(serviceDiscovery -> {
execute(serviceDiscovery::destroy);
@ -1255,6 +1482,17 @@ public class DubboBootstrap {
}
}
private void destroyMetadataReports() {
AbstractMetadataReportFactory.destroy();
ExtensionLoader.resetExtensionLoader(MetadataReportFactory.class);
}
private void destroyDynamicConfigurations() {
// DynamicConfiguration may be cached somewhere, and maybe used during destroy
// destroy them may cause some troubles, so just clear instances cache
ExtensionLoader.resetExtensionLoader(DynamicConfigurationFactory.class);
}
private void clear() {
clearConfigs();
clearApplicationModel();
@ -1278,6 +1516,11 @@ public class DubboBootstrap {
logger.info(NAME + " is about to shutdown...");
}
condition.signalAll();
// sleep
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
}
});
}
@ -1299,68 +1542,7 @@ public class DubboBootstrap {
}
public ApplicationConfig getApplication() {
ApplicationConfig application = configManager
.getApplication()
.orElseGet(() -> {
ApplicationConfig applicationConfig = new ApplicationConfig();
configManager.setApplication(applicationConfig);
return applicationConfig;
});
if (!application.isRefreshed()) {
application.refresh();
}
return application;
return configManager.getApplicationOrElseThrow();
}
private MonitorConfig getMonitor() {
MonitorConfig monitor = configManager
.getMonitor()
.orElseGet(() -> {
MonitorConfig monitorConfig = new MonitorConfig();
configManager.setMonitor(monitorConfig);
return monitorConfig;
});
monitor.refresh();
return monitor;
}
private MetricsConfig getMetrics() {
MetricsConfig metrics = configManager
.getMetrics()
.orElseGet(() -> {
MetricsConfig metricsConfig = new MetricsConfig();
configManager.setMetrics(metricsConfig);
return metricsConfig;
});
metrics.refresh();
return metrics;
}
private ModuleConfig getModule() {
ModuleConfig module = configManager
.getModule()
.orElseGet(() -> {
ModuleConfig moduleConfig = new ModuleConfig();
configManager.setModule(moduleConfig);
return moduleConfig;
});
module.refresh();
return module;
}
private SslConfig getSsl() {
SslConfig ssl = configManager
.getSsl()
.orElseGet(() -> {
SslConfig sslConfig = new SslConfig();
configManager.setSsl(sslConfig);
return sslConfig;
});
ssl.refresh();
return ssl;
}
}

View File

@ -34,18 +34,12 @@ public abstract class AbstractBuilder<C extends AbstractConfig, B extends Abstra
* The config id
*/
protected String id;
protected String prefix;
public B id(String id) {
this.id = id;
return getThis();
}
protected B prefix(String prefix) {
this.prefix = prefix;
return getThis();
}
protected abstract B getThis();
protected static Map<String, String> appendParameter(Map<String, String> parameters, String key, String value) {
@ -68,9 +62,6 @@ public abstract class AbstractBuilder<C extends AbstractConfig, B extends Abstra
if (!StringUtils.isEmpty(id)) {
instance.setId(id);
}
if (!StringUtils.isEmpty(prefix)) {
instance.setPrefix(prefix);
}
}
/**

View File

@ -17,13 +17,16 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.api.Greeting;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.lang.annotation.ElementType;
@ -31,8 +34,10 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@ -42,6 +47,16 @@ import static org.junit.jupiter.api.Assertions.fail;
public class AbstractConfigTest {
@BeforeEach
public void beforeEach() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
//FIXME
/*@Test
public void testAppendProperties1() throws Exception {
@ -156,20 +171,21 @@ public class AbstractConfigTest {
@Test
public void testAppendAttributes1() throws Exception {
Map<String, Object> parameters = new HashMap<String, Object>();
AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01), "prefix");
Assertions.assertEquals('l', parameters.get("prefix.let"));
Assertions.assertEquals(true, parameters.get("prefix.activate"));
Assertions.assertFalse(parameters.containsKey("prefix.flag"));
}
ParameterConfig config = new ParameterConfig(1, "hello/world", 30, "password");
Map<String, String> parameters = new HashMap<>();
AbstractConfig.appendParameters(parameters, config);
@Test
public void testAppendAttributes2() throws Exception {
Map<String, Object> parameters = new HashMap<String, Object>();
AbstractConfig.appendAttributes(parameters, new AttributeConfig('l', true, (byte) 0x01));
Assertions.assertEquals('l', parameters.get("let"));
Assertions.assertEquals(true, parameters.get("activate"));
Assertions.assertFalse(parameters.containsKey("flag"));
Map<String, String> attributes = new HashMap<>();
AbstractConfig.appendAttributes(attributes, config);
Assertions.assertEquals(null, parameters.get("secret"));
Assertions.assertEquals(null, parameters.get("parameters"));
// secret is excluded for url parameters, but keep for attributes
Assertions.assertEquals(config.getSecret(), attributes.get("secret"));
Assertions.assertEquals(config.getName(), attributes.get("name"));
Assertions.assertEquals(""+config.getNumber(), attributes.get("number"));
Assertions.assertEquals(""+config.getAge(), attributes.get("age"));
Assertions.assertEquals(StringUtils.encodeParameters(config.getParameters()), attributes.get("parameters"));
}
@Test
@ -313,14 +329,14 @@ public class AbstractConfigTest {
external.put("dubbo.override.key", "external");
// @Parameter(key="key2", useKeyAsProperty=true)
external.put("dubbo.override.key2", "external");
ApplicationModel.getEnvironment().setExternalConfigMap(external);
ApplicationModel.getEnvironment().initialize();
ApplicationModel.getEnvironment().setExternalConfigMap(external);
System.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
System.setProperty("dubbo.override.protocol", "system");
SysProps.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
SysProps.setProperty("dubbo.override.protocol", "system");
// this will not override, use 'key' instead, @Parameter(key="key1", useKeyAsProperty=false)
System.setProperty("dubbo.override.key1", "system");
System.setProperty("dubbo.override.key2", "system");
SysProps.setProperty("dubbo.override.key1", "system");
SysProps.setProperty("dubbo.override.key2", "system");
// Load configuration from system properties -> externalConfiguration -> RegistryConfig -> dubbo.properties
overrideConfig.refresh();
@ -329,13 +345,10 @@ public class AbstractConfigTest {
Assertions.assertEquals("system", overrideConfig.getProtocol());
Assertions.assertEquals("override-config://", overrideConfig.getEscape());
Assertions.assertEquals("external", overrideConfig.getKey());
Assertions.assertEquals("system", overrideConfig.getUseKeyAsProperty());
Assertions.assertEquals("system", overrideConfig.getKey2());
} finally {
System.clearProperty("dubbo.override.address");
System.clearProperty("dubbo.override.protocol");
System.clearProperty("dubbo.override.key1");
System.clearProperty("dubbo.override.key2");
ApplicationModel.getEnvironment().clearExternalConfigs();
SysProps.clear();
ApplicationModel.getEnvironment().destroy();
}
}
@ -348,9 +361,9 @@ public class AbstractConfigTest {
overrideConfig.setEscape("override-config://");
overrideConfig.setExclude("override-config");
System.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
System.setProperty("dubbo.override.protocol", "system");
System.setProperty("dubbo.override.key", "system");
SysProps.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
SysProps.setProperty("dubbo.override.protocol", "system");
SysProps.setProperty("dubbo.override.key", "system");
overrideConfig.refresh();
@ -359,10 +372,8 @@ public class AbstractConfigTest {
Assertions.assertEquals("override-config://", overrideConfig.getEscape());
Assertions.assertEquals("system", overrideConfig.getKey());
} finally {
System.clearProperty("dubbo.override.address");
System.clearProperty("dubbo.override.protocol");
System.clearProperty("dubbo.override.key1");
ApplicationModel.getEnvironment().clearExternalConfigs();
SysProps.clear();
ApplicationModel.getEnvironment().destroy();
}
}
@ -386,7 +397,7 @@ public class AbstractConfigTest {
Assertions.assertEquals("override-config://", overrideConfig.getEscape());
//Assertions.assertEquals("properties", overrideConfig.getUseKeyAsProperty());
} finally {
ApplicationModel.getEnvironment().clearExternalConfigs();
ApplicationModel.getEnvironment().destroy();
ConfigUtils.setProperties(null);
}
}
@ -410,8 +421,8 @@ public class AbstractConfigTest {
external.put("dubbo.override.key", "external");
// @Parameter(key="key2", useKeyAsProperty=true)
external.put("dubbo.override.key2", "external");
ApplicationModel.getEnvironment().setExternalConfigMap(external);
ApplicationModel.getEnvironment().initialize();
ApplicationModel.getEnvironment().setExternalConfigMap(external);
overrideConfig.refresh();
@ -420,9 +431,9 @@ public class AbstractConfigTest {
Assertions.assertEquals("external://", overrideConfig.getEscape());
Assertions.assertEquals("external", overrideConfig.getExclude());
Assertions.assertEquals("external", overrideConfig.getKey());
Assertions.assertEquals("external", overrideConfig.getUseKeyAsProperty());
Assertions.assertEquals("external", overrideConfig.getKey2());
} finally {
ApplicationModel.getEnvironment().clearExternalConfigs();
ApplicationModel.getEnvironment().destroy();
}
}
@ -437,16 +448,16 @@ public class AbstractConfigTest {
overrideConfig.setExclude("override-config");
Map<String, String> external = new HashMap<>();
external.put("dubbo.override.override-id.address", "external-override-id://127.0.0.1:2181");
external.put("dubbo.overrides.override-id.address", "external-override-id://127.0.0.1:2181");
external.put("dubbo.override.address", "external://127.0.0.1:2181");
// @Parameter(exclude=true)
external.put("dubbo.override.exclude", "external");
// @Parameter(key="key1", useKeyAsProperty=false)
external.put("dubbo.override.key", "external");
external.put("dubbo.overrides.override-id.key", "external");
// @Parameter(key="key2", useKeyAsProperty=true)
external.put("dubbo.override.key2", "external");
ApplicationModel.getEnvironment().setExternalConfigMap(external);
external.put("dubbo.overrides.override-id.key2", "external");
ApplicationModel.getEnvironment().initialize();
ApplicationModel.getEnvironment().setExternalConfigMap(external);
ConfigCenterConfig configCenter = new ConfigCenterConfig();
overrideConfig.setConfigCenter(configCenter);
@ -457,9 +468,9 @@ public class AbstractConfigTest {
Assertions.assertEquals("override-config", overrideConfig.getProtocol());
Assertions.assertEquals("override-config://", overrideConfig.getEscape());
Assertions.assertEquals("external", overrideConfig.getKey());
Assertions.assertEquals("external", overrideConfig.getUseKeyAsProperty());
Assertions.assertEquals("external", overrideConfig.getKey2());
} finally {
ApplicationModel.getEnvironment().clearExternalConfigs();
ApplicationModel.getEnvironment().destroy();
}
}
@ -475,8 +486,8 @@ public class AbstractConfigTest {
Map<String, String> external = new HashMap<>();
external.put("dubbo.override.parameters", "[{key3:value3},{key4:value4},{key2:value5}]");
ApplicationModel.getEnvironment().setExternalConfigMap(external);
ApplicationModel.getEnvironment().initialize();
ApplicationModel.getEnvironment().setExternalConfigMap(external);
ConfigCenterConfig configCenter = new ConfigCenterConfig();
overrideConfig.setConfigCenter(configCenter);
@ -488,14 +499,14 @@ public class AbstractConfigTest {
Assertions.assertEquals("value3", overrideConfig.getParameters().get("key3"));
Assertions.assertEquals("value4", overrideConfig.getParameters().get("key4"));
System.setProperty("dubbo.override.parameters", "[{key3:value6}]");
SysProps.setProperty("dubbo.override.parameters", "[{key3:value6}]");
overrideConfig.refresh();
Assertions.assertEquals("value6", overrideConfig.getParameters().get("key3"));
Assertions.assertEquals("value4", overrideConfig.getParameters().get("key4"));
} finally {
System.clearProperty("dubbo.override.parameters");
ApplicationModel.getEnvironment().clearExternalConfigs();
SysProps.clear();
ApplicationModel.getEnvironment().destroy();
}
}
@ -525,7 +536,7 @@ public class AbstractConfigTest {
Assertions.assertEquals("value-from-config", overrideConfig.getNotConflictKey());
Assertions.assertEquals("value-from-env", overrideConfig.getNotConflictKey2());
} finally {
ApplicationModel.getEnvironment().clearExternalConfigs();
ApplicationModel.getEnvironment().destroy();
}
}
@ -560,12 +571,12 @@ public class AbstractConfigTest {
Assertions.assertEquals(application1, application2);
ProtocolConfig protocol1 = new ProtocolConfig();
protocol1.setHost("127.0.0.1");// excluded
protocol1.setName("dubbo");
protocol1.setPort(1234);
ProtocolConfig protocol2 = new ProtocolConfig();
protocol2.setHost("127.0.0.2");// excluded
protocol2.setName("dubbo");
Assertions.assertEquals(protocol1, protocol2);
protocol2.setPort(1235);
Assertions.assertNotEquals(protocol1, protocol2);
}
@Retention(RetentionPolicy.RUNTIME)
@ -597,7 +608,7 @@ public class AbstractConfigTest {
public String protocol;
public String exclude;
public String key;
public String useKeyAsProperty;
public String key2;
public String escape;
public String notConflictKey;
public String notConflictKey2;
@ -627,7 +638,7 @@ public class AbstractConfigTest {
this.exclude = exclude;
}
@Parameter(key = "key1", useKeyAsProperty = false)
@Parameter(key = "key1")
public String getKey() {
return key;
}
@ -636,13 +647,13 @@ public class AbstractConfigTest {
this.key = key;
}
@Parameter(key = "key2", useKeyAsProperty = true)
public String getUseKeyAsProperty() {
return useKeyAsProperty;
@Parameter(key = "mykey")
public String getKey2() {
return key2;
}
public void setUseKeyAsProperty(String useKeyAsProperty) {
this.useKeyAsProperty = useKeyAsProperty;
public void setKey2(String key2) {
this.key2 = key2;
}
@Parameter(escaped = true)
@ -686,7 +697,7 @@ public class AbstractConfigTest {
}
PropertiesConfig(String id) {
this.id = id;
this.setId(id);
}
public char getC() {
@ -821,44 +832,6 @@ public class AbstractConfigTest {
}
}
private static class AttributeConfig {
private char letter;
private boolean activate;
private byte flag;
public AttributeConfig(char letter, boolean activate, byte flag) {
this.letter = letter;
this.activate = activate;
this.flag = flag;
}
@Parameter(attribute = true, key = "let")
public char getLetter() {
return letter;
}
public void setLetter(char letter) {
this.letter = letter;
}
@Parameter(attribute = true)
public boolean isActivate() {
return activate;
}
public void setActivate(boolean activate) {
this.activate = activate;
}
public byte getFlag() {
return flag;
}
public void setFlag(byte flag) {
this.flag = flag;
}
}
private static class AnnotationConfig extends AbstractConfig {
private Class interfaceClass;
private String filter;
@ -933,4 +906,24 @@ public class AbstractConfigTest {
}
}
}
@Test
public void testMetaData() throws Exception {
// Expect empty metadata for new instance
// Check and set default value of field in checkDefault() method
List<Class<? extends AbstractConfig>> configClasses = Arrays.asList(ApplicationConfig.class,
ConsumerConfig.class, ProviderConfig.class, ReferenceConfig.class, ServiceConfig.class,
ProtocolConfig.class, RegistryConfig.class, ConfigCenterConfig.class, MetadataReportConfig.class,
ModuleConfig.class, SslConfig.class, MetricsConfig.class, MonitorConfig.class, MethodConfig.class);
for (Class<? extends AbstractConfig> configClass : configClasses) {
AbstractConfig config = configClass.newInstance();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata for new instance but found: "+metaData +" of "+configClass.getSimpleName());
System.out.println(configClass.getSimpleName()+" metadata is checked.");
}
}
}

View File

@ -18,13 +18,13 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.config.api.Greeting;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.mock.GreetingLocal1;
import org.apache.dubbo.config.mock.GreetingLocal2;
import org.apache.dubbo.config.mock.GreetingLocal3;
import org.apache.dubbo.config.mock.GreetingMock1;
import org.apache.dubbo.config.mock.GreetingMock2;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
@ -42,85 +42,20 @@ public class AbstractInterfaceConfigTest {
@BeforeAll
public static void setUp(@TempDir Path folder) {
ApplicationModel.reset();
DubboBootstrap.reset();
dubboProperties = folder.resolve(CommonConstants.DUBBO_PROPERTIES_KEY).toFile();
System.setProperty(CommonConstants.DUBBO_PROPERTIES_KEY, dubboProperties.getAbsolutePath());
}
@AfterAll
public static void tearDown() {
ApplicationModel.reset();
DubboBootstrap.reset();
System.clearProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
}
@AfterEach
public void tearMethodAfterEachUT() {
// ApplicationModel.getConfigManager().clear();
}
@Test
public void testCheckRegistry1() {
System.setProperty("dubbo.registry.address", "addr1");
try {
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.setApplication(new ApplicationConfig("testCheckRegistry1"));
interfaceConfig.checkRegistry();
Assertions.assertEquals(1, interfaceConfig.getRegistries().size());
Assertions.assertEquals("addr1", interfaceConfig.getRegistries().get(0).getAddress());
} finally {
System.clearProperty("dubbo.registry.address");
}
}
@Test
public void testCheckRegistry2() {
Assertions.assertThrows(IllegalStateException.class, () -> {
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkRegistry();
});
}
@Test
public void checkInterfaceAndMethods1() {
Assertions.assertThrows(IllegalStateException.class, () -> {
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkInterfaceAndMethods(null, null);
});
}
@Test
public void checkInterfaceAndMethods2() {
Assertions.assertThrows(IllegalStateException.class, () -> {
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkInterfaceAndMethods(AbstractInterfaceConfigTest.class, null);
});
}
@Test
public void checkInterfaceAndMethod3() {
Assertions.assertThrows(IllegalStateException.class, () -> {
MethodConfig methodConfig = new MethodConfig();
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
});
}
@Test
public void checkInterfaceAndMethod4() {
Assertions.assertThrows(IllegalStateException.class, () -> {
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("nihao");
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
});
}
@Test
public void checkInterfaceAndMethod5() {
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("hello");
InterfaceConfig interfaceConfig = new InterfaceConfig();
interfaceConfig.checkInterfaceAndMethods(Greeting.class, Collections.singletonList(methodConfig));
DubboBootstrap.reset();
}
@Test
@ -312,6 +247,7 @@ public class AbstractInterfaceConfigTest {
interfaceConfig.setMonitor("monitor-addr");
Assertions.assertEquals("monitor-addr", interfaceConfig.getMonitor().getAddress());
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setAddress("monitor-addr");
interfaceConfig.setMonitor(monitorConfig);
Assertions.assertSame(monitorConfig, interfaceConfig.getMonitor());
}

View File

@ -17,7 +17,10 @@
package org.apache.dubbo.config;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
@ -37,13 +40,28 @@ import static org.hamcrest.Matchers.sameInstance;
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
public class ApplicationConfigTest {
@BeforeEach
public void beforeEach() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
@Test
public void testName() throws Exception {
ApplicationConfig application = new ApplicationConfig();
application.setName("app");
assertThat(application.getName(), equalTo("app"));
assertThat(application.getId(), equalTo(null));
application = new ApplicationConfig("app2");
assertThat(application.getName(), equalTo("app2"));
assertThat(application.getId(), equalTo(null));
Map<String, String> parameters = new HashMap<String, String>();
ApplicationConfig.appendParameters(parameters, application);
assertThat(parameters, hasEntry(APPLICATION_KEY, "app2"));
@ -185,7 +203,7 @@ public class ApplicationConfigTest {
public void testAppendEnvironmentProperties() {
try {
ApplicationConfig application = new ApplicationConfig("app");
System.setProperty("dubbo.labels", "tag1=value1;tag2=value2 ; tag3 = value3");
SysProps.setProperty("dubbo.labels", "tag1=value1;tag2=value2 ; tag3 = value3");
application.refresh();
Map<String, String> parameters = application.getParameters();
Assertions.assertEquals("value1", parameters.get("tag1"));
@ -193,11 +211,11 @@ public class ApplicationConfigTest {
Assertions.assertEquals("value3", parameters.get("tag3"));
ApplicationConfig application1 = new ApplicationConfig("app");
System.setProperty("dubbo.env.keys", "tag1, tag2,tag3");
SysProps.setProperty("dubbo.env.keys", "tag1, tag2,tag3");
// mock environment variables
System.setProperty("tag1", "value1");
System.setProperty("tag2", "value2");
System.setProperty("tag3", "value3");
SysProps.setProperty("tag1", "value1");
SysProps.setProperty("tag2", "value2");
SysProps.setProperty("tag3", "value3");
application1.refresh();
Map<String, String> parameters1 = application1.getParameters();
Assertions.assertEquals("value1", parameters1.get("tag1"));
@ -210,8 +228,118 @@ public class ApplicationConfigTest {
Assertions.assertEquals("value2", urlParameters.get("tag2"));
Assertions.assertEquals("value3", urlParameters.get("tag3"));
} finally {
System.clearProperty("dubbo.labels");
System.clearProperty("dubbo.keys");
SysProps.clear();
}
}
@Test
public void testMetaData() {
ApplicationConfig config = new ApplicationConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
@Test
public void testOverrideEmptyConfig() {
String owner = "tom1";
SysProps.setProperty("dubbo.application.name", "demo-app");
SysProps.setProperty("dubbo.application.owner", owner);
SysProps.setProperty("dubbo.application.version", "1.2.3");
try {
ApplicationConfig applicationConfig = new ApplicationConfig();
DubboBootstrap.getInstance()
.application(applicationConfig)
.initialize();
Assertions.assertEquals(owner, applicationConfig.getOwner());
Assertions.assertEquals("1.2.3", applicationConfig.getVersion());
} finally {
}
}
@Test
public void testOverrideConfigById() {
String owner = "tom2";
SysProps.setProperty("dubbo.applications.demo-app.owner", owner);
SysProps.setProperty("dubbo.applications.demo-app.version", "1.2.3");
SysProps.setProperty("dubbo.applications.demo-app.name", "demo-app");
try {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setId("demo-app");
DubboBootstrap.getInstance()
.application(applicationConfig)
.initialize();
Assertions.assertEquals("demo-app", applicationConfig.getId());
Assertions.assertEquals("demo-app", applicationConfig.getName());
Assertions.assertEquals(owner, applicationConfig.getOwner());
Assertions.assertEquals("1.2.3", applicationConfig.getVersion());
} finally {
}
}
@Test
public void testOverrideConfigByName() {
String owner = "tom3";
SysProps.setProperty("dubbo.applications.demo-app.owner", owner);
SysProps.setProperty("dubbo.applications.demo-app.version", "1.2.3");
try {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-app");
DubboBootstrap.getInstance()
.application(applicationConfig)
.initialize();
Assertions.assertEquals(owner, applicationConfig.getOwner());
Assertions.assertEquals("1.2.3", applicationConfig.getVersion());
} finally {
}
}
@Test
public void testLoadConfig() {
String owner = "tom4";
SysProps.setProperty("dubbo.applications.demo-app.owner", owner);
SysProps.setProperty("dubbo.applications.demo-app.version", "1.2.3");
try {
DubboBootstrap.getInstance()
.initialize();
ApplicationConfig applicationConfig = DubboBootstrap.getInstance().getApplication();
Assertions.assertEquals("demo-app", applicationConfig.getId());
Assertions.assertEquals("demo-app", applicationConfig.getName());
Assertions.assertEquals(owner, applicationConfig.getOwner());
Assertions.assertEquals("1.2.3", applicationConfig.getVersion());
} finally {
}
}
@Test
public void testOverrideConfigConvertCase() {
SysProps.setProperty("dubbo.application.NAME", "demo-app");
SysProps.setProperty("dubbo.application.qos-Enable", "false");
SysProps.setProperty("dubbo.application.qos_host", "127.0.0.1");
SysProps.setProperty("dubbo.application.qosPort", "2345");
try {
DubboBootstrap.getInstance()
.initialize();
ApplicationConfig applicationConfig = DubboBootstrap.getInstance().getApplication();
Assertions.assertEquals(false, applicationConfig.getQosEnable());
Assertions.assertEquals("127.0.0.1", applicationConfig.getQosHost());
Assertions.assertEquals(2345, applicationConfig.getQosPort());
Assertions.assertEquals("demo-app", applicationConfig.getName());
} finally {
}
}
}

View File

@ -18,14 +18,43 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
public class ConfigCenterConfigTest {
@BeforeEach
public void setUp() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
@Test
public void testPrefix() {
ConfigCenterConfig config = new ConfigCenterConfig();
Assertions.assertEquals("dubbo.config-center", config.getPrefix());
Assertions.assertEquals(Arrays.asList("dubbo.config-center"), config.getPrefixes());
config.setId("configcenterA");
Assertions.assertEquals(Arrays.asList("dubbo.config-centers.configcenterA", "dubbo.config-center"),
config.getPrefixes());
}
@Test
@ -34,11 +63,226 @@ public class ConfigCenterConfigTest {
config.setNamespace("namespace");
config.setGroup("group");
config.setAddress("zookeeper://127.0.0.1:2181");
config.setHighestPriority(null);
config.refresh();
Assertions.assertEquals("zookeeper://127.0.0.1:2181/ConfigCenterConfig?check=true&" +
"config-file=dubbo.properties&group=group&highest-priority=true&" +
"config-file=dubbo.properties&group=group&" +
"namespace=namespace&timeout=3000",
config.toUrl().toFullString()
);
}
@Test
public void testOverrideConfig() {
String zkAddr = "zookeeper://127.0.0.1:2181";
// sysprops has no id
SysProps.setProperty("dubbo.config-center.check", "false");
SysProps.setProperty("dubbo.config-center.address", zkAddr);
try {
//No id and no address
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setAddress("N/A");
try {
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.initialize();
} catch (Exception e) {
e.printStackTrace();
}
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(zkAddr, configCenter.getAddress());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfig2() {
String zkAddr = "nacos://127.0.0.1:8848";
// sysprops has no id
SysProps.setProperty("dubbo.config-center.check", "false");
SysProps.setProperty("dubbo.config-center.address", zkAddr);
try {
//No id but has address
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setAddress("zookeeper://127.0.0.1:2181");
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.start();
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(zkAddr, configCenter.getAddress());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigBySystemProps() {
//Config instance has Id, but sysprops without id
SysProps.setProperty("dubbo.config-center.check", "false");
SysProps.setProperty("dubbo.config-center.timeout", "1234");
try {
// Config instance has id
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setTimeout(3000L);
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.initialize();
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(1234, configCenter.getTimeout());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigByDubboProps() {
// Config instance has id, dubbo props has no id
Map props = new HashMap();
props.put("dubbo.config-center.check", "false");
props.put("dubbo.config-center.timeout", "1234");
ConfigUtils.getProperties().putAll(props);
try {
// Config instance has id
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setTimeout(3000L);
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.initialize();
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(3000L, configCenter.getTimeout());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
props.keySet().forEach(ConfigUtils.getProperties()::remove);
}
}
@Test
public void testOverrideConfigBySystemPropsWithId() {
// Both config instance and sysprops have id
SysProps.setProperty("dubbo.config-centers.configcenterA.check", "false");
SysProps.setProperty("dubbo.config-centers.configcenterA.timeout", "1234");
try {
// Config instance has id
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setId("configcenterA");
configCenter.setTimeout(3000L);
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.start();
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(1234, configCenter.getTimeout());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigByDubboPropsWithId() {
// Config instance has id, dubbo props has id
Map props = new HashMap();
props.put("dubbo.config-centers.configcenterA.check", "false");
props.put("dubbo.config-centers.configcenterA.timeout", "1234");
ConfigUtils.getProperties().putAll(props);
try {
// Config instance has id
ConfigCenterConfig configCenter = new ConfigCenterConfig();
configCenter.setId("configcenterA");
configCenter.setTimeout(3000L);
DubboBootstrap.getInstance()
.application("demo-app")
.configCenter(configCenter)
.start();
Collection<ConfigCenterConfig> configCenters = ApplicationModel.getConfigManager().getConfigCenters();
Assertions.assertEquals(1, configCenters.size());
Assertions.assertEquals(configCenter, configCenters.iterator().next());
Assertions.assertEquals(3000L, configCenter.getTimeout());
Assertions.assertEquals(false, configCenter.isCheck());
} finally {
props.keySet().forEach(ConfigUtils.getProperties()::remove);
}
}
@Test
public void testMetaData() {
ConfigCenterConfig configCenter = new ConfigCenterConfig();
Map<String, String> metaData = configCenter.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
@Test
public void testParameters() {
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setParameters(new LinkedHashMap<>());
cc.getParameters().put(CLIENT_KEY, null);
Map<String, String> params = new LinkedHashMap<>();
ConfigCenterConfig.appendParameters(params, cc);
Map<String, String> attributes = new LinkedHashMap<>();
ConfigCenterConfig.appendAttributes(attributes, cc);
String encodedParametersStr = attributes.get("parameters");
Assertions.assertEquals("[]", encodedParametersStr);
Assertions.assertEquals(0, StringUtils.parseParameters(encodedParametersStr).size());
}
@Test
public void testAttributes() {
ConfigCenterConfig cc = new ConfigCenterConfig();
cc.setAddress("zookeeper://127.0.0.1:2181");
Map<String, String> attributes = new LinkedHashMap<>();
ConfigCenterConfig.appendAttributes(attributes, cc);
Assertions.assertEquals(cc.getAddress(), attributes.get("address"));
Assertions.assertEquals(cc.getProtocol(), attributes.get("protocol"));
Assertions.assertEquals(""+cc.getPort(), attributes.get("port"));
Assertions.assertEquals(null, attributes.get("valid"));
Assertions.assertEquals(null, attributes.get("refreshed"));
}
}

View File

@ -17,13 +17,35 @@
package org.apache.dubbo.config;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
public class ConsumerConfigTest {
@BeforeEach
public void setUp() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
@Test
public void testTimeout() throws Exception {
try {
@ -78,4 +100,160 @@ public class ConsumerConfigTest {
consumer.setQueues(5);
assertThat(consumer.getQueues(), equalTo(5));
}
@Test
public void testOverrideConfigSingle() {
SysProps.setProperty("dubbo.consumer.check", "false");
SysProps.setProperty("dubbo.consumer.group", "demo");
SysProps.setProperty("dubbo.consumer.threads", "10");
try {
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setGroup("groupA");
consumerConfig.setThreads(20);
consumerConfig.setCheck(true);
DubboBootstrap.getInstance()
.application("demo-app")
.consumer(consumerConfig)
.initialize();
Collection<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
Assertions.assertEquals("demo", consumerConfig.getGroup());
Assertions.assertEquals(10, consumerConfig.getThreads());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigByPluralityId() {
SysProps.setProperty("dubbo.consumer.group", "demoA"); //ignore
SysProps.setProperty("dubbo.consumers.consumerA.check", "false");
SysProps.setProperty("dubbo.consumers.consumerA.group", "demoB");
SysProps.setProperty("dubbo.consumers.consumerA.threads", "10");
try {
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setId("consumerA");
consumerConfig.setGroup("groupA");
consumerConfig.setThreads(20);
consumerConfig.setCheck(true);
DubboBootstrap.getInstance()
.application("demo-app")
.consumer(consumerConfig)
.initialize();
Collection<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
Assertions.assertEquals("demoB", consumerConfig.getGroup());
Assertions.assertEquals(10, consumerConfig.getThreads());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigBySingularId() {
// override success
SysProps.setProperty("dubbo.consumer.group", "demoA");
SysProps.setProperty("dubbo.consumer.threads", "15");
// ignore singular format: dubbo.{tag-name}.{config-id}.{config-item}={config-value}
SysProps.setProperty("dubbo.consumer.consumerA.check", "false");
SysProps.setProperty("dubbo.consumer.consumerA.group", "demoB");
SysProps.setProperty("dubbo.consumer.consumerA.threads", "10");
try {
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setId("consumerA");
consumerConfig.setGroup("groupA");
consumerConfig.setThreads(20);
consumerConfig.setCheck(true);
DubboBootstrap.getInstance()
.application("demo-app")
.consumer(consumerConfig)
.initialize();
Collection<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(true, consumerConfig.isCheck());
Assertions.assertEquals("demoA", consumerConfig.getGroup());
Assertions.assertEquals(15, consumerConfig.getThreads());
} finally {
SysProps.clear();
}
}
@Test
public void testOverrideConfigByDubboProps() {
Map props = new HashMap();
props.put("dubbo.consumers.consumerA.check", "false");
props.put("dubbo.consumers.consumerA.group", "demo");
props.put("dubbo.consumers.consumerA.threads", "10");
ConfigUtils.getProperties().putAll(props);
try {
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setId("consumerA");
//
consumerConfig.setGroup("groupA");
DubboBootstrap.getInstance()
.application("demo-app")
.consumer(consumerConfig)
.initialize();
Collection<ConsumerConfig> consumers = ApplicationModel.getConfigManager().getConsumers();
Assertions.assertEquals(1, consumers.size());
Assertions.assertEquals(consumerConfig, consumers.iterator().next());
Assertions.assertEquals(false, consumerConfig.isCheck());
Assertions.assertEquals("groupA", consumerConfig.getGroup());
Assertions.assertEquals(10, consumerConfig.getThreads());
} finally {
props.keySet().forEach(ConfigUtils.getProperties()::remove);
}
}
@Test
public void testReferenceAndConsumerConfigOverlay() {
SysProps.setProperty("dubbo.consumer.group", "demo");
SysProps.setProperty("dubbo.consumer.threads", "12");
SysProps.setProperty("dubbo.consumer.timeout", "1234");
SysProps.setProperty("dubbo.consumer.init", "false");
SysProps.setProperty("dubbo.consumer.check", "false");
SysProps.setProperty("dubbo.registry.address", "N/A");
try {
ReferenceConfig referenceConfig = new ReferenceConfig();
referenceConfig.setInterface(DemoService.class);
DubboBootstrap.getInstance()
.application("demo-app")
.reference(referenceConfig)
.initialize();
Assertions.assertEquals("demo", referenceConfig.getGroup());
Assertions.assertEquals(1234, referenceConfig.getTimeout());
Assertions.assertEquals(false, referenceConfig.isInit());
Assertions.assertEquals(false, referenceConfig.isCheck());
} finally {
}
}
@Test
public void testMetaData() {
ConsumerConfig consumerConfig = new ConsumerConfig();
Map<String, String> metaData = consumerConfig.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
}

View File

@ -21,11 +21,19 @@ import org.apache.dubbo.config.annotation.Argument;
import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -71,6 +79,16 @@ public class MethodConfigTest {
arguments = {@Argument(index = ARGUMENTS_INDEX, callback = ARGUMENTS_CALLBACK, type = ARGUMENTS_TYPE)})})
private String testField;
@BeforeEach
public void beforeEach() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
//TODO remove this test
@Test
public void testStaticConstructor() throws NoSuchFieldException {
@ -161,14 +179,14 @@ public class MethodConfigTest {
assertThat(method.getSticky(), is(true));
}
@Test
//@Test
public void testOnreturn() throws Exception {
MethodConfig method = new MethodConfig();
method.setOnreturn("on-return-object");
assertThat(method.getOnreturn(), equalTo((Object) "on-return-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_RETURN_INSTANCE_KEY, (Object) "on-return-object"));
assertThat(method.getOnreturn(), equalTo("on-return-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry(ON_RETURN_INSTANCE_KEY, "on-return-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -179,22 +197,22 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOnreturnMethod("on-return-method");
assertThat(method.getOnreturnMethod(), equalTo("on-return-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_RETURN_METHOD_KEY, (Object) "on-return-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_RETURN_METHOD_KEY, (Object) "on-return-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
}
@Test
//@Test
public void testOnthrow() throws Exception {
MethodConfig method = new MethodConfig();
method.setOnthrow("on-throw-object");
assertThat(method.getOnthrow(), equalTo((Object) "on-throw-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_THROW_INSTANCE_KEY, (Object) "on-throw-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_THROW_INSTANCE_KEY, (Object) "on-throw-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -205,22 +223,22 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOnthrowMethod("on-throw-method");
assertThat(method.getOnthrowMethod(), equalTo("on-throw-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_THROW_METHOD_KEY, (Object) "on-throw-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_THROW_METHOD_KEY, (Object) "on-throw-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
}
@Test
//@Test
public void testOninvoke() throws Exception {
MethodConfig method = new MethodConfig();
method.setOninvoke("on-invoke-object");
assertThat(method.getOninvoke(), equalTo((Object) "on-invoke-object"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_INVOKE_INSTANCE_KEY, (Object) "on-invoke-object"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -231,9 +249,9 @@ public class MethodConfigTest {
MethodConfig method = new MethodConfig();
method.setOninvokeMethod("on-invoke-method");
assertThat(method.getOninvokeMethod(), equalTo("on-invoke-method"));
Map<String, Object> attribute = new HashMap<String, Object>();
MethodConfig.appendAttributes(attribute, method);
assertThat(attribute, hasEntry((Object) ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method"));
Map<String, String> attributes = new HashMap<>();
MethodConfig.appendAttributes(attributes, method);
assertThat(attributes, hasEntry((Object) ON_INVOKE_METHOD_KEY, (Object) "on-invoke-method"));
Map<String, String> parameters = new HashMap<String, String>();
MethodConfig.appendParameters(parameters, method);
assertThat(parameters.size(), is(0));
@ -245,4 +263,83 @@ public class MethodConfigTest {
method.setReturn(true);
assertThat(method.isReturn(), is(true));
}
@Test
public void testOverrideMethodConfig() {
String interfaceName = DemoService.class.getName();
SysProps.setProperty("dubbo.reference."+ interfaceName +".sayName.timeout", "1234");
SysProps.setProperty("dubbo.reference."+ interfaceName +".sayName.sticky", "true");
SysProps.setProperty("dubbo.reference."+ interfaceName +".sayName.parameters", "[{a:1},{b:2}]");
SysProps.setProperty("dubbo.reference."+ interfaceName +".init", "false");
try {
ReferenceConfig referenceConfig = new ReferenceConfig();
referenceConfig.setInterface(interfaceName);
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("sayName");
methodConfig.setTimeout(1000);
referenceConfig.setMethods(Arrays.asList(methodConfig));
DubboBootstrap.getInstance()
.application("demo-app")
.reference(referenceConfig)
.initialize();
Map<String, String> params = new LinkedHashMap<>();
params.put("a", "1");
params.put("b", "2");
Assertions.assertEquals(1234, methodConfig.getTimeout());
Assertions.assertEquals(true, methodConfig.getSticky());
Assertions.assertEquals(params, methodConfig.getParameters());
Assertions.assertEquals(false, referenceConfig.isInit());
} finally {
}
}
@Test
public void testOverrideMethodConfigOfService() {
String interfaceName = DemoService.class.getName();
SysProps.setProperty("dubbo.service."+ interfaceName +".sayName.timeout", "1234");
SysProps.setProperty("dubbo.service."+ interfaceName +".sayName.sticky", "true");
SysProps.setProperty("dubbo.service."+ interfaceName +".sayName.parameters", "[{a:1},{b:2}]");
SysProps.setProperty("dubbo.service."+ interfaceName +".group", "demo");
SysProps.setProperty("dubbo.registry.address", "N/A");
try {
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(interfaceName);
serviceConfig.setRef(new DemoServiceImpl());
MethodConfig methodConfig = new MethodConfig();
methodConfig.setName("sayName");
methodConfig.setTimeout(1000);
serviceConfig.setMethods(Arrays.asList(methodConfig));
DubboBootstrap.getInstance()
.application("demo-app")
.service(serviceConfig)
.initialize();
Map<String, String> params = new LinkedHashMap<>();
params.put("a", "1");
params.put("b", "2");
Assertions.assertEquals(1234, methodConfig.getTimeout());
Assertions.assertEquals(true, methodConfig.getSticky());
Assertions.assertEquals(params, methodConfig.getParameters());
Assertions.assertEquals("demo", serviceConfig.getGroup());
} finally {
}
}
@Test
public void testMetaData() {
MethodConfig methodConfig = new MethodConfig();
Map<String, String> metaData = methodConfig.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
}

View File

@ -18,6 +18,7 @@
package org.apache.dubbo.config;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collections;
@ -38,7 +39,7 @@ public class ModuleConfigTest {
ModuleConfig module = new ModuleConfig();
module.setName("module-name");
assertThat(module.getName(), equalTo("module-name"));
assertThat(module.getId(), equalTo("module-name"));
assertThat(module.getId(), equalTo(null));
Map<String, String> parameters = new HashMap<String, String>();
ModuleConfig.appendParameters(parameters, module);
assertThat(parameters, hasEntry("module", "module-name"));
@ -101,4 +102,11 @@ public class ModuleConfigTest {
module.setDefault(true);
assertThat(module.isDefault(), is(true));
}
@Test
public void testMetaData() {
MonitorConfig config = new MonitorConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.config;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collections;
@ -104,4 +105,11 @@ public class MonitorConfigTest {
monitor.setInterval("100");
assertThat(monitor.getInterval(), equalTo("100"));
}
@Test
public void testMetaData() {
MonitorConfig config = new MonitorConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
}

View File

@ -17,8 +17,14 @@
package org.apache.dubbo.config;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.context.ConfigManager;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -30,14 +36,25 @@ import static org.hamcrest.Matchers.is;
public class ProtocolConfigTest {
@BeforeEach
public void setUp() {
DubboBootstrap.reset();
}
@AfterEach
public void afterEach() {
SysProps.clear();
}
@Test
public void testName() throws Exception {
ProtocolConfig protocol = new ProtocolConfig();
protocol.setName("name");
String protocolName = "xprotocol";
protocol.setName(protocolName);
Map<String, String> parameters = new HashMap<String, String>();
ProtocolConfig.appendParameters(parameters, protocol);
assertThat(protocol.getName(), equalTo("name"));
assertThat(protocol.getId(), equalTo("name"));
assertThat(protocol.getName(), equalTo(protocolName));
assertThat(protocol.getId(), equalTo(null));
assertThat(parameters.isEmpty(), is(true));
}
@ -201,4 +218,151 @@ public class ProtocolConfigTest {
protocol.setExtension("extension");
assertThat(protocol.getExtension(), equalTo("extension"));
}
@Test
public void testMetaData() {
ProtocolConfig config = new ProtocolConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "actual: "+metaData);
}
@Test
public void testOverrideEmptyConfig() {
//dubbo.protocol.name=rest
//dubbo.protocol.port=1234
SysProps.setProperty("dubbo.protocol.name", "rest");
SysProps.setProperty("dubbo.protocol.port", "1234");
try {
ProtocolConfig protocolConfig = new ProtocolConfig();
DubboBootstrap.getInstance()
.application("test-app")
.protocol(protocolConfig)
.initialize();
Assertions.assertEquals("rest", protocolConfig.getName());
Assertions.assertEquals(1234, protocolConfig.getPort());
} finally {
}
}
@Test
public void testOverrideConfigByName() {
SysProps.setProperty("dubbo.protocols.rest.port", "1234");
try {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("rest");
DubboBootstrap.getInstance()
.application("test-app")
.protocol(protocolConfig)
.initialize();
Assertions.assertEquals("rest", protocolConfig.getName());
Assertions.assertEquals(1234, protocolConfig.getPort());
} finally {
}
}
@Test
public void testOverrideConfigById() {
SysProps.setProperty("dubbo.protocols.rest1.name", "rest");
SysProps.setProperty("dubbo.protocols.rest1.port", "1234");
try {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("xxx");
protocolConfig.setId("rest1");
DubboBootstrap.getInstance()
.application("test-app")
.protocol(protocolConfig)
.initialize();
Assertions.assertEquals("rest", protocolConfig.getName());
Assertions.assertEquals(1234, protocolConfig.getPort());
} finally {
}
}
@Test
public void testCreateConfigFromPropsWithId() {
SysProps.setProperty("dubbo.protocols.rest1.name", "rest");
SysProps.setProperty("dubbo.protocols.rest1.port", "1234");
SysProps.setProperty("dubbo.protocol.name", "dubbo"); // ignore
SysProps.setProperty("dubbo.protocol.port", "2346");
try {
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application("test-app")
.initialize();
ConfigManager configManager = bootstrap.getConfigManager();
Collection<ProtocolConfig> protocols = configManager.getProtocols();
Assertions.assertEquals(1, protocols.size());
ProtocolConfig protocol = configManager.getProtocol("rest1").get();
Assertions.assertEquals("rest", protocol.getName());
Assertions.assertEquals(1234, protocol.getPort());
} finally {
}
}
@Test
public void testCreateConfigFromPropsWithName() {
SysProps.setProperty("dubbo.protocols.rest.port", "1234");
SysProps.setProperty("dubbo.protocol.name", "dubbo"); // ignore
SysProps.setProperty("dubbo.protocol.port", "2346");
try {
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application("test-app")
.initialize();
ConfigManager configManager = bootstrap.getConfigManager();
Collection<ProtocolConfig> protocols = configManager.getProtocols();
Assertions.assertEquals(1, protocols.size());
ProtocolConfig protocol = configManager.getProtocol("rest").get();
Assertions.assertEquals("rest", protocol.getName());
Assertions.assertEquals(1234, protocol.getPort());
} finally {
}
}
@Test
public void testCreateDefaultConfigFromProps() {
SysProps.setProperty("dubbo.protocol.name", "rest");
SysProps.setProperty("dubbo.protocol.port", "2346");
String protocolId = "rest-protocol";
SysProps.setProperty("dubbo.protocol.id", protocolId); // Allow override config id from props
try {
DubboBootstrap bootstrap = DubboBootstrap.getInstance();
bootstrap.application("test-app")
.initialize();
ConfigManager configManager = bootstrap.getConfigManager();
Collection<ProtocolConfig> protocols = configManager.getProtocols();
Assertions.assertEquals(1, protocols.size());
ProtocolConfig protocol = configManager.getProtocol("rest").get();
Assertions.assertEquals("rest", protocol.getName());
Assertions.assertEquals(2346, protocol.getPort());
Assertions.assertEquals(protocolId, protocol.getId());
ProtocolConfig protocolConfig = configManager.getProtocol(protocolId).get();
} finally {
DubboBootstrap.getInstance().stop();
}
}
}

View File

@ -17,6 +17,7 @@
package org.apache.dubbo.config;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.HashMap;
@ -216,4 +217,11 @@ public class ProviderConfigTest {
provider.setWait(10);
assertThat(provider.getWait(), equalTo(10));
}
@Test
public void testMetaData() {
ProtocolConfig config = new ProtocolConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
}

View File

@ -23,8 +23,8 @@ import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.curator.test.TestingServer;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@ -33,6 +33,8 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
@ -43,7 +45,7 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() throws Exception {
ApplicationModel.reset();
DubboBootstrap.reset();
int zkServerPort = NetUtils.getAvailablePort(NetUtils.getRandomPort());
this.zkServer = new TestingServer(zkServerPort, true);
this.zkServer.start();
@ -52,8 +54,8 @@ public class ReferenceConfigTest {
@AfterEach
public void tearDown() throws IOException {
DubboBootstrap.reset();
zkServer.stop();
ApplicationModel.reset();
}
@Test
@ -61,6 +63,7 @@ public class ReferenceConfigTest {
public void testInjvm() throws Exception {
ApplicationConfig application = new ApplicationConfig();
application.setName("test-protocol-random-port");
application.setEnableFileCache(false);
ApplicationModel.getConfigManager().setApplication(application);
RegistryConfig registry = new RegistryConfig();
@ -101,9 +104,10 @@ public class ReferenceConfigTest {
* unit test for dubbo-1765
*/
@Test
public void testReferenceRetry() {
public void test1ReferenceRetry() {
ApplicationConfig application = new ApplicationConfig();
application.setName("test-reference-retry");
application.setEnableFileCache(false);
ApplicationModel.getConfigManager().setApplication(application);
RegistryConfig registry = new RegistryConfig();
@ -149,6 +153,44 @@ public class ReferenceConfigTest {
}
@Test
public void testMetaData() {
ReferenceConfig config = new ReferenceConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
// test merged and override consumer attributes
ConsumerConfig consumerConfig = new ConsumerConfig();
consumerConfig.setAsync(true);
consumerConfig.setActives(10);
config.setConsumer(consumerConfig);
config.setAsync(false);// override
metaData = config.getMetaData();
Assertions.assertEquals(2, metaData.size());
Assertions.assertEquals("" + consumerConfig.getActives(), metaData.get("actives"));
Assertions.assertEquals("" + config.isAsync(), metaData.get("async"));
}
@Test
public void testGetPrefixes() {
ReferenceConfig referenceConfig = new ReferenceConfig();
referenceConfig.setInterface(DemoService.class);
List<String> prefixes = referenceConfig.getPrefixes();
Assertions.assertTrue(prefixes.contains("dubbo.reference." + referenceConfig.getInterface()));
long start = System.currentTimeMillis();
for (int i = 0; i < 1000; i++) {
referenceConfig.getPrefixes();
}
long end = System.currentTimeMillis();
System.out.println("ReferenceConfig get prefixes cost: " + (end - start));
}
@Test
public void testConstructWithReferenceAnnotation() throws NoSuchFieldException {
Reference reference = getClass().getDeclaredField("innerTest").getAnnotation(Reference.class);

View File

@ -17,12 +17,16 @@
package org.apache.dubbo.config;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.UrlUtils;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
@ -38,6 +42,12 @@ import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.not;
public class RegistryConfigTest {
@AfterEach
public void afterEach() {
SysProps.clear();
}
@Test
public void testProtocol() throws Exception {
RegistryConfig registry = new RegistryConfig();
@ -192,6 +202,35 @@ public class RegistryConfigTest {
}
@Test
public void testMetaData() {
RegistryConfig config = new RegistryConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: "+metaData);
}
@Test
public void testOverrideConfigBySystemProps() {
SysProps.setProperty("dubbo.registry.address", "zookeeper://${zookeeper.address}:${zookeeper.port}");
SysProps.setProperty("dubbo.registry.useAsConfigCenter", "false");
SysProps.setProperty("dubbo.registry.useAsMetadataCenter", "false");
SysProps.setProperty("zookeeper.address", "localhost");
SysProps.setProperty("zookeeper.port", "2188");
try {
DubboBootstrap.getInstance()
.application("demo-app")
.initialize();
Collection<RegistryConfig> registries = ApplicationModel.getConfigManager().getRegistries();
Assertions.assertEquals(1, registries.size());
RegistryConfig registryConfig = registries.iterator().next();
Assertions.assertEquals("zookeeper://localhost:2188", registryConfig.getAddress());
} finally {
}
}
public void testPreferredWithTrueValue() {
RegistryConfig registry = new RegistryConfig();
registry.setPreferred(true);

View File

@ -28,6 +28,7 @@ import org.apache.dubbo.registry.Registry;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.service.GenericService;
import org.junit.jupiter.api.AfterEach;
@ -38,6 +39,7 @@ import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import java.util.Collections;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
@ -78,6 +80,8 @@ public class ServiceConfigTest {
@BeforeEach
public void setUp() throws Exception {
ApplicationModel.getConfigManager().clear();
MockProtocol2.delegate = protocolDelegate;
MockRegistryFactory2.registry = registryDelegate;
Mockito.when(protocolDelegate.export(Mockito.any(Invoker.class))).thenReturn(exporter);
@ -126,12 +130,11 @@ public class ServiceConfigTest {
delayService.setMethods(Collections.singletonList(method));
delayService.setDelay(100);
// ApplicationModel.getConfigManager().clear();
}
@AfterEach
public void tearDown() {
// ApplicationModel.getConfigManager().clear();
ApplicationModel.getConfigManager().clear();
}
@Test
@ -281,4 +284,24 @@ public class ServiceConfigTest {
Assertions.assertNotNull(service.toUrl().getApplication());
Assertions.assertEquals("app", service.toUrl().getApplication());
}
@Test
public void testMetaData() {
// test new instance
ServiceConfig config = new ServiceConfig();
Map<String, String> metaData = config.getMetaData();
Assertions.assertEquals(0, metaData.size(), "Expect empty metadata but found: " + metaData);
// test merged and override provider attributes
ProviderConfig providerConfig = new ProviderConfig();
providerConfig.setAsync(true);
providerConfig.setActives(10);
config.setProvider(providerConfig);
config.setAsync(false);// override
metaData = config.getMetaData();
Assertions.assertEquals(2, metaData.size());
Assertions.assertEquals("" + providerConfig.getActives(), metaData.get("actives"));
Assertions.assertEquals("" + config.isAsync(), metaData.get("async"));
}
}

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.config;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Use to set and clear System property
*/
public class SysProps {
private static Map<String, String> map = new LinkedHashMap<String, String>();
public static void reset() {
map.clear();
}
public static void setProperty(String key, String value) {
map.put(key, value);
System.setProperty(key, value);
}
public static void clear() {
for (String key : map.keySet()) {
System.clearProperty(key);
}
reset();
}
}

View File

@ -17,18 +17,21 @@
package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.url.component.ServiceConfigURL;
import org.apache.dubbo.common.utils.ConfigUtils;
import org.apache.dubbo.config.AbstractInterfaceConfigTest;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.config.SysProps;
import org.apache.dubbo.monitor.MonitorService;
import org.apache.dubbo.registry.RegistryService;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
@ -58,23 +61,28 @@ public class DubboBootstrapTest {
@BeforeAll
public static void setUp(@TempDir Path folder) {
ApplicationModel.reset();
DubboBootstrap.reset();
dubboProperties = folder.resolve(CommonConstants.DUBBO_PROPERTIES_KEY).toFile();
System.setProperty(CommonConstants.DUBBO_PROPERTIES_KEY, dubboProperties.getAbsolutePath());
}
@AfterAll
public static void tearDown() {
System.clearProperty(CommonConstants.DUBBO_PROPERTIES_KEY);
}
@AfterEach
public void tearDown() throws IOException {
ApplicationModel.reset();
public void afterEach() throws IOException {
DubboBootstrap.reset();
SysProps.clear();
}
@Test
public void checkApplication() {
System.setProperty("dubbo.application.name", "demo");
SysProps.setProperty("dubbo.application.name", "demo");
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.refresh();
Assertions.assertEquals("demo", applicationConfig.getName());
System.clearProperty("dubbo.application.name");
}
@Test
@ -103,13 +111,21 @@ public class DubboBootstrapTest {
@Test
public void testLoadRegistries() {
System.setProperty("dubbo.registry.address", "addr1");
AbstractInterfaceConfigTest.InterfaceConfig interfaceConfig = new AbstractInterfaceConfigTest.InterfaceConfig();
// FIXME: now we need to check first, then load
interfaceConfig.setApplication(new ApplicationConfig("testLoadRegistries"));
interfaceConfig.checkRegistry();
ApplicationModel.getEnvironment().setDynamicConfiguration(new CompositeDynamicConfiguration());
List<URL> urls = ConfigValidationUtils.loadRegistries(interfaceConfig, true);
SysProps.setProperty("dubbo.registry.address", "addr1");
ServiceConfig serviceConfig = new ServiceConfig();
serviceConfig.setInterface(DemoService.class);
serviceConfig.setRef(new DemoServiceImpl());
serviceConfig.setApplication(new ApplicationConfig("testLoadRegistries"));
// load configs from props
DubboBootstrap.getInstance()
.initialize();
serviceConfig.refresh();
//ApplicationModel.getEnvironment().setDynamicConfiguration(new CompositeDynamicConfiguration());
List<URL> urls = ConfigValidationUtils.loadRegistries(serviceConfig, true);
Assertions.assertEquals(1, urls.size());
URL url = urls.get(0);
Assertions.assertEquals("registry", url.getProtocol());
@ -124,8 +140,8 @@ public class DubboBootstrapTest {
@Test
public void testLoadMonitor() {
System.setProperty("dubbo.monitor.address", "monitor-addr:12080");
System.setProperty("dubbo.monitor.protocol", "monitor");
SysProps.setProperty("dubbo.monitor.address", "monitor-addr:12080");
SysProps.setProperty("dubbo.monitor.protocol", "monitor");
AbstractInterfaceConfigTest.InterfaceConfig interfaceConfig = new AbstractInterfaceConfigTest.InterfaceConfig();
interfaceConfig.setApplication(new ApplicationConfig("testLoadMonitor"));
interfaceConfig.setMonitor(new MonitorConfig());

View File

@ -33,13 +33,6 @@ class AbstractBuilderTest {
Assertions.assertEquals("id", builder.build().getId());
}
@Test
void prefix() {
Builder builder = new Builder();
builder.prefix("prefix");
Assertions.assertEquals("prefix", builder.build().getPrefix());
}
@Test
void appendParameter() {
Map<String, String> source = null;
@ -96,13 +89,11 @@ class AbstractBuilderTest {
void build() {
Builder builder = new Builder();
builder.id("id");
builder.prefix("prefix");
Config config = builder.build();
Config config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}

View File

@ -24,13 +24,20 @@ import org.apache.dubbo.config.ModuleConfig;
import org.apache.dubbo.config.MonitorConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
class AbstractInterfaceBuilderTest {
@BeforeEach
void beforeEach() {
DubboBootstrap.reset();
}
@Test
void local() {
InterfaceBuilder builder = new InterfaceBuilder();
@ -254,7 +261,7 @@ class AbstractInterfaceBuilderTest {
ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
InterfaceBuilder builder = new InterfaceBuilder();
builder.id("id").prefix("prefix").local(true).stub(false).monitor("123").proxy("mockproxyfactory").cluster("mockcluster")
builder.id("id").local(true).stub(false).monitor("123").proxy("mockproxyfactory").cluster("mockcluster")
.filter("mockfilter").listener("mockinvokerlistener").owner("owner").connections(1)
.layer("layer").application(applicationConfig).module(moduleConfig)
.addRegistry(registryConfig).registryIds("registryIds")
@ -267,7 +274,6 @@ class AbstractInterfaceBuilderTest {
InterfaceConfig config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertEquals("true", config.getLocal());
Assertions.assertEquals("false", config.getStub());
Assertions.assertEquals(monitorConfig, config.getMonitor());

View File

@ -150,7 +150,7 @@ class AbstractMethodBuilderTest {
@Test
void build() {
MethodBuilder builder = new MethodBuilder();
builder.id("id").prefix("prefix").timeout(1).retries(2).actives(3).loadbalance("mockloadbalance").async(true)
builder.id("id").timeout(1).retries(2).actives(3).loadbalance("mockloadbalance").async(true)
.sent(false).mock("mock").merger("merger").cache("cache").validation("validation")
.appendParameter("default.num", "one");
@ -158,7 +158,6 @@ class AbstractMethodBuilderTest {
MethodConfig config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertEquals(1, config.getTimeout());
Assertions.assertEquals(2, config.getRetries());
Assertions.assertEquals(3, config.getActives());

View File

@ -111,13 +111,12 @@ class AbstractReferenceBuilderTest {
void build() {
ReferenceBuilder builder = new ReferenceBuilder();
builder.check(true).init(false).generic(true).injvm(false).lazy(true).reconnect("reconnect").sticky(false)
.version("version").group("group").id("id").prefix("prefix");
.version("version").group("group").id("id");
ReferenceConfig config = builder.build();
ReferenceConfig config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertTrue(config.isCheck());
Assertions.assertFalse(config.isInit());
Assertions.assertTrue(config.isGeneric());

View File

@ -197,13 +197,12 @@ class AbstractServiceBuilderTest {
builder.version("version").group("group").deprecated(true).delay(1000).export(false).weight(1)
.document("document").dynamic(true).token("token").accesslog("accesslog")
.addProtocol(protocol).protocolIds("protocolIds").tag("tag").executes(100).register(false)
.warmup(200).serialization("serialization").id("id").prefix("prefix");
.warmup(200).serialization("serialization").id("id");
ServiceConfig config = builder.build();
ServiceConfig config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertEquals("version", config.getVersion());
Assertions.assertEquals("group", config.getGroup());
Assertions.assertEquals("document", config.getDocument());

View File

@ -247,7 +247,7 @@ class ApplicationBuilderTest {
RegistryConfig registry = new RegistryConfig();
ApplicationBuilder builder = new ApplicationBuilder();
builder.id("id").prefix("prefix").name("name").version("version").owner("owner").organization("organization").architecture("architecture")
builder.id("id").name("name").version("version").owner("owner").organization("organization").architecture("architecture")
.environment("develop").compiler("compiler").logger("log4j").monitor(monitor).isDefault(false)
.dumpDirectory("dumpDirectory").qosEnable(true).qosPort(8080).qosAcceptForeignIp(false)
.shutwait("shutwait").registryIds("registryIds").addRegistry(registry)
@ -258,7 +258,6 @@ class ApplicationBuilderTest {
ApplicationConfig config2 = builder.build();
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertEquals("name", config.getName());
Assertions.assertEquals("version", config.getVersion());
Assertions.assertEquals("owner", config.getOwner());

View File

@ -142,7 +142,7 @@ class ConfigCenterBuilderTest {
builder.check(true).protocol("protocol").address("address").appConfigFile("appConfigFile")
.cluster("cluster").configFile("configFile").group("group").highestPriority(false)
.namespace("namespace").password("password").timeout(1000L).username("usernama")
.appendParameter("default.num", "one").id("id").prefix("prefix");
.appendParameter("default.num", "one").id("id");
ConfigCenterConfig config = builder.build();
ConfigCenterConfig config2 = builder.build();
@ -162,7 +162,6 @@ class ConfigCenterBuilderTest {
Assertions.assertTrue(config.getParameters().containsKey("default.num"));
Assertions.assertEquals("one", config.getParameters().get("default.num"));
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}

View File

@ -76,7 +76,7 @@ class ConsumerBuilderTest {
void build() {
ConsumerBuilder builder = new ConsumerBuilder();
builder.isDefault(true).client("client").threadPool("threadPool").coreThreads(10).threads(100).queues(200)
.shareConnections(300).id("id").prefix("prefix");
.shareConnections(300).id("id");
ConsumerConfig config = builder.build();
ConsumerConfig config2 = builder.build();
@ -85,7 +85,6 @@ class ConsumerBuilderTest {
Assertions.assertEquals("client", config.getClient());
Assertions.assertEquals("threadPool", config.getThreadpool());
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertEquals(10, config.getCorethreads());
Assertions.assertEquals(100, config.getThreads());
Assertions.assertEquals(200, config.getQueues());

View File

@ -128,7 +128,7 @@ class MetadataReportBuilderTest {
MetadataReportBuilder builder = new MetadataReportBuilder();
builder.address("address").username("username").password("password").timeout(1000).group("group")
.retryTimes(1).retryPeriod(2).cycleReport(true).syncReport(false)
.appendParameter("default.num", "one").id("id").prefix("prefix");
.appendParameter("default.num", "one").id("id");
MetadataReportConfig config = builder.build();
MetadataReportConfig config2 = builder.build();
@ -145,7 +145,6 @@ class MetadataReportBuilderTest {
Assertions.assertTrue(config.getParameters().containsKey("default.num"));
Assertions.assertEquals("one", config.getParameters().get("default.num"));
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -113,7 +113,7 @@ class MonitorBuilderTest {
MonitorBuilder builder = new MonitorBuilder();
builder.protocol("protocol").address("address").group("group").interval("interval").isDefault(true)
.password("password").username("username").version("version")
.appendParameter("default.num", "one").id("id").prefix("prefix");
.appendParameter("default.num", "one").id("id");
MonitorConfig config = builder.build();
MonitorConfig config2 = builder.build();
@ -129,7 +129,6 @@ class MonitorBuilderTest {
Assertions.assertTrue(config.getParameters().containsKey("default.num"));
Assertions.assertEquals("one", config.getParameters().get("default.num"));
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -293,7 +293,7 @@ class ProtocolBuilderTest {
.dispatcher("mockdispatcher").networker("networker").server("server").client("client")
.telnet("mocktelnethandler").prompt("prompt").status("mockstatuschecker").register(true).keepAlive(false)
.optimizer("optimizer").extension("extension").isDefault(true)
.appendParameter("default.num", "one").id("id").prefix("prefix");
.appendParameter("default.num", "one").id("id");
ProtocolConfig config = builder.build();
ProtocolConfig config2 = builder.build();
@ -332,7 +332,6 @@ class ProtocolBuilderTest {
Assertions.assertTrue(config.getParameters().containsKey("default.num"));
Assertions.assertEquals("one", config.getParameters().get("default.num"));
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -192,7 +192,7 @@ class ProviderBuilderTest {
.charset("utf-8").payload(6).buffer(1024).transporter("mocktransporter").exchanger("mockexchanger")
.dispatcher("mockdispatcher").networker("networker").server("server").client("client")
.telnet("mocktelnethandler").prompt("prompt").status("mockstatuschecker").wait(Integer.valueOf(1000))
.isDefault(true).id("id").prefix("prefix");
.isDefault(true).id("id");
ProviderConfig config = builder.build();
ProviderConfig config2 = builder.build();
@ -221,7 +221,6 @@ class ProviderBuilderTest {
Assertions.assertEquals("mockstatuschecker", config.getStatus());
Assertions.assertTrue(config.isDefault());
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -220,7 +220,7 @@ class RegistryBuilderTest {
.transporter("transporter").server("server").client("client").cluster("cluster").group("group")
.version("version").timeout(1000).session(2000).file("file").wait(Integer.valueOf(10)).isCheck(true)
.isDynamic(false).register(true).subscribe(false).isDefault(true).simplified(false).extraKeys("A")
.parameter("default.num", "one").id("id").prefix("prefix");
.parameter("default.num", "one").id("id");
RegistryConfig config = builder.build();
RegistryConfig config2 = builder.build();
@ -250,7 +250,6 @@ class RegistryBuilderTest {
Assertions.assertTrue(config.getParameters().containsKey("default.num"));
Assertions.assertEquals("one", config.getParameters().get("default.num"));
Assertions.assertEquals("id", config.getId());
Assertions.assertEquals("prefix", config.getPrefix());
Assertions.assertNotSame(config, config2);
}
}

View File

@ -28,6 +28,7 @@ import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.RpcInvocation;
@ -49,7 +50,7 @@ public class CacheTest {
@BeforeEach
public void setUp() {
// ApplicationModel.getConfigManager().clear();
DubboBootstrap.reset();
}
@AfterEach

View File

@ -21,6 +21,7 @@ import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.bootstrap.EchoService;
import org.apache.dubbo.config.bootstrap.EchoServiceImpl;
import org.apache.dubbo.config.context.ConfigManager;
@ -51,7 +52,7 @@ public class PublishingServiceDefinitionListenerTest {
@BeforeEach
public void init() {
ApplicationModel.reset();
DubboBootstrap.reset();
String metadataType = DEFAULT_METADATA_STORAGE_TYPE;
ConfigManager configManager = ApplicationModel.getConfigManager();
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-demo-provider");
@ -62,7 +63,7 @@ public class PublishingServiceDefinitionListenerTest {
@AfterEach
public void reset() {
ApplicationModel.reset();
DubboBootstrap.reset();
}
/**

View File

@ -19,7 +19,7 @@ package org.apache.dubbo.config.url;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
@ -43,13 +43,13 @@ public class ExporterSideConfigUrlTest extends UrlTestBase {
@BeforeEach
public void setUp() {
ApplicationModel.reset();
DubboBootstrap.reset();
initServConf();
}
@AfterEach()
public void teardown() {
ApplicationModel.reset();
DubboBootstrap.reset();
}
@Test

View File

@ -18,6 +18,7 @@ package org.apache.dubbo.config.utils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.utils.service.FooService;
import org.junit.jupiter.api.BeforeEach;
@ -31,6 +32,7 @@ public class ReferenceConfigCacheTest {
@BeforeEach
public void setUp() throws Exception {
DubboBootstrap.reset();
MockReferenceConfig.setCounter(0);
ReferenceConfigCache.CACHE_HOLDER.clear();
}

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.metadata;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
import org.apache.dubbo.rpc.model.ApplicationModel;
@ -41,7 +42,7 @@ public class MetadataServiceExporterTest {
@BeforeAll
public static void init() {
ApplicationModel.reset();
DubboBootstrap.reset();
ApplicationModel.getConfigManager().setApplication(new ApplicationConfig("Test"));
ApplicationModel.getConfigManager().addRegistry(new RegistryConfig("multicast://224.5.6.7:1234"));
ApplicationModel.getConfigManager().addProtocol(new ProtocolConfig("injvm"));
@ -49,8 +50,7 @@ public class MetadataServiceExporterTest {
@AfterAll
public static void destroy() {
ApplicationModel.getConfigManager().setApplication(null);
ApplicationModel.reset();
DubboBootstrap.reset();
}
@Test

View File

@ -1,2 +1,3 @@
dubbo.override.key2=properties
dubbo.override.protocol=properties
dubbo.override.protocol=properties
dubbo.application.enable-file-cache=false

View File

@ -77,12 +77,24 @@
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-triple</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-injvm</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-rpc-rest</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-remoting-netty4</artifactId>

View File

@ -21,5 +21,14 @@ package org.apache.dubbo.config.spring;
*/
public interface Constants {
/**
* attributes of reference annotation
*/
String REFERENCE_PROPS = "referenceProps";
/**
* Registration sources of the reference, may be xml file or annotation location
*/
String REFERENCE_SOURCES = "referenceSources";
}

View File

@ -40,7 +40,9 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -135,6 +137,9 @@ public class ReferenceBean<T> implements FactoryBean,
//actual reference config
private ReferenceConfig referenceConfig;
// Registration sources of this reference, may be xml file or annotation location
private List<Map<String,Object>> sources = new ArrayList<>();
public ReferenceBean() {
super();
}
@ -158,6 +163,30 @@ public class ReferenceBean<T> implements FactoryBean,
this.setId(name);
}
/**
* Create bean instance.
* <p/>
* When Spring searches beans by type, if Spring cannot determine the type of a factory bean, it may try to initialize it.
* The ReferenceBean is also a FactoryBean.
*
* <p/>
* In addition, if some ReferenceBeans are dependent on beans that are initialized very early,
* and dubbo config beans are not ready yet, there will be many unexpected problems if initializing the dubbo reference immediately.
*
* <p/>
* When it is initialized, only a lazy proxy object will be created,
* and dubbo reference-related resources will not be initialized.
* <br/>
* In this way, the influence of Spring is eliminated, and the dubbo configuration initialization is controllable.
*
* <p/>
* Dubbo config beans are initialized in DubboConfigInitializationPostProcessor.
* <br/>
* The actual references will be processing in DubboBootstrap.referServices().
*
* @see org.apache.dubbo.config.spring.context.DubboConfigInitializationPostProcessor
* @see org.apache.dubbo.config.bootstrap.DubboBootstrap
*/
@Override
public Object getObject() {
if (lazyProxy == null) {
@ -214,6 +243,9 @@ public class ReferenceBean<T> implements FactoryBean,
Assert.notNull(this.actualInterface, "The actual interface of ReferenceBean is not initialized");
this.interfaceName = actualInterface.getName();
// this.sources = (List<Map<String, Object>>) beanDefinition.getAttribute(Constants.REFERENCE_SOURCES);
// Assert.notNull(this.sources, "The registration sources of this reference is empty");
ReferenceBeanManager referenceBeanManager = beanFactory.getBean(ReferenceBeanManager.BEAN_NAME, ReferenceBeanManager.class);
referenceBeanManager.addReference(this);
}
@ -227,11 +259,6 @@ public class ReferenceBean<T> implements FactoryBean,
// do nothing
}
@Deprecated
public Object get() {
return referenceConfig.get();
}
public String getId() {
return id;
}
@ -281,7 +308,7 @@ public class ReferenceBean<T> implements FactoryBean,
}
/**
* create lazy proxy for reference
* Create lazy proxy for reference.
*/
private void createLazyProxy() {

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
import org.apache.dubbo.config.support.Parameter;
@ -64,6 +65,7 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
//TODO remove SpringExtensionFactory.addApplicationContext();
SpringExtensionFactory.addApplicationContext(applicationContext);
}
@ -88,6 +90,8 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
setPath(getInterface());
}
}
//register service bean and set bootstrap
DubboBootstrap.getInstance().service(this);
}
/**

View File

@ -1,50 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.Service;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
/**
* {@link Service} Annotation {@link BeanDefinitionRegistryPostProcessor Bean Definition Registry Post Processor}
*
* @since 2.5.8
* @deprecated Recommend {@link ServiceClassPostProcessor} as the substitute
*/
@Deprecated
public class ServiceAnnotationBeanPostProcessor extends ServiceClassPostProcessor {
public ServiceAnnotationBeanPostProcessor(String... packagesToScan) {
this(Arrays.asList(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
this(new LinkedHashSet<>(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
super(packagesToScan);
}
}

View File

@ -19,6 +19,7 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.ArrayUtils;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.MethodConfig;
import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Method;
@ -35,14 +36,12 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
@ -55,8 +54,6 @@ import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.lang.annotation.Annotation;
import java.util.Collection;
@ -87,7 +84,7 @@ import static org.springframework.util.ClassUtils.resolveClassName;
* @see BeanDefinitionRegistryPostProcessor
* @since 2.7.7
*/
public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
public class ServiceAnnotationPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
private final static List<Class<? extends Annotation>> serviceAnnotationTypes = asList(
@ -110,15 +107,15 @@ public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProc
private ClassLoader classLoader;
public ServiceClassPostProcessor(String... packagesToScan) {
public ServiceAnnotationPostProcessor(String... packagesToScan) {
this(asList(packagesToScan));
}
public ServiceClassPostProcessor(Collection<String> packagesToScan) {
public ServiceAnnotationPostProcessor(Collection<String> packagesToScan) {
this(new LinkedHashSet<>(packagesToScan));
}
public ServiceClassPostProcessor(Set<String> packagesToScan) {
public ServiceAnnotationPostProcessor(Set<String> packagesToScan) {
this.packagesToScan = packagesToScan;
}
@ -403,7 +400,7 @@ public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProc
propertyValues.addPropertyValues(new AnnotationPropertyValuesAdapter(serviceAnnotation, environment, ignoreAttributeNames));
//set config id, for ConfigManager cache key
builder.addPropertyValue("id", beanName);
//builder.addPropertyValue("id", beanName);
// References "ref" property to annotated-@Service Bean
addPropertyReference(builder, "ref", annotatedServiceBeanName);
// Set interface
@ -416,65 +413,59 @@ public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProc
builder.addPropertyValue("methods", methodConfigs);
}
/**
* Add {@link org.apache.dubbo.config.ProviderConfig} Bean reference
*/
String providerConfigBeanName = serviceAnnotationAttributes.getString("provider");
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
// convert provider to providerIds
String providerConfigId = serviceAnnotationAttributes.getString("provider");
if (StringUtils.hasText(providerConfigId)) {
addPropertyValue(builder, "providerIds", providerConfigId);
}
/**
* Add {@link org.apache.dubbo.config.MonitorConfig} Bean reference
*/
String monitorConfigBeanName = serviceAnnotationAttributes.getString("monitor");
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
// Convert registry[] to registryIds
String[] registryConfigIds = serviceAnnotationAttributes.getStringArray("registry");
if (registryConfigIds != null && registryConfigIds.length > 0) {
resolveStringArray(registryConfigIds);
builder.addPropertyValue("registryIds", StringUtils.join(registryConfigIds, ','));
}
/**
* Add {@link org.apache.dubbo.config.ApplicationConfig} Bean reference
*/
String applicationConfigBeanName = serviceAnnotationAttributes.getString("application");
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
// Convert protocol[] to protocolIds
String[] protocolConfigIds = serviceAnnotationAttributes.getStringArray("protocol");
if (protocolConfigIds != null && protocolConfigIds.length > 0) {
resolveStringArray(protocolConfigIds);
builder.addPropertyValue("protocolIds", StringUtils.join(protocolConfigIds, ','));
}
/**
* Add {@link org.apache.dubbo.config.ModuleConfig} Bean reference
*/
String moduleConfigBeanName = serviceAnnotationAttributes.getString("module");
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
// TODO Could we ignore these attributes: applicatin/monitor/module ? Use global config
// monitor reference
String monitorConfigId = serviceAnnotationAttributes.getString("monitor");
if (StringUtils.hasText(monitorConfigId)) {
addPropertyReference(builder, "monitor", monitorConfigId);
}
/**
* Add {@link org.apache.dubbo.config.RegistryConfig} Bean reference
*/
String[] registryConfigBeanNames = serviceAnnotationAttributes.getStringArray("registry");
List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
// application reference
String applicationConfigId = serviceAnnotationAttributes.getString("application");
if (StringUtils.hasText(applicationConfigId)) {
addPropertyReference(builder, "application", applicationConfigId);
}
/**
* Add {@link org.apache.dubbo.config.ProtocolConfig} Bean reference
*/
String[] protocolConfigBeanNames = serviceAnnotationAttributes.getStringArray("protocol");
List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!protocolRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
// module reference
String moduleConfigId = serviceAnnotationAttributes.getString("module");
if (StringUtils.hasText(moduleConfigId)) {
addPropertyReference(builder, "module", moduleConfigId);
}
return builder.getBeanDefinition();
}
private String[] resolveStringArray(String[] strs) {
if (strs == null) {
return null;
}
for (int i = 0; i < strs.length; i++) {
strs[i] = environment.resolvePlaceholders(strs[i]);
}
return strs;
}
private List convertMethodConfigs(Object methodsAnnotation) {
if (methodsAnnotation == null) {
return Collections.EMPTY_LIST;
@ -482,30 +473,16 @@ public class ServiceClassPostProcessor implements BeanDefinitionRegistryPostProc
return MethodConfig.constructMethodConfig((Method[]) methodsAnnotation);
}
private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) {
ManagedList<RuntimeBeanReference> runtimeBeanReferences = new ManagedList<>();
if (!ObjectUtils.isEmpty(beanNames)) {
for (String beanName : beanNames) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
runtimeBeanReferences.add(new RuntimeBeanReference(resolvedBeanName));
}
}
return runtimeBeanReferences;
}
private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
builder.addPropertyReference(propertyName, resolvedBeanName);
}
private void addPropertyValue(BeanDefinitionBuilder builder, String propertyName, String value) {
String resolvedBeanName = environment.resolvePlaceholders(value);
builder.addPropertyValue(propertyName, resolvedBeanName);
}
private Map<String, String> convertParameters(String[] parameters) {
if (ArrayUtils.isEmpty(parameters)) {
return null;

View File

@ -16,11 +16,10 @@
*/
package org.apache.dubbo.config.spring.beans.factory.config;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ProtocolConfig;
import com.alibaba.spring.beans.factory.config.GenericBeanPostProcessorAdapter;
import org.apache.dubbo.config.Constants;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
@ -54,15 +53,13 @@ public class DubboConfigDefaultPropertyValueBeanPostProcessor extends GenericBea
public static final String BEAN_NAME = "dubboConfigDefaultPropertyValueBeanPostProcessor";
protected void processBeforeInitialization(AbstractConfig dubboConfigBean, String beanName) throws BeansException {
// [Feature] https://github.com/apache/dubbo/issues/5721
setBeanNameAsDefaultValue(dubboConfigBean, "id", beanName);
if (dubboConfigBean instanceof ProtocolConfig) {
ProtocolConfig config = (ProtocolConfig) dubboConfigBean;
if (StringUtils.isEmpty(config.getName())) {
config.setName("dubbo");
}
} else {
setBeanNameAsDefaultValue(dubboConfigBean, "name", beanName);
// ignore auto generate bean name
if (!beanName.contains("#")) {
// [Feature] https://github.com/apache/dubbo/issues/5721
setPropertyIfAbsent(dubboConfigBean, Constants.ID, beanName);
// beanName should not be used as config name, fix https://github.com/apache/dubbo/pull/7624
//setPropertyIfAbsent(dubboConfigBean, "name", beanName);
}
}
@ -71,7 +68,7 @@ public class DubboConfigDefaultPropertyValueBeanPostProcessor extends GenericBea
// DO NOTHING
}
protected void setBeanNameAsDefaultValue(Object bean, String propertyName, String beanName) {
protected void setPropertyIfAbsent(Object bean, String propertyName, String beanName) {
Class<?> beanClass = getTargetClass(bean);

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