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 86c5ed45f9a..ccd5b6b9943 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 @@ -22,6 +22,8 @@ import org.apache.dubbo.common.Version; import org.apache.dubbo.common.bytecode.Wrapper; import org.apache.dubbo.common.config.Environment; +import org.apache.dubbo.common.event.Event; +import org.apache.dubbo.common.event.EventDispatcher; import org.apache.dubbo.common.extension.ExtensionLoader; import org.apache.dubbo.common.utils.ClassUtils; import org.apache.dubbo.common.utils.CollectionUtils; @@ -30,6 +32,8 @@ import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.event.ServiceConfigExportedEvent; +import org.apache.dubbo.config.event.ServiceConfigUnExportedEvent; import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker; import org.apache.dubbo.config.support.Parameter; import org.apache.dubbo.metadata.integration.MetadataReportService; @@ -76,6 +80,8 @@ public class ServiceConfig extends AbstractServiceConfig { private static final long serialVersionUID = 3033787999037024738L; + private static final EventDispatcher eventDispathcer = EventDispatcher.getDefaultExtension(); + /** * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios. * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}. @@ -387,6 +393,13 @@ protected synchronized void doExport() { path = interfaceName; } doExportUrls(); + + // dispatch a ServiceConfigExportedEvent since 2.7.2 + dispatch(new ServiceConfigExportedEvent(this)); + } + + private void dispatch(Event event) { + eventDispathcer.dispatch(event); } private void checkRef() { @@ -419,6 +432,9 @@ public synchronized void unexport() { exporters.clear(); } unexported = true; + + // dispatch a ServiceConfigUnExportedEvent since 2.7.2 + dispatch(new ServiceConfigUnExportedEvent(this)); } @SuppressWarnings({"unchecked", "rawtypes"}) diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigExportedEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigExportedEvent.java new file mode 100644 index 00000000000..047a8f7a940 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigExportedEvent.java @@ -0,0 +1,36 @@ +/* + * 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.event; + +import org.apache.dubbo.common.event.Event; +import org.apache.dubbo.config.ServiceConfig; + +/** + * {@link ServiceConfig} event post-{@link ServiceConfig#export() export} + * + * @since 2.7.2 + */ +public class ServiceConfigExportedEvent extends Event { + + public ServiceConfigExportedEvent(ServiceConfig source) { + super(source); + } + + public ServiceConfig getServiceConfig() { + return (ServiceConfig) getSource(); + } +} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigUnExportedEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigUnExportedEvent.java new file mode 100644 index 00000000000..4f5af9b9ce8 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ServiceConfigUnExportedEvent.java @@ -0,0 +1,36 @@ +/* + * 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.event; + +import org.apache.dubbo.common.event.Event; +import org.apache.dubbo.config.ServiceConfig; + +/** + * {@link ServiceConfig} event post-{@link ServiceConfig#unexport() unexport} + * + * @since 2.7.2 + */ +public class ServiceConfigUnExportedEvent extends Event { + + public ServiceConfigUnExportedEvent(ServiceConfig source) { + super(source); + } + + public ServiceConfig getServiceConfig() { + return (ServiceConfig) getSource(); + } +} 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 2dff18b5af5..45c78a70ab3 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 @@ -19,9 +19,13 @@ import org.apache.dubbo.common.Constants; import org.apache.dubbo.common.URL; +import org.apache.dubbo.common.event.EventDispatcher; +import org.apache.dubbo.common.event.EventListener; import org.apache.dubbo.config.api.DemoService; import org.apache.dubbo.config.api.Greeting; import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.event.ServiceConfigExportedEvent; +import org.apache.dubbo.config.event.ServiceConfigUnExportedEvent; import org.apache.dubbo.config.mock.MockProtocol2; import org.apache.dubbo.config.mock.MockRegistryFactory2; import org.apache.dubbo.config.mock.TestProxyFactory; @@ -41,6 +45,7 @@ import java.util.Collections; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicReference; import static org.apache.dubbo.common.Constants.GENERIC_SERIALIZATION_BEAN; import static org.apache.dubbo.common.Constants.GENERIC_SERIALIZATION_DEFAULT; @@ -64,6 +69,8 @@ public class ServiceConfigTest { private ServiceConfig service2 = new ServiceConfig(); private ServiceConfig delayService = new ServiceConfig(); + private EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + @BeforeEach public void setUp() throws Exception { MockProtocol2.delegate = protocolDelegate; @@ -115,6 +122,9 @@ public void setUp() throws Exception { delayService.setDelay(100); ConfigManager.getInstance().clear(); + + // remove all event listeners + eventDispatcher.removeAllEventListeners(); } @AfterEach @@ -124,8 +134,20 @@ public void tearDown() { @Test public void testExport() throws Exception { + + AtomicReference reference = new AtomicReference(); + + eventDispatcher.addEventListener(new EventListener() { + @Override + public void onEvent(ServiceConfigExportedEvent event) { + reference.set(event.getServiceConfig()); + } + }); + service.export(); + assertEquals(service, reference.get()); + assertThat(service.getExportedUrls(), hasSize(1)); URL url = service.toUrl(); assertThat(url.getProtocol(), equalTo("mockprotocol2")); @@ -167,8 +189,32 @@ public void testDelayExport() throws Exception { public void testUnexport() throws Exception { System.setProperty(Constants.SHUTDOWN_WAIT_KEY, "0"); try { + AtomicReference reference = new AtomicReference(); + + eventDispatcher.addEventListener(new EventListener() { + @Override + public void onEvent(ServiceConfigExportedEvent event) { + reference.set(event.getServiceConfig()); + } + }); + service.export(); + + assertEquals(service, reference.get()); + + assertTrue(reference.compareAndSet(service, null)); + + eventDispatcher.addEventListener(new EventListener() { + @Override + public void onEvent(ServiceConfigUnExportedEvent event) { + reference.set(event.getServiceConfig()); + } + }); + service.unexport(); + + assertEquals(service, reference.get()); + Thread.sleep(1000); Mockito.verify(exporter, Mockito.atLeastOnce()).unexport(); } finally {