You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/12/17 06:57:10 UTC

[incubator-dubbo] 04/07: support using multi registries/protocols in config center.

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

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

commit 0a2aab8c59d43486bb497c09a1b44c986db4fe78
Author: ken.lj <ke...@gmail.com>
AuthorDate: Mon Dec 17 11:31:04 2018 +0800

    support using multi registries/protocols in config center.
---
 .../common/config/CompositeConfiguration.java      |   6 +-
 .../dubbo/common/config/ConfigurationUtils.java    |   1 +
 .../apache/dubbo/common/config/Environment.java    |  42 ++++--
 .../org/apache/dubbo/common/utils/UrlUtils.java    |   6 +
 .../org/apache/dubbo/config/AbstractConfig.java    |  25 ++--
 .../dubbo/config/AbstractInterfaceConfig.java      | 142 ++++++++++++++-------
 .../apache/dubbo/config/AbstractServiceConfig.java |  10 ++
 .../org/apache/dubbo/config/ApplicationConfig.java |  10 ++
 .../apache/dubbo/config/ConfigCenterConfig.java    |  31 ++++-
 .../org/apache/dubbo/config/ReferenceConfig.java   |   2 +-
 .../org/apache/dubbo/config/ServiceConfig.java     |  75 ++++++++---
 .../apache/dubbo/config/AbstractConfigTest.java    |   8 +-
 .../dubbo/config/spring/ConfigCenterBean.java      |  22 ++--
 .../apache/dubbo/config/spring/ReferenceBean.java  |  30 ++++-
 .../apache/dubbo/config/spring/ServiceBean.java    |  56 +++++++-
 .../annotation/DubboConfigConfiguration.java       |   4 +-
 .../spring/schema/DubboBeanDefinitionParser.java   |  38 +-----
 .../spring/schema/DubboNamespaceHandler.java       |   2 +-
 .../src/main/resources/META-INF/compat/dubbo.xsd   |   4 +-
 .../src/main/resources/META-INF/dubbo.xsd          |   4 +-
 20 files changed, 350 insertions(+), 168 deletions(-)

diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
index 6d732da..a181aeb 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/CompositeConfiguration.java
@@ -19,7 +19,6 @@ package org.apache.dubbo.common.config;
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.stream.Collectors;
 
 /**
  *
@@ -78,9 +77,6 @@ public class CompositeConfiguration extends AbstractConfiguration {
 
     @Override
     public boolean containsKey(String key) {
-        List<Configuration> subConfigList = configList.stream()
-                .filter(config -> config.containsKey(key))
-                .collect(Collectors.toList());
-        return subConfigList.size() > 0;
+        return configList.stream().anyMatch(c -> c.containsKey(key));
     }
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
index 28ef93b..a69a6cf 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/ConfigurationUtils.java
@@ -55,4 +55,5 @@ public class ConfigurationUtils {
     public static String getProperty(String property, String defaultValue) {
         return Environment.getInstance().getConfiguration().getString(property, defaultValue);
     }
+
 }
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
index 11aabd5..fe4c03d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/Environment.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.common.utils.StringUtils;
 
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.ConcurrentHashMap;
 
 /**
@@ -82,14 +83,22 @@ public class Environment {
         return appConfigs.get(toKey(prefix, id));
     }
 
-    public void setExternalConfig(Map<String, String> externalConfiguration) {
+    public void setExternalConfigMap(Map<String, String> externalConfiguration) {
         this.externalConfigurationMap = externalConfiguration;
     }
 
-    public void setAppExternalConfig(Map<String, String> appExternalConfiguration) {
+    public void setAppExternalConfigMap(Map<String, String> appExternalConfiguration) {
         this.appExternalConfigurationMap = appExternalConfiguration;
     }
 
+    public Map<String, String> getExternalConfigurationMap() {
+        return externalConfigurationMap;
+    }
+
+    public Map<String, String> getAppExternalConfigurationMap() {
+        return appExternalConfigurationMap;
+    }
+
     public void addAppConfig(String prefix, String id, Map<String, String> properties) {
         appConfigs.computeIfAbsent(toKey(prefix, id), k -> {
             InmemoryConfiguration configuration = new InmemoryConfiguration(prefix, id);
@@ -117,15 +126,24 @@ public class Environment {
      */
     public Configuration getConfiguration(String prefix, String id) {
         CompositeConfiguration compositeConfiguration = new CompositeConfiguration();
-        compositeConfiguration.addConfiguration(this.getSystemConfig(prefix, id));
-        compositeConfiguration.addConfiguration(this.getAppExternalConfig(prefix, id));
-        compositeConfiguration.addConfiguration(this.getExternalConfig(prefix, id));
-        compositeConfiguration.addConfiguration(this.getPropertiesConfig(prefix, id));
-
         InmemoryConfiguration appConfig = this.getAppConfig(prefix, id);
-        if (appConfig != null) {
-            int index = configCenterFirst ? 3 : 1;
-            compositeConfiguration.addConfiguration(index, appConfig);
+        // Config center has the highest priority
+        if (!configCenterFirst) {
+            if (appConfig != null) {
+                compositeConfiguration.addConfiguration(appConfig);
+            }
+            compositeConfiguration.addConfiguration(this.getSystemConfig(prefix, id));
+            compositeConfiguration.addConfiguration(this.getAppExternalConfig(prefix, id));
+            compositeConfiguration.addConfiguration(this.getExternalConfig(prefix, id));
+            compositeConfiguration.addConfiguration(this.getPropertiesConfig(prefix, id));
+        } else {
+            compositeConfiguration.addConfiguration(this.getSystemConfig(prefix, id));
+            compositeConfiguration.addConfiguration(this.getAppExternalConfig(prefix, id));
+            compositeConfiguration.addConfiguration(this.getExternalConfig(prefix, id));
+            if (appConfig != null) {
+                compositeConfiguration.addConfiguration(appConfig);
+            }
+            compositeConfiguration.addConfiguration(this.getPropertiesConfig(prefix, id));
         }
         return compositeConfiguration;
     }
@@ -161,8 +179,8 @@ public class Environment {
         this.configCenterFirst = configCenterFirst;
     }
 
-    public Configuration getDynamicConfiguration() {
-        return dynamicConfiguration;
+    public Optional<Configuration> getDynamicConfiguration() {
+        return Optional.ofNullable(dynamicConfiguration);
     }
 
     public void setDynamicConfiguration(Configuration dynamicConfiguration) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
index 65381ab..8cbb34d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/UrlUtils.java
@@ -24,6 +24,8 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
 
 public class UrlUtils {
 
@@ -439,6 +441,10 @@ public class UrlUtils {
                 value.getParameter(Constants.VERSION_KEY));
     }
 
+    public static List<URL> classifyUrls(List<URL> urls, Predicate<URL> predicate) {
+        return urls.stream().filter(predicate).collect(Collectors.toList());
+    }
+
     /**
      * Check if the given value matches the given pattern. The pattern supports wildcard "*".
      *
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 537893a..9ca9204 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -35,8 +35,10 @@ import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 /**
  * Utility methods and public methods for parsing configuration
@@ -80,8 +82,7 @@ public abstract class AbstractConfig implements Serializable {
     }
 
     protected String id;
-    private boolean init;
-    private volatile Map<String, String> metaData;
+    protected String prefix;
 
     private static String convertLegacyValue(String key, String value) {
         if (value != null && value.length() > 0) {
@@ -352,6 +353,13 @@ public abstract class AbstractConfig implements Serializable {
         }
     }
 
+    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());
+    }
+
     private static String extractPropertyName(Class<?> clazz, Method setter) throws Exception {
         String propertyName = setter.getName().substring("set".length());
         Method getter = null;
@@ -436,7 +444,7 @@ public abstract class AbstractConfig implements Serializable {
      * Notice! This method should include all properties in the returning map, treat @Parameter differently compared to appendParameters.
      */
     public Map<String, String> getMetaData() {
-        metaData = new HashMap<>();
+        Map<String, String> metaData = new HashMap<>();
         Method[] methods = this.getClass().getMethods();
         for (Method method : methods) {
             try {
@@ -510,7 +518,11 @@ public abstract class AbstractConfig implements Serializable {
 
     @Parameter(excluded = true)
     public String getPrefix() {
-        return Constants.DUBBO + "." + getTagName(this.getClass());
+        return StringUtils.isNotEmpty(prefix) ? prefix : (Constants.DUBBO + "." + getTagName(this.getClass()));
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
     }
 
     /**
@@ -518,11 +530,6 @@ public abstract class AbstractConfig implements Serializable {
      * overriding of customized parameters stored in 'parameters'.
      */
     public void refresh() {
-        if (init) {
-            return;
-        }
-        init = true;
-
         try {
             Environment env = Environment.getInstance();
             env.addAppConfig(getPrefix(), getId(), getMetaData());
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 61c29ac..8bef3bf 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -34,13 +34,16 @@ import org.apache.dubbo.rpc.Filter;
 import org.apache.dubbo.rpc.InvokerListener;
 import org.apache.dubbo.rpc.ProxyFactory;
 import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.model.ApplicationModel;
 import org.apache.dubbo.rpc.support.MockInvoker;
 
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import static org.apache.dubbo.common.Constants.APPLICATION_KEY;
 import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
@@ -94,6 +97,8 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     // registry centers
     protected List<RegistryConfig> registries;
 
+    protected String registryLiteral;
+
     // connection events
     protected String onconnect;
 
@@ -107,67 +112,27 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
     private String scope;
 
     protected void checkRegistry() {
-        // for backward compatibility
-        // -Ddubbo.registry.address is now deprecated.
-        if (registries == null || registries.isEmpty()) {
-            String address = ConfigUtils.getProperty("dubbo.registry.address");
-            if (address != null && address.length() > 0) {
-                registries = new ArrayList<RegistryConfig>();
-                String[] as = address.split("\\s*[|]+\\s*");
-                for (String a : as) {
-                    RegistryConfig registryConfig = new RegistryConfig();
-                    registryConfig.setAddress(a);
-                    registries.add(registryConfig);
-                }
-            }
-        }
+        loadRegistriesFromBackwardConfig();
 
-        if (registries == null || registries.isEmpty()) {
-            registries = new ArrayList<>();
-            String registryIds = Environment.getInstance().getConfiguration(null, null).getString("dubbo.registries");
-            if (StringUtils.isNotEmpty(registryIds)) {
-                Arrays.stream(Constants.COMMA_SPLIT_PATTERN.split(registryIds))
-                        .map(regId -> {
-                            RegistryConfig registryConfig = new RegistryConfig();
-                            registryConfig.setId(regId);
-                            return registryConfig;
-                        })
-                        .forEach(registries::add);
-            } else {
-                registries.add(new RegistryConfig());
-            }
-        }
+        convertRegistryLiteralToRegistries();
 
         for (RegistryConfig registryConfig : registries) {
             registryConfig.refresh();
+            if (StringUtils.isNotEmpty(registryConfig.getId())) {
+                registryConfig.setPrefix(Constants.REGISTRIES_SUFFIX);
+                registryConfig.refresh();
+            }
         }
 
         for (RegistryConfig registryConfig : registries) {
             if (!registryConfig.isValid()) {
-                throw new IllegalStateException("No registry config found or it's not a valid config!");
+                throw new IllegalStateException("No registry config found or it's not a valid config! The registry config is: " + registryConfig);
             }
         }
 
         useRegistryForConfigIfNecessary();
     }
 
-    /**
-     * For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and
-     * there's no config center specified explicitly.
-     */
-    private void useRegistryForConfigIfNecessary() {
-        RegistryConfig registry = registries.get(0);
-        if (registry.isZookeeperProtocol()) {
-            // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
-            if (Environment.getInstance().getDynamicConfiguration() == null) {
-                ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
-                configCenterConfig.setProtocol(registry.getProtocol());
-                configCenterConfig.setAddress(registry.getAddress());
-                configCenterConfig.init();
-            }
-        }
-    }
-
     @SuppressWarnings("deprecation")
     protected void checkApplication() {
         // for backward compatibility
@@ -182,6 +147,9 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
                     "No application config found or it's not a valid config! Please add <dubbo:application name=\"...\" /> to your spring config.");
         }
 
+        ApplicationModel.setApplication(application.getName());
+
+        // backward compatibility
         String wait = ConfigUtils.getProperty(Constants.SHUTDOWN_WAIT_KEY);
         if (wait != null && wait.trim().length() > 0) {
             System.setProperty(Constants.SHUTDOWN_WAIT_KEY, wait.trim());
@@ -418,6 +386,77 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         }
     }
 
+    private void convertRegistryLiteralToRegistries() {
+        if (StringUtils.isEmpty(registryLiteral) && (registries == null || registries.isEmpty())) {
+            Set<String> configedRegistries = new HashSet<>();
+            configedRegistries.addAll(getSubProperties(Environment.getInstance()
+                    .getExternalConfigurationMap(), Constants.REGISTRIES_SUFFIX));
+            configedRegistries.addAll(getSubProperties(Environment.getInstance()
+                    .getAppExternalConfigurationMap(), Constants.REGISTRIES_SUFFIX));
+
+            registryLiteral = String.join(",", configedRegistries);
+        }
+
+        if (StringUtils.isEmpty(registryLiteral)) {
+            if (registries == null || registries.isEmpty()) {
+                registries = new ArrayList<>();
+                registries.add(new RegistryConfig());
+            }
+        } else {
+            String[] arr = Constants.COMMA_SPLIT_PATTERN.split(registryLiteral);
+            if (registries == null || registries.isEmpty()) {
+                registries = new ArrayList<>();
+            }
+            Arrays.stream(arr).forEach(id -> {
+                if (registries.stream().noneMatch(reg -> reg.getId().equals(id))) {
+                    RegistryConfig registryConfig = new RegistryConfig();
+                    registryConfig.setId(id);
+                    registries.add(registryConfig);
+                }
+            });
+            if (registries.size() > arr.length) {
+                throw new IllegalStateException("Too much registries found, the registries assigned to this service are :" + registryLiteral + ", but got " + registries
+                        .size() + " registries!");
+            }
+        }
+
+    }
+
+    private void loadRegistriesFromBackwardConfig() {
+        // for backward compatibility
+        // -Ddubbo.registry.address is now deprecated.
+        if (registries == null || registries.isEmpty()) {
+            String address = ConfigUtils.getProperty("dubbo.registry.address");
+            if (address != null && address.length() > 0) {
+                registries = new ArrayList<RegistryConfig>();
+                String[] as = address.split("\\s*[|]+\\s*");
+                for (String a : as) {
+                    RegistryConfig registryConfig = new RegistryConfig();
+                    registryConfig.setAddress(a);
+                    registries.add(registryConfig);
+                }
+            }
+        }
+    }
+
+    /**
+     * For compatibility purpose, use registry as the default config center if the registry protocol is zookeeper and
+     * there's no config center specified explicitly.
+     */
+    private void useRegistryForConfigIfNecessary() {
+        registries.stream().filter(RegistryConfig::isZookeeperProtocol).findFirst().ifPresent(rc -> {
+            // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
+            Environment.getInstance().getDynamicConfiguration().orElseGet(() -> {
+                ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
+                configCenterConfig.setProtocol(rc.getProtocol());
+                configCenterConfig.setAddress(rc.getAddress());
+                configCenterConfig.setEnable(false);
+                configCenterConfig.init();
+                return null;
+            });
+        });
+    }
+
     /**
      * @return local
      * @deprecated Replace to <code>getStub()</code>
@@ -557,6 +596,15 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
         this.registries = (List<RegistryConfig>) registries;
     }
 
+    @Parameter(excluded = true)
+    public String getRegistryLiteral() {
+        return registryLiteral;
+    }
+
+    public void setRegistry(String registryLiteral) {
+        this.registryLiteral = registryLiteral;
+    }
+
     public MonitorConfig getMonitor() {
         return monitor;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
index 6109294..2b3ae11 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractServiceConfig.java
@@ -62,6 +62,7 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
     // access log
     protected String accesslog;
     protected List<ProtocolConfig> protocols;
+    protected String protocolLiteral;
     // provider tag
     protected String tag;
     // max allowed execute times
@@ -174,6 +175,15 @@ public abstract class AbstractServiceConfig extends AbstractInterfaceConfig {
         this.protocols = Arrays.asList(protocol);
     }
 
+    @Parameter(excluded = true)
+    public String getProtocolLiteral() {
+        return protocolLiteral;
+    }
+
+    public void setProtocol(String protocolLiteral) {
+        this.protocolLiteral = protocolLiteral;
+    }
+
     public String getAccesslog() {
         return accesslog;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index 9710515..37ae811 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@ -62,6 +62,7 @@ public class ApplicationConfig extends AbstractConfig {
 
     // registry centers
     private List<RegistryConfig> registries;
+    private String registryLiteral;
 
     // monitor center
     private MonitorConfig monitor;
@@ -177,6 +178,15 @@ public class ApplicationConfig extends AbstractConfig {
         this.registries = (List<RegistryConfig>) registries;
     }
 
+    @Parameter(excluded = true)
+    public String getRegistryLiteral() {
+        return registryLiteral;
+    }
+
+    public void setRegistry(String registryLiteral) {
+        this.registryLiteral = registryLiteral;
+    }
+
     public MonitorConfig getMonitor() {
         return monitor;
     }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
index dbe3821..7aee0ba 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
@@ -31,11 +31,14 @@ import java.io.StringReader;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 /**
  *
  */
 public class ConfigCenterConfig extends AbstractConfig {
+    private AtomicBoolean inited = new AtomicBoolean(false);
+
     private String protocol;
     private String address;
     private String env;
@@ -45,7 +48,7 @@ public class ConfigCenterConfig extends AbstractConfig {
     private String username;
     private String password;
     private Long timeout = 3000L;
-    private Boolean priority = true;
+    private Boolean enable = true;
     private Boolean check = true;
 
     private String appname;
@@ -62,6 +65,10 @@ public class ConfigCenterConfig extends AbstractConfig {
     }
 
     public void init() {
+        if (!inited.compareAndSet(false, true)) {
+            return;
+        }
+
         // give jvm properties the chance to override local configs, e.g., -Ddubbo.configcenter.config.priority
         refresh();
         // try to use registryConfig as the default configcenter, only applies to zookeeper.
@@ -85,7 +92,7 @@ public class ConfigCenterConfig extends AbstractConfig {
                         );
             }
             try {
-                Environment.getInstance().setConfigCenterFirst(priority);
+                Environment.getInstance().setConfigCenterFirst(enable);
                 Environment.getInstance().updateExternalConfigurationMap(parseProperties(configContent));
                 Environment.getInstance().updateAppExternalConfigurationMap(parseProperties(appConfigContent));
             } catch (IOException e) {
@@ -139,6 +146,16 @@ public class ConfigCenterConfig extends AbstractConfig {
         return map;
     }
 
+    public void setExternalConfig(Map<String, String> externalConfiguration) {
+        Environment.getInstance().setExternalConfigMap(externalConfiguration);
+        inited.set(true);
+    }
+
+    public void setAppExternalConfig(Map<String, String> appExternalConfiguration) {
+        Environment.getInstance().setAppExternalConfigMap(appExternalConfiguration);
+        inited.set(true);
+    }
+
     public String getProtocol() {
         return protocol;
     }
@@ -201,13 +218,13 @@ public class ConfigCenterConfig extends AbstractConfig {
         this.check = check;
     }
 
-    @Parameter(key = Constants.CONFIG_PRIORITY_KEY)
-    public Boolean isPriority() {
-        return priority;
+    @Parameter(key = Constants.CONFIG_ENABLE_KEY)
+    public Boolean getEnable() {
+        return enable;
     }
 
-    public void setPriority(Boolean priority) {
-        this.priority = priority;
+    public void setEnable(Boolean enable) {
+        this.enable = enable;
     }
 
     public String getUsername() {
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 9b3380d..c304fc8 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -555,7 +555,7 @@ public class ReferenceConfig<T> extends AbstractReferenceConfig {
     @Override
     @Parameter(excluded = true)
     public String getPrefix() {
-        return Constants.DUBBO + ".reference";
+        return Constants.DUBBO + ".reference." + interfaceName;
     }
 
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index dd86532..fc5d251 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -91,6 +91,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
     // method configuration
     private List<MethodConfig> methods;
     private ProviderConfig provider;
+    private String providerLiteral;
     private transient volatile boolean exported;
 
     private transient volatile boolean unexported;
@@ -726,31 +727,56 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
     }
 
     private void checkProtocol() {
-        if ((protocols == null || protocols.isEmpty())
-                && provider != null) {
+        if ((protocols == null || protocols.isEmpty()) && provider != null) {
             setProtocols(provider.getProtocols());
         }
-        // backward compatibility
-        if (protocols == null || protocols.isEmpty()) {
-            //check 'dubbo.protocols=dubboProtocolId,hessianProtocolId' and decide if we need multiple protocols
-            String protocolIds = Environment.getInstance().getConfiguration(null, null).getString("dubbo.protocols");
-            if (StringUtils.isNotEmpty(protocolIds)) {
-                Arrays.stream(Constants.COMMA_SPLIT_PATTERN.split(protocolIds))
-                        .map(pId -> {
-                            ProtocolConfig protocolConfig = new ProtocolConfig();
-                            protocolConfig.setId(pId);
-                            return protocolConfig;
-                        })
-                        .forEach(protocols::add);
-            } else {
-                setProtocol(new ProtocolConfig());
-            }
-        }
+
+        convertProtocolLiteralToProtocols();
+
         for (ProtocolConfig protocolConfig : protocols) {
             if (StringUtils.isEmpty(protocolConfig.getName())) {
                 protocolConfig.setName(Constants.DUBBO_VERSION_KEY);
             }
             protocolConfig.refresh();
+            if (StringUtils.isNotEmpty(protocolConfig.getId())) {
+                protocolConfig.setPrefix("dubbo.protocols.");
+                protocolConfig.refresh();
+            }
+        }
+    }
+
+    private void convertProtocolLiteralToProtocols() {
+        if (StringUtils.isEmpty(protocolLiteral) && (protocols == null || protocols.isEmpty())) {
+            List<String> configedProtocols = new ArrayList<>();
+            configedProtocols.addAll(getSubProperties(Environment.getInstance()
+                    .getExternalConfigurationMap(), Constants.PROTOCOLS_SUFFIX));
+            configedProtocols.addAll(getSubProperties(Environment.getInstance()
+                    .getAppExternalConfigurationMap(), Constants.PROTOCOLS_SUFFIX));
+
+            protocolLiteral = String.join(",", configedProtocols);
+        }
+
+        if (StringUtils.isEmpty(protocolLiteral)) {
+            if (protocols == null || protocols.isEmpty()) {
+                protocols = new ArrayList<>();
+                protocols.add(new ProtocolConfig());
+            }
+        } else {
+            String[] arr = Constants.COMMA_SPLIT_PATTERN.split(protocolLiteral);
+            if (protocols == null || protocols.isEmpty()) {
+                protocols = new ArrayList<>();
+            }
+            Arrays.stream(arr).forEach(id -> {
+                if (protocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
+                    ProtocolConfig protocolConfig = new ProtocolConfig();
+                    protocolConfig.setId(id);
+                    protocols.add(protocolConfig);
+                }
+            });
+            if (protocols.size() > arr.length) {
+                throw new IllegalStateException("Too much protocols found, the protocols comply to this service are :" + protocolLiteral + " but got " + protocols
+                        .size() + " registries!");
+            }
         }
     }
 
@@ -837,6 +863,15 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
         this.provider = provider;
     }
 
+    @Parameter(excluded = true)
+    public String getProviderLiteral() {
+        return providerLiteral;
+    }
+
+    public void setProvider(String providerLiteral) {
+        this.providerLiteral = providerLiteral;
+    }
+
     public String getGeneric() {
         return generic;
     }
@@ -888,7 +923,7 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
         if (group != null && group.length() > 0) {
             buf.append(group).append("/");
         }
-        buf.append(interfaceName);
+        buf.append(StringUtils.isNotEmpty(path) ? path : interfaceName);
         if (version != null && version.length() > 0) {
             buf.append(":").append(version);
         }
@@ -898,6 +933,6 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
     @Override
     @Parameter(excluded = true)
     public String getPrefix() {
-        return Constants.DUBBO + ".service";
+        return Constants.DUBBO + ".service." + interfaceName;
     }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index b50433a..85a9301 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -293,7 +293,7 @@ public class AbstractConfigTest {
             external.put("dubbo.override.key", "external");
             // @Parameter(key="key2", useKeyAsProperty=true)
             external.put("dubbo.override.key2", "external");
-            Environment.getInstance().setExternalConfig(external);
+            Environment.getInstance().setExternalConfigMap(external);
 
             System.setProperty("dubbo.override.address", "system://127.0.0.1:2181");
             System.setProperty("dubbo.override.protocol", "system");
@@ -348,7 +348,7 @@ public class AbstractConfigTest {
     @Test
     public void testRefreshProperties() {
         try {
-            Environment.getInstance().setExternalConfig(new HashMap<>());
+            Environment.getInstance().setExternalConfigMap(new HashMap<>());
             OverrideConfig overrideConfig = new OverrideConfig();
             overrideConfig.setAddress("override-config://127.0.0.1:2181");
             overrideConfig.setProtocol("override-config");
@@ -384,7 +384,7 @@ public class AbstractConfigTest {
             external.put("dubbo.override.key", "external");
             // @Parameter(key="key2", useKeyAsProperty=true)
             external.put("dubbo.override.key2", "external");
-            Environment.getInstance().setExternalConfig(external);
+            Environment.getInstance().setExternalConfigMap(external);
 
             overrideConfig.refresh();
 
@@ -418,7 +418,7 @@ public class AbstractConfigTest {
             external.put("dubbo.override.key", "external");
             // @Parameter(key="key2", useKeyAsProperty=true)
             external.put("dubbo.override.key2", "external");
-            Environment.getInstance().setExternalConfig(external);
+            Environment.getInstance().setExternalConfigMap(external);
 
             ConfigCenterConfig configCenter = new ConfigCenterConfig();
             configCenter.init();
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
index 6b5782e..a0ddd87 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ConfigCenterBean.java
@@ -16,11 +16,13 @@
  */
 package org.apache.dubbo.config.spring;
 
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ConfigCenterConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.spring.extension.SpringExtensionFactory;
 import org.apache.dubbo.config.support.Parameter;
+
 import org.springframework.beans.factory.BeanFactoryUtils;
 import org.springframework.beans.factory.DisposableBean;
 import org.springframework.beans.factory.InitializingBean;
@@ -46,7 +48,7 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
 
     private transient ApplicationContext applicationContext;
 
-    private Boolean auto = false;
+    private Boolean fromSpring = false;
 
     @Override
     public void setApplicationContext(ApplicationContext applicationContext) {
@@ -92,7 +94,7 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
             }
         }
 
-        if (!auto) {
+        if (!fromSpring) {
             this.init();
         }
     }
@@ -104,11 +106,11 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
 
     @Override
     public void setEnvironment(Environment environment) {
-        if (auto) {
+        if (fromSpring) {
             Map<String, String> externalProperties = getConfigurations(getConfigfile(), environment);
-            Map<String, String> appExternalProperties = getConfigurations("application." + getConfigfile(), environment);
-            org.apache.dubbo.common.config.Environment.getInstance().setExternalConfig(externalProperties);
-            org.apache.dubbo.common.config.Environment.getInstance().setAppExternalConfig(appExternalProperties);
+            Map<String, String> appExternalProperties = getConfigurations(StringUtils.isNotEmpty(getLocalconfigfile()) ? getLocalconfigfile() : ("application." + getConfigfile()), environment);
+            org.apache.dubbo.common.config.Environment.getInstance().setExternalConfigMap(externalProperties);
+            org.apache.dubbo.common.config.Environment.getInstance().setAppExternalConfigMap(appExternalProperties);
             this.init();
         }
     }
@@ -142,11 +144,11 @@ public class ConfigCenterBean extends ConfigCenterConfig implements Initializing
     }
 
     @Parameter(excluded = true)
-    public boolean isAuto() {
-        return auto;
+    public Boolean getFromSpring() {
+        return fromSpring;
     }
 
-    public void setAuto(boolean auto) {
-        this.auto = auto;
+    public void setFromSpring(Boolean fromSpring) {
+        this.fromSpring = fromSpring;
     }
 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
index b6ac23b..b1b360e 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ReferenceBean.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.config.spring;
 
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.ConsumerConfig;
 import org.apache.dubbo.config.MetadataReportConfig;
@@ -36,6 +38,7 @@ import org.springframework.context.ApplicationContext;
 import org.springframework.context.ApplicationContextAware;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -138,15 +141,35 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
                 }
             }
         }
+
+        if (StringUtils.isEmpty(getRegistryLiteral())) {
+            if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryLiteral())) {
+                setRegistry(getApplication().getRegistryLiteral());
+            }
+            if (getConsumer() != null && StringUtils.isNotEmpty(getConsumer().getRegistryLiteral())) {
+                setRegistry(getConsumer().getRegistryLiteral());
+            }
+        }
+
         if ((getRegistries() == null || getRegistries().isEmpty())
                 && (getConsumer() == null || getConsumer().getRegistries() == null || getConsumer().getRegistries().isEmpty())
                 && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
             Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
             if (registryConfigMap != null && registryConfigMap.size() > 0) {
                 List<RegistryConfig> registryConfigs = new ArrayList<>();
-                for (RegistryConfig config : registryConfigMap.values()) {
-                    if (config.isDefault() == null || config.isDefault()) {
-                        registryConfigs.add(config);
+                if (StringUtils.isNotEmpty(registryLiteral)) {
+                    Arrays.stream(Constants.COMMA_SPLIT_PATTERN.split(registryLiteral)).forEach(registryLiteral -> {
+                        if (registryConfigMap.containsKey(registryLiteral)) {
+                            registryConfigs.add(registryConfigMap.get(registryLiteral));
+                        }
+                    });
+                }
+
+                if (registryConfigs.isEmpty()) {
+                    for (RegistryConfig config : registryConfigMap.values()) {
+                        if (StringUtils.isEmpty(registryLiteral)) {
+                            registryConfigs.add(config);
+                        }
                     }
                 }
                 if (!registryConfigs.isEmpty()) {
@@ -154,6 +177,7 @@ public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean,
                 }
             }
         }
+
         if (getMetadataReportConfig() == null) {
             Map<String, MetadataReportConfig> metadataReportConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, MetadataReportConfig.class, false, false);
             if (metadataReportConfigMap != null && metadataReportConfigMap.size() == 1) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
index 74d06df..6d83374 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java
@@ -16,6 +16,8 @@
  */
 package org.apache.dubbo.config.spring;
 
+import org.apache.dubbo.common.Constants;
+import org.apache.dubbo.common.utils.StringUtils;
 import org.apache.dubbo.config.ApplicationConfig;
 import org.apache.dubbo.config.MetadataReportConfig;
 import org.apache.dubbo.config.ModuleConfig;
@@ -39,6 +41,7 @@ import org.springframework.context.ApplicationListener;
 import org.springframework.context.event.ContextRefreshedEvent;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
@@ -172,15 +175,35 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
                 }
             }
         }
+
+        if (StringUtils.isEmpty(getRegistryLiteral())) {
+            if (getApplication() != null && StringUtils.isNotEmpty(getApplication().getRegistryLiteral())) {
+                setRegistry(getApplication().getRegistryLiteral());
+            }
+            if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getRegistryLiteral())) {
+                setRegistry(getProvider().getRegistryLiteral());
+            }
+        }
+
         if ((getRegistries() == null || getRegistries().isEmpty())
                 && (getProvider() == null || getProvider().getRegistries() == null || getProvider().getRegistries().isEmpty())
                 && (getApplication() == null || getApplication().getRegistries() == null || getApplication().getRegistries().isEmpty())) {
             Map<String, RegistryConfig> registryConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, RegistryConfig.class, false, false);
             if (registryConfigMap != null && registryConfigMap.size() > 0) {
-                List<RegistryConfig> registryConfigs = new ArrayList<RegistryConfig>();
-                for (RegistryConfig config : registryConfigMap.values()) {
-                    if (config.isDefault() == null || config.isDefault()) {
-                        registryConfigs.add(config);
+                List<RegistryConfig> registryConfigs = new ArrayList<>();
+                if (StringUtils.isNotEmpty(registryLiteral)) {
+                    Arrays.stream(Constants.COMMA_SPLIT_PATTERN.split(registryLiteral)).forEach(registryLiteral -> {
+                        if (registryConfigMap.containsKey(registryLiteral)) {
+                            registryConfigs.add(registryConfigMap.get(registryLiteral));
+                        }
+                    });
+                }
+
+                if (registryConfigs.isEmpty()) {
+                    for (RegistryConfig config : registryConfigMap.values()) {
+                        if (StringUtils.isEmpty(registryLiteral)) {
+                            registryConfigs.add(config);
+                        }
                     }
                 }
                 if (!registryConfigs.isEmpty()) {
@@ -225,16 +248,35 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean
                 }
             }
         }
+
+        if (StringUtils.isEmpty(getProtocolLiteral())) {
+            if (getProvider() != null && StringUtils.isNotEmpty(getProvider().getProtocolLiteral())) {
+                setProtocol(getProvider().getProtocolLiteral());
+            }
+        }
+
         if ((getProtocols() == null || getProtocols().isEmpty())
                 && (getProvider() == null || getProvider().getProtocols() == null || getProvider().getProtocols().isEmpty())) {
             Map<String, ProtocolConfig> protocolConfigMap = applicationContext == null ? null : BeanFactoryUtils.beansOfTypeIncludingAncestors(applicationContext, ProtocolConfig.class, false, false);
             if (protocolConfigMap != null && protocolConfigMap.size() > 0) {
                 List<ProtocolConfig> protocolConfigs = new ArrayList<ProtocolConfig>();
-                for (ProtocolConfig config : protocolConfigMap.values()) {
-                    if (config.isDefault() == null || config.isDefault()) {
-                        protocolConfigs.add(config);
+                if (StringUtils.isNotEmpty(getProtocolLiteral())) {
+                    Arrays.stream(Constants.COMMA_SPLIT_PATTERN.split(getProtocolLiteral()))
+                            .forEach(protocolLiteral -> {
+                                if (protocolConfigMap.containsKey(protocolLiteral)) {
+                                    protocolConfigs.add(protocolConfigMap.get(protocolLiteral));
+                                }
+                            });
+                }
+
+                if (protocolConfigs.isEmpty()) {
+                    for (ProtocolConfig config : protocolConfigMap.values()) {
+                        if (StringUtils.isEmpty(protocolLiteral)) {
+                            protocolConfigs.add(config);
+                        }
                     }
                 }
+
                 if (!protocolConfigs.isEmpty()) {
                     super.setProtocols(protocolConfigs);
                 }
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfiguration.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfiguration.java
index e154baf..cd5ddce 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfiguration.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboConfigConfiguration.java
@@ -27,6 +27,7 @@ import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.RegistryDataConfig;
 import org.apache.dubbo.config.spring.ConfigCenterBean;
+
 import org.springframework.context.annotation.Configuration;
 
 /**
@@ -57,8 +58,7 @@ public class DubboConfigConfiguration {
             @EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
             @EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
             @EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
-            @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class),
-            @EnableDubboConfigBinding(prefix = "dubbo.configcenter", type = ConfigCenterBean.class),
+            @EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class), @EnableDubboConfigBinding(prefix = "dubbo.config-center", type = ConfigCenterBean.class),
             @EnableDubboConfigBinding(prefix = "dubbo.registrydata", type = RegistryDataConfig.class),
             @EnableDubboConfigBinding(prefix = "dubbo.metadatareport", type = MetadataReportConfig.class)
     })
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
index e38d1af..58e92b0 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
@@ -17,7 +17,6 @@
 package org.apache.dubbo.config.spring.schema;
 
 import org.apache.dubbo.common.Constants;
-import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.Logger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.utils.ReflectUtils;
@@ -30,7 +29,6 @@ import org.apache.dubbo.config.ProviderConfig;
 import org.apache.dubbo.config.RegistryConfig;
 import org.apache.dubbo.config.spring.ReferenceBean;
 import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.rpc.Protocol;
 
 import org.springframework.beans.PropertyValue;
 import org.springframework.beans.factory.config.BeanDefinition;
@@ -166,12 +164,8 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
                                 RegistryConfig registryConfig = new RegistryConfig();
                                 registryConfig.setAddress(RegistryConfig.NO_AVAILABLE);
                                 beanDefinition.getPropertyValues().addPropertyValue(property, registryConfig);
-                            } else if ("registry".equals(property) && value.indexOf(',') != -1) {
-                                parseMultiRef("registries", value, beanDefinition, parserContext);
-                            } else if ("provider".equals(property) && value.indexOf(',') != -1) {
-                                parseMultiRef("providers", value, beanDefinition, parserContext);
-                            } else if ("protocol".equals(property) && value.indexOf(',') != -1) {
-                                parseMultiRef("protocols", value, beanDefinition, parserContext);
+                            } else if ("provider".equals(property) || "protocol".equals(property) || "registry".equals(property)) {
+                                beanDefinition.getPropertyValues().addPropertyValue(property, value);
                             } else {
                                 Object reference;
                                 if (isPrimitive(type)) {
@@ -185,17 +179,6 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
                                         value = null;
                                     }
                                     reference = value;
-                                } else if ("protocol".equals(property)
-                                        && ExtensionLoader.getExtensionLoader(Protocol.class).hasExtension(value)
-                                        && (!parserContext.getRegistry().containsBeanDefinition(value)
-                                        || !ProtocolConfig.class.getName().equals(parserContext.getRegistry().getBeanDefinition(value).getBeanClassName()))) {
-                                    if ("dubbo:provider".equals(element.getTagName())) {
-                                        logger.warn("Recommended replace <dubbo:provider protocol=\"" + value + "\" ... /> to <dubbo:protocol name=\"" + value + "\" ... />");
-                                    }
-                                    // backward compatibility
-                                    ProtocolConfig protocol = new ProtocolConfig();
-                                    protocol.setName(value);
-                                    reference = protocol;
                                 } else if ("onreturn".equals(property)) {
                                     int index = value.lastIndexOf(".");
                                     String returnRef = value.substring(0, index);
@@ -256,23 +239,6 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
                 || cls == String.class || cls == Date.class || cls == Class.class;
     }
 
-    @SuppressWarnings("unchecked")
-    private static void parseMultiRef(String property, String value, RootBeanDefinition beanDefinition,
-                                      ParserContext parserContext) {
-        String[] values = value.split("\\s*[,]+\\s*");
-        ManagedList list = null;
-        for (int i = 0; i < values.length; i++) {
-            String v = values[i];
-            if (v != null && v.length() > 0) {
-                if (list == null) {
-                    list = new ManagedList();
-                }
-                list.add(new RuntimeBeanReference(v));
-            }
-        }
-        beanDefinition.getPropertyValues().addPropertyValue(property, list);
-    }
-
     private static void parseNested(Element element, ParserContext parserContext, Class<?> beanClass, boolean required, String tag, String property, String ref, BeanDefinition beanDefinition) {
         NodeList nodeList = element.getChildNodes();
         if (nodeList != null && nodeList.getLength() > 0) {
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
index afbc26b..d4ea6ed 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandler.java
@@ -46,7 +46,7 @@ public class DubboNamespaceHandler extends NamespaceHandlerSupport {
         registerBeanDefinitionParser("application", new DubboBeanDefinitionParser(ApplicationConfig.class, true));
         registerBeanDefinitionParser("module", new DubboBeanDefinitionParser(ModuleConfig.class, true));
         registerBeanDefinitionParser("registry", new DubboBeanDefinitionParser(RegistryConfig.class, true));
-        registerBeanDefinitionParser("configcenter", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
+        registerBeanDefinitionParser("config-center", new DubboBeanDefinitionParser(ConfigCenterBean.class, true));
         registerBeanDefinitionParser("monitor", new DubboBeanDefinitionParser(MonitorConfig.class, true));
         registerBeanDefinitionParser("provider", new DubboBeanDefinitionParser(ProviderConfig.class, true));
         registerBeanDefinitionParser("consumer", new DubboBeanDefinitionParser(ConsumerConfig.class, true));
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
index f68a47d..87f2f11 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/compat/dubbo.xsd
@@ -659,7 +659,7 @@
                 <xsd:documentation><![CDATA[ The request timeout. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
-        <xsd:attribute name="priority" type="xsd:boolean" use="optional">
+        <xsd:attribute name="enable" type="xsd:boolean" use="optional">
             <xsd:annotation>
                 <xsd:documentation>
                     <![CDATA[ Whether the configs from config center has the highest priority. ]]></xsd:documentation>
@@ -1343,7 +1343,7 @@
         </xsd:annotation>
     </xsd:element>
 
-    <xsd:element name="configcenter" type="configCenterType">
+    <xsd:element name="config-center" type="configCenterType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The config center config ]]></xsd:documentation>
         </xsd:annotation>
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index 294c1b5..c36e59c 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -653,7 +653,7 @@
                 <xsd:documentation><![CDATA[ The request timeout. ]]></xsd:documentation>
             </xsd:annotation>
         </xsd:attribute>
-        <xsd:attribute name="priority" type="xsd:boolean" use="optional">
+        <xsd:attribute name="enable" type="xsd:boolean" use="optional">
             <xsd:annotation>
                 <xsd:documentation>
                     <![CDATA[ Whether the configs from config center has the highest priority. ]]></xsd:documentation>
@@ -1332,7 +1332,7 @@
         </xsd:annotation>
     </xsd:element>
 
-    <xsd:element name="configcenter" type="configCenterType">
+    <xsd:element name="config-center" type="configCenterType">
         <xsd:annotation>
             <xsd:documentation><![CDATA[ The config center config ]]></xsd:documentation>
         </xsd:annotation>