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 2021/06/24 10:10:59 UTC

[dubbo] branch 3.0 updated: Add ServiceListener for ServiceConfig (#8134)

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

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


The following commit(s) were added to refs/heads/3.0 by this push:
     new 9bccd5c  Add ServiceListener for ServiceConfig (#8134)
9bccd5c is described below

commit 9bccd5cfdd131e77c69cb2d45e970ffb10cf6c3c
Author: Gong Dewei <ky...@qq.com>
AuthorDate: Thu Jun 24 18:10:45 2021 +0800

    Add ServiceListener for ServiceConfig (#8134)
---
 .../org/apache/dubbo/config/ServiceConfig.java     | 31 ++++++++++++++-
 .../org/apache/dubbo/config/ServiceListener.java   | 38 ++++++++++++++++++
 .../dubbo/config/bootstrap/DubboBootstrap.java     |  8 ++--
 .../org/apache/dubbo/config/ServiceConfigTest.java | 28 +++++++++++++-
 .../dubbo/config/mock/MockServiceListener.java     | 45 ++++++++++++++++++++++
 .../org.apache.dubbo.config.ServiceListener        |  1 +
 6 files changed, 144 insertions(+), 7 deletions(-)

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 2463147..8d5893b 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
@@ -142,6 +142,8 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
      */
     private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
 
+    private List<ServiceListener> serviceListeners = new ArrayList<>();
+
     public ServiceConfig() {
     }
 
@@ -182,15 +184,20 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             exporters.clear();
         }
         unexported = true;
+        onUnexpoted();
     }
 
     public void init() {
         if (this.initialized.compareAndSet(false, true)) {
             if (this.bootstrap == null) {
-                this.bootstrap = DubboBootstrap.getInstance();
+                this.setBootstrap(DubboBootstrap.getInstance());
                 this.bootstrap.initialize();
             }
 
+            // load ServiceListeners from extension
+            ExtensionLoader<ServiceListener> extensionLoader = ExtensionLoader.getExtensionLoader(ServiceListener.class);
+            this.serviceListeners.addAll(extensionLoader.getSupportedExtensionInstances());
+
             this.checkAndUpdateSubConfigs();
         }
 
@@ -203,7 +210,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     public synchronized void export() {
         if (this.shouldExport() && !this.exported) {
             this.init();
-            this.bootstrap.service(this);
 
             // check bootstrap state
             if (!bootstrap.isInitialized()) {
@@ -236,6 +242,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
             ServiceNameMapping serviceNameMapping = ServiceNameMapping.getDefaultExtension();
             serviceNameMapping.map(url);
         });
+        onExported();
     }
 
     private void checkAndUpdateSubConfigs() {
@@ -748,4 +755,24 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
     public void setBootstrap(DubboBootstrap bootstrap) {
         this.bootstrap = bootstrap;
     }
+
+    public void addServiceListener(ServiceListener listener) {
+        this.serviceListeners.add(listener);
+    }
+
+    public boolean removeServiceListener(ServiceListener listener) {
+        return this.serviceListeners.remove(listener);
+    }
+
+    protected void onExported() {
+        for (ServiceListener serviceListener : this.serviceListeners) {
+            serviceListener.exported(this);
+        }
+    }
+
+    protected void onUnexpoted() {
+        for (ServiceListener serviceListener : this.serviceListeners) {
+            serviceListener.unexported(this);
+        }
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceListener.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceListener.java
new file mode 100644
index 0000000..451356c
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceListener.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.extension.SPI;
+
+/**
+ * Listener for service config
+ */
+@SPI
+public interface ServiceListener {
+
+    /**
+     * Callback when ServiceConfig is exported
+     * @param sc
+     */
+    void exported(ServiceConfig sc);
+
+    /**
+     * Callback when ServiceConfig is unexported
+     * @param sc
+     */
+    void unexported(ServiceConfig sc);
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index 85b4853..f15d25e 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -257,9 +257,9 @@ public class DubboBootstrap {
         DubboShutdownHook.getDubboShutdownHook().unregister();
     }
 
-    private boolean isOnlyRegisterProvider() {
+    private boolean isRegisterConsumerInstance() {
         Boolean registerConsumer = getApplication().getRegisterConsumer();
-        return registerConsumer == null || !registerConsumer;
+        return Boolean.TRUE.equals(registerConsumer);
     }
 
     private String getMetadataType() {
@@ -1095,8 +1095,8 @@ public class DubboBootstrap {
             // 1. export Dubbo Services
             exportServices();
 
-            // Not only provider register
-            if (!isOnlyRegisterProvider() || hasExportedServices()) {
+            // If register consumer instance or has exported services
+            if (isRegisterConsumerInstance() || hasExportedServices()) {
                 // 2. export MetadataService
                 exportMetadataService();
                 // 3. Register the local ServiceInstance if required
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
index 3aebdd0..a4c6a62 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ServiceConfigTest.java
@@ -18,10 +18,12 @@
 package org.apache.dubbo.config;
 
 import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
 import org.apache.dubbo.config.api.DemoService;
 import org.apache.dubbo.config.api.Greeting;
 import org.apache.dubbo.config.mock.MockProtocol2;
 import org.apache.dubbo.config.mock.MockRegistryFactory2;
+import org.apache.dubbo.config.mock.MockServiceListener;
 import org.apache.dubbo.config.mock.TestProxyFactory;
 import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
 import org.apache.dubbo.registry.Registry;
@@ -40,6 +42,7 @@ import org.mockito.Mockito;
 
 import java.util.Collections;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
@@ -67,6 +70,8 @@ import static org.hamcrest.Matchers.hasEntry;
 import static org.hamcrest.Matchers.hasKey;
 import static org.hamcrest.Matchers.hasSize;
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.Mockito.withSettings;
 
@@ -288,7 +293,7 @@ public class ServiceConfigTest {
     @Test
     public void testApplicationInUrl() {
         service.export();
-        Assertions.assertNotNull(service.toUrl().getApplication());
+        assertNotNull(service.toUrl().getApplication());
         Assertions.assertEquals("app", service.toUrl().getApplication());
     }
 
@@ -335,4 +340,25 @@ public class ServiceConfigTest {
         assertThat(url.getParameters(), hasEntry(SIDE_KEY, PROVIDER));
         Mockito.verify(protocolDelegate).export(Mockito.any(Invoker.class));
     }
+
+    @Test
+    public void testServiceListener() {
+        ExtensionLoader<ServiceListener> extensionLoader = ExtensionLoader.getExtensionLoader(ServiceListener.class);
+        Set<ServiceListener> serviceListeners = extensionLoader.getSupportedExtensionInstances();
+        MockServiceListener mockServiceListener = null;
+        for (ServiceListener serviceListener : serviceListeners) {
+            if (serviceListener instanceof MockServiceListener) {
+                mockServiceListener = (MockServiceListener) serviceListener;
+            }
+        }
+        assertNotNull(mockServiceListener);
+        mockServiceListener.clearExportedServices();
+
+        service.export();
+
+        Map<String, ServiceConfig> exportedServices = mockServiceListener.getExportedServices();
+        assertEquals(1, exportedServices.size());
+        ServiceConfig serviceConfig = exportedServices.get(service.getUniqueServiceName());
+        assertSame(service, serviceConfig);
+    }
 }
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceListener.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceListener.java
new file mode 100644
index 0000000..5cc31b8
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/mock/MockServiceListener.java
@@ -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.mock;
+
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.ServiceListener;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class MockServiceListener implements ServiceListener {
+
+    private Map<String, ServiceConfig> exportedServices = new ConcurrentHashMap<>();
+
+    @Override
+    public void exported(ServiceConfig sc) {
+        exportedServices.put(sc.getUniqueServiceName(), sc);
+    }
+
+    @Override
+    public void unexported(ServiceConfig sc) {
+    }
+
+    public Map<String, ServiceConfig> getExportedServices() {
+        return exportedServices;
+    }
+
+    public void clearExportedServices() {
+        exportedServices.clear();
+    }
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.config.ServiceListener b/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.config.ServiceListener
new file mode 100644
index 0000000..d7ce28b
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/resources/META-INF/services/org.apache.dubbo.config.ServiceListener
@@ -0,0 +1 @@
+mock=org.apache.dubbo.config.mock.MockServiceListener