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

liujun pushed a commit to branch 3.2
in repository https://gitbox.apache.org/repos/asf/dubbo.git


The following commit(s) were added to refs/heads/3.2 by this push:
     new 9df0d154a5 Customize parameters for interface-level registration 
(#13304)
9df0d154a5 is described below

commit 9df0d154a5ff77de6572dce30cf8fb0f6d08963a
Author: TomlongTK <[email protected]>
AuthorDate: Wed Dec 20 21:21:49 2023 +0800

    Customize parameters for interface-level registration (#13304)
---
 dubbo-distribution/dubbo-all/pom.xml               |   4 +
 .../integration/DefaultServiceURLCustomizer.java   | 120 ++++++++++++++++++++
 .../registry/integration/RegistryProtocol.java     | 121 +++++----------------
 .../registry/integration/ServiceURLCustomizer.java |  39 +++++++
 ...dubbo.registry.integration.ServiceURLCustomizer |   1 +
 5 files changed, 193 insertions(+), 92 deletions(-)

diff --git a/dubbo-distribution/dubbo-all/pom.xml 
b/dubbo-distribution/dubbo-all/pom.xml
index 99187e7f11..783dbbe1a9 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -934,6 +934,10 @@
                 <transformer 
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                   
<resource>META-INF/dubbo/internal/org.apache.dubbo.rpc.model.PackableMethodFactory</resource>
                 </transformer>
+
+                <transformer 
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+                  
<resource>META-INF/dubbo/internal/org.apache.dubbo.registry.integration.ServiceURLCustomizer</resource>
+                </transformer>
               </transformers>
               <filters>
                 <filter>
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DefaultServiceURLCustomizer.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DefaultServiceURLCustomizer.java
new file mode 100644
index 0000000000..2473df54b7
--- /dev/null
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/DefaultServiceURLCustomizer.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.registry.integration;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.util.Arrays;
+import java.util.Map;
+import java.util.stream.Stream;
+
+import static org.apache.dubbo.common.constants.CommonConstants.ALIVE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.BACKGROUND_KEY;
+import static 
org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
+import static 
org.apache.dubbo.common.constants.CommonConstants.CORE_THREADS_KEY;
+import static 
org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE;
+import static org.apache.dubbo.common.constants.CommonConstants.EXTRA_KEYS_KEY;
+import static 
org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.QUEUES_KEY;
+import static 
org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
+import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.THREADS_KEY;
+import static 
org.apache.dubbo.common.constants.CommonConstants.THREAD_NAME_KEY;
+import static org.apache.dubbo.common.constants.FilterConstants.VALIDATION_KEY;
+import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
+import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
+import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
+import static org.apache.dubbo.common.constants.QosConstants.QOS_PORT;
+import static 
org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
+import static org.apache.dubbo.registry.Constants.SIMPLIFIED_KEY;
+import static 
org.apache.dubbo.registry.integration.RegistryProtocol.DEFAULT_REGISTER_PROVIDER_KEYS;
+import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
+import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
+import static org.apache.dubbo.rpc.Constants.INTERFACES;
+
+public class DefaultServiceURLCustomizer implements ServiceURLCustomizer {
+
+    private static final String[] excludedParameters = new String[] {
+        MONITOR_KEY,
+        BIND_IP_KEY,
+        BIND_PORT_KEY,
+        QOS_ENABLE,
+        QOS_HOST,
+        QOS_PORT,
+        ACCEPT_FOREIGN_IP,
+        VALIDATION_KEY,
+        INTERFACES,
+        REGISTER_MODE_KEY,
+        PID_KEY,
+        REGISTRY_LOCAL_FILE_CACHE_ENABLED,
+        EXECUTOR_MANAGEMENT_MODE,
+        BACKGROUND_KEY,
+        ANYHOST_KEY,
+        THREAD_NAME_KEY,
+        THREADPOOL_KEY,
+        ALIVE_KEY,
+        QUEUES_KEY,
+        CORE_THREADS_KEY,
+        THREADS_KEY
+    };
+
+    @Override
+    public URL customize(URL serviceURL, ApplicationModel applicationModel) {
+        boolean simplified = (boolean) serviceURL.getAttribute(SIMPLIFIED_KEY, 
false);
+        if (simplified) {
+            String extraKeys = (String) 
serviceURL.getAttribute(EXTRA_KEYS_KEY, "");
+            // if path is not the same as interface name then we should keep 
INTERFACE_KEY,
+            // otherwise, the registry structure of zookeeper would be 
'/dubbo/path/providers',
+            // but what we expect is '/dubbo/interface/providers'
+            if 
(!serviceURL.getPath().equals(serviceURL.getParameter(INTERFACE_KEY))) {
+                if (StringUtils.isNotEmpty(extraKeys)) {
+                    extraKeys += ",";
+                }
+                extraKeys += INTERFACE_KEY;
+            }
+            String[] paramsToRegistry = Stream.concat(
+                            Arrays.stream(DEFAULT_REGISTER_PROVIDER_KEYS),
+                            
Arrays.stream(COMMA_SPLIT_PATTERN.split(extraKeys)))
+                    .toArray(String[]::new);
+            return URL.valueOf(serviceURL, paramsToRegistry, 
serviceURL.getParameter(METHODS_KEY, (String[]) null));
+        }
+        return 
serviceURL.removeParameters(getFilteredKeys(serviceURL)).removeParameters(excludedParameters);
+    }
+
+    @Override
+    public int getPriority() {
+        return MAX_PRIORITY;
+    }
+
+    private String[] getFilteredKeys(URL url) {
+        Map<String, String> params = url.getParameters();
+        if (CollectionUtils.isNotEmptyMap(params)) {
+            return params.keySet().stream()
+                    .filter(k -> k.startsWith(HIDE_KEY_PREFIX))
+                    .toArray(String[]::new);
+        }
+        return new String[0];
+    }
+}
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
index 6fb5f43f32..f05b8bdd94 100644
--- 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryProtocol.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
 import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
 import org.apache.dubbo.common.constants.RegistryConstants;
 import org.apache.dubbo.common.deploy.ApplicationDeployer;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
 import org.apache.dubbo.common.logger.LoggerFactory;
 import org.apache.dubbo.common.threadpool.manager.FrameworkExecutorRepository;
@@ -77,46 +78,32 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
-import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.BACKGROUND_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
 import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER;
 import static 
org.apache.dubbo.common.constants.CommonConstants.DUBBO_VERSION_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.ENABLED_KEY;
-import static 
org.apache.dubbo.common.constants.CommonConstants.EXECUTOR_MANAGEMENT_MODE;
 import static org.apache.dubbo.common.constants.CommonConstants.EXTRA_KEYS_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static 
org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
 import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.IPV6_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
 import static 
org.apache.dubbo.common.constants.CommonConstants.PACKABLE_METHOD_FACTORY_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
-import static 
org.apache.dubbo.common.constants.CommonConstants.REGISTRY_LOCAL_FILE_CACHE_ENABLED;
 import static 
org.apache.dubbo.common.constants.CommonConstants.REGISTRY_PROTOCOL_LISTENER_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.RELEASE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
 import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
-import static org.apache.dubbo.common.constants.FilterConstants.VALIDATION_KEY;
 import static 
org.apache.dubbo.common.constants.LoggerCodeConstants.INTERNAL_ERROR;
 import static 
org.apache.dubbo.common.constants.LoggerCodeConstants.REGISTRY_UNSUPPORTED_CATEGORY;
-import static org.apache.dubbo.common.constants.QosConstants.ACCEPT_FOREIGN_IP;
-import static org.apache.dubbo.common.constants.QosConstants.QOS_ENABLE;
-import static org.apache.dubbo.common.constants.QosConstants.QOS_HOST;
-import static org.apache.dubbo.common.constants.QosConstants.QOS_PORT;
 import static 
org.apache.dubbo.common.constants.RegistryConstants.ALL_CATEGORIES;
 import static org.apache.dubbo.common.constants.RegistryConstants.CATEGORY_KEY;
 import static 
org.apache.dubbo.common.constants.RegistryConstants.CONFIGURATORS_CATEGORY;
 import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
 import static 
org.apache.dubbo.common.constants.RegistryConstants.OVERRIDE_PROTOCOL;
-import static 
org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
 import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
 import static 
org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
 import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
@@ -130,8 +117,6 @@ import static 
org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
 import static org.apache.dubbo.registry.Constants.REGISTER_KEY;
 import static org.apache.dubbo.registry.Constants.REGISTRY_RETRY_PERIOD_KEY;
 import static org.apache.dubbo.registry.Constants.SIMPLIFIED_KEY;
-import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
-import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
 import static org.apache.dubbo.remoting.Constants.CHECK_KEY;
 import static org.apache.dubbo.remoting.Constants.CODEC_KEY;
 import static org.apache.dubbo.remoting.Constants.CONNECTIONS_KEY;
@@ -140,7 +125,6 @@ import static 
org.apache.dubbo.remoting.Constants.PREFER_SERIALIZATION_KEY;
 import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
 import static org.apache.dubbo.rpc.Constants.DEPRECATED_KEY;
 import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
-import static org.apache.dubbo.rpc.Constants.INTERFACES;
 import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
 import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
 import static org.apache.dubbo.rpc.cluster.Constants.CONSUMER_URL_KEY;
@@ -184,18 +168,6 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
     private FrameworkModel frameworkModel;
     private ExporterFactory exporterFactory;
 
-    // Filter the parameters that do not need to be output in url(Starting 
with .)
-    private static String[] getFilteredKeys(URL url) {
-        Map<String, String> params = url.getParameters();
-        if (CollectionUtils.isNotEmptyMap(params)) {
-            return params.keySet().stream()
-                    .filter(k -> k.startsWith(HIDE_KEY_PREFIX))
-                    .toArray(String[]::new);
-        } else {
-            return new String[0];
-        }
-    }
-
     public RegistryProtocol() {}
 
     @Override
@@ -292,7 +264,7 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
 
         // url to registry
         final Registry registry = getRegistry(registryUrl);
-        final URL registeredProviderUrl = getUrlToRegistry(providerUrl, 
registryUrl);
+        final URL registeredProviderUrl = customizeURL(providerUrl, 
registryUrl);
 
         // decide if we need to delay publish (provider itself and registry 
should both need to register)
         boolean register = providerUrl.getParameter(REGISTER_KEY, true) && 
registryUrl.getParameter(REGISTER_KEY, true);
@@ -354,10 +326,10 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
 
         ReferenceCountExporter<?> exporter =
                 exporterFactory.createExporter(providerUrlKey, () -> 
protocol.export(invokerDelegate));
-        return (ExporterChangeableWrapper<T>) 
bounds.computeIfAbsent(providerUrlKey, _k -> new ConcurrentHashMap<>())
-                .computeIfAbsent(registryUrlKey, s -> {
-                    return new 
ExporterChangeableWrapper<>((ReferenceCountExporter<T>) exporter, 
originInvoker);
-                });
+        return (ExporterChangeableWrapper<T>) 
bounds.computeIfAbsent(providerUrlKey, k -> new ConcurrentHashMap<>())
+                .computeIfAbsent(
+                        registryUrlKey,
+                        s -> new 
ExporterChangeableWrapper<>((ReferenceCountExporter<T>) exporter, 
originInvoker));
     }
 
     public <T> void reExport(Exporter<T> exporter, URL newInvokerUrl) {
@@ -402,10 +374,10 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
         URL registeredUrl = exporter.getRegisterUrl();
 
         URL registryUrl = getRegistryUrl(originInvoker);
-        URL newProviderUrl = getUrlToRegistry(newInvokerUrl, registryUrl);
+        URL newProviderUrl = customizeURL(newInvokerUrl, registryUrl);
 
         // update local exporter
-        Invoker<T> invokerDelegate = new InvokerDelegate<T>(originInvoker, 
newInvokerUrl);
+        Invoker<T> invokerDelegate = new InvokerDelegate<>(originInvoker, 
newInvokerUrl);
         exporter.setExporter(protocol.export(invokerDelegate));
 
         // update registry
@@ -501,45 +473,19 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
     /**
      * Return the url that is registered to the registry and filter the url 
parameter once
      *
-     * @param providerUrl
+     * @param providerUrl provider service url
+     * @param registryUrl registry center url
      * @return url to registry.
      */
-    private URL getUrlToRegistry(final URL providerUrl, final URL registryUrl) 
{
-        // The address you see at the registry
-        if (!registryUrl.getParameter(SIMPLIFIED_KEY, false)) {
-            return providerUrl
-                    .removeParameters(getFilteredKeys(providerUrl))
-                    .removeParameters(
-                            MONITOR_KEY,
-                            BIND_IP_KEY,
-                            BIND_PORT_KEY,
-                            QOS_ENABLE,
-                            QOS_HOST,
-                            QOS_PORT,
-                            ACCEPT_FOREIGN_IP,
-                            VALIDATION_KEY,
-                            INTERFACES,
-                            REGISTER_MODE_KEY,
-                            PID_KEY,
-                            REGISTRY_LOCAL_FILE_CACHE_ENABLED,
-                            EXECUTOR_MANAGEMENT_MODE,
-                            BACKGROUND_KEY,
-                            ANYHOST_KEY);
-        } else {
-            String extraKeys = registryUrl.getParameter(EXTRA_KEYS_KEY, "");
-            // if path is not the same as interface name then we should keep 
INTERFACE_KEY,
-            // otherwise, the registry structure of zookeeper would be 
'/dubbo/path/providers',
-            // but what we expect is '/dubbo/interface/providers'
-            if 
(!providerUrl.getPath().equals(providerUrl.getParameter(INTERFACE_KEY))) {
-                if (StringUtils.isNotEmpty(extraKeys)) {
-                    extraKeys += ",";
-                }
-                extraKeys += INTERFACE_KEY;
-            }
-            String[] paramsToRegistry =
-                    getParamsToRegistry(DEFAULT_REGISTER_PROVIDER_KEYS, 
COMMA_SPLIT_PATTERN.split(extraKeys));
-            return URL.valueOf(providerUrl, paramsToRegistry, 
providerUrl.getParameter(METHODS_KEY, (String[]) null));
+    private URL customizeURL(final URL providerUrl, final URL registryUrl) {
+        URL newProviderURL = providerUrl.putAttribute(SIMPLIFIED_KEY, 
registryUrl.getParameter(SIMPLIFIED_KEY, false));
+        newProviderURL = newProviderURL.putAttribute(EXTRA_KEYS_KEY, 
registryUrl.getParameter(EXTRA_KEYS_KEY, ""));
+        ApplicationModel applicationModel = 
providerUrl.getOrDefaultApplicationModel();
+        ExtensionLoader<ServiceURLCustomizer> loader = 
applicationModel.getExtensionLoader(ServiceURLCustomizer.class);
+        for (ServiceURLCustomizer customizer : 
loader.getSupportedExtensionInstances()) {
+            newProviderURL = customizer.customize(newProviderURL, 
applicationModel);
         }
+        return newProviderURL;
     }
 
     private URL getSubscribedOverrideUrl(URL registeredProviderUrl) {
@@ -571,14 +517,12 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
      */
     private String getProviderUrlKey(final Invoker<?> originInvoker) {
         URL providerUrl = getProviderUrl(originInvoker);
-        String key = providerUrl.removeParameters(DYNAMIC_KEY, 
ENABLED_KEY).toFullString();
-        return key;
+        return providerUrl.removeParameters(DYNAMIC_KEY, 
ENABLED_KEY).toFullString();
     }
 
     private String getRegistryUrlKey(final Invoker<?> originInvoker) {
         URL registryUrl = getRegistryUrl(originInvoker);
-        String key = registryUrl.removeParameters(DYNAMIC_KEY, 
ENABLED_KEY).toFullString();
-        return key;
+        return registryUrl.removeParameters(DYNAMIC_KEY, 
ENABLED_KEY).toFullString();
     }
 
     @Override
@@ -633,7 +577,7 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
             Class<T> type,
             URL url,
             URL consumerUrl) {
-        return new ServiceDiscoveryMigrationInvoker<T>(registryProtocol, 
cluster, registry, type, url, consumerUrl);
+        return new ServiceDiscoveryMigrationInvoker<>(registryProtocol, 
cluster, registry, type, url, consumerUrl);
     }
 
     /**
@@ -721,15 +665,6 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
                 .getActivateExtension(url, REGISTRY_PROTOCOL_LISTENER_KEY);
     }
 
-    // available to test
-    public String[] getParamsToRegistry(String[] defaultKeys, String[] 
additionalParameterKeys) {
-        int additionalLen = additionalParameterKeys.length;
-        String[] registryParams = new String[defaultKeys.length + 
additionalLen];
-        System.arraycopy(defaultKeys, 0, registryParams, 0, 
defaultKeys.length);
-        System.arraycopy(additionalParameterKeys, 0, registryParams, 
defaultKeys.length, additionalLen);
-        return registryParams;
-    }
-
     @Override
     public void destroy() {
         // FIXME all application models in framework are removed at this moment
@@ -757,7 +692,10 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
                         // already removed
                         continue;
                     }
-                    if 
(moduleModel.getServiceRepository().getExportedServices().size() > 0) {
+                    if (!moduleModel
+                            .getServiceRepository()
+                            .getExportedServices()
+                            .isEmpty()) {
                         moduleModel
                                 
.getExtensionLoader(GovernanceRuleRepository.class)
                                 .getDefaultExtension()
@@ -1166,11 +1104,10 @@ public class RegistryProtocol implements Protocol, 
ScopeModelAware {
                                         .getConfiguration()
                                         .convert(Boolean.class, 
ENABLE_CONFIGURATION_LISTEN, true)) {
                                     for (ModuleModel moduleModel : 
applicationModel.getPubModuleModels()) {
-                                        if (moduleModel
-                                                        .getServiceRepository()
-                                                        .getExportedServices()
-                                                        .size()
-                                                > 0) {
+                                        if (!moduleModel
+                                                .getServiceRepository()
+                                                .getExportedServices()
+                                                .isEmpty()) {
                                             moduleModel
                                                     
.getExtensionLoader(GovernanceRuleRepository.class)
                                                     .getDefaultExtension()
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/ServiceURLCustomizer.java
 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/ServiceURLCustomizer.java
new file mode 100644
index 0000000000..8229ba5875
--- /dev/null
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/ServiceURLCustomizer.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.registry.integration;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import static org.apache.dubbo.common.extension.ExtensionScope.APPLICATION;
+
+/**
+ * Customize parameters for interface-level registration
+ */
+@SPI(scope = APPLICATION)
+public interface ServiceURLCustomizer extends Prioritized {
+
+    /**
+     * Customizes {@link URL the service url}
+     *
+     * @param serviceURL {@link URL the service url}
+     * @return new service url
+     */
+    URL customize(URL serviceURL, ApplicationModel applicationModel);
+}
diff --git 
a/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.integration.ServiceURLCustomizer
 
b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.integration.ServiceURLCustomizer
new file mode 100644
index 0000000000..83a3432c9b
--- /dev/null
+++ 
b/dubbo-registry/dubbo-registry-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.registry.integration.ServiceURLCustomizer
@@ -0,0 +1 @@
+default=org.apache.dubbo.registry.integration.DefaultServiceURLCustomizer

Reply via email to