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 45f24cf0657..b5b7c0f8f3a 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 @@ -27,7 +27,11 @@ import org.apache.dubbo.common.utils.StringUtils; import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.event.ReferenceConfigDestroyedEvent; +import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent; import org.apache.dubbo.config.support.Parameter; +import org.apache.dubbo.event.Event; +import org.apache.dubbo.event.EventDispatcher; import org.apache.dubbo.metadata.integration.MetadataReportService; import org.apache.dubbo.remoting.Constants; import org.apache.dubbo.rpc.Invoker; @@ -62,18 +66,18 @@ import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY; import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE; 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.REVISION_KEY; import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN; import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY; import static org.apache.dubbo.common.constants.ConfigConstants.CLUSTER_KEY; -import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY; -import static org.apache.dubbo.common.constants.RegistryConstants.REFER_KEY; -import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY; -import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.CONSUMER_PROTOCOL; +import static org.apache.dubbo.common.constants.RegistryConstants.REFER_KEY; import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL; -import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL; import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost; +import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY; +import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY; +import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL; /** * ReferenceConfig @@ -117,6 +121,11 @@ public class ReferenceConfig extends AbstractReferenceConfig { */ private final List urls = new ArrayList(); + /** + * The {@link EventDispatcher} + */ + private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + /** * The interface name of the reference service */ @@ -267,6 +276,9 @@ public synchronized void destroy() { } invoker = null; ref = null; + + // dispatch a ReferenceConfigDestroyedEvent since 2.7.2 + dispatch(new ReferenceConfigDestroyedEvent(this)); } private void init() { @@ -331,6 +343,9 @@ private void init() { String serviceKey = URL.buildKey(interfaceName, group, version); ApplicationModel.initConsumerModel(serviceKey, buildConsumerModel(serviceKey, attributes)); initialized = true; + + // dispatch a ReferenceConfigInitializedEvent since 2.7.2 + dispatch(new ReferenceConfigInitializedEvent(this, invoker)); } private ConsumerModel buildConsumerModel(String serviceKey, Map attributes) { @@ -373,7 +388,7 @@ private T createProxy(Map map) { } } else { // assemble URL from register center's configuration // if protocols not injvm checkRegistry - if (!LOCAL_PROTOCOL.equalsIgnoreCase(getProtocol())){ + if (!LOCAL_PROTOCOL.equalsIgnoreCase(getProtocol())) { checkRegistry(); List us = loadRegistries(false); if (CollectionUtils.isNotEmpty(us)) { @@ -660,4 +675,14 @@ private void resolveFile() { } } } + + /** + * Dispatch an {@link Event event} + * + * @param event an {@link Event event} + * @since 2.7.2 + */ + protected void dispatch(Event event) { + eventDispatcher.dispatch(event); + } } diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigDestroyedEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigDestroyedEvent.java new file mode 100644 index 00000000000..58b871ea7e9 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigDestroyedEvent.java @@ -0,0 +1,41 @@ +/* + * 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.config.ReferenceConfig; +import org.apache.dubbo.config.annotation.Reference; +import org.apache.dubbo.event.Event; + +/** + * The {@link ReferenceConfig Dubbo service ReferenceConfig} destroyed {@link Event event} + * + * @see Reference + * @see ReferenceConfig#destroy() + * @see Event + * @since 2.7.2 + */ +public class ReferenceConfigDestroyedEvent extends Event { + + public ReferenceConfigDestroyedEvent(ReferenceConfig referenceConfig) { + super(referenceConfig); + } + + public ReferenceConfig getReferenceConfig() { + return (ReferenceConfig) getSource(); + } + +} \ No newline at end of file diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigInitializedEvent.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigInitializedEvent.java new file mode 100644 index 00000000000..dcf02cfec77 --- /dev/null +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/ReferenceConfigInitializedEvent.java @@ -0,0 +1,48 @@ +/* + * 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.config.ReferenceConfig; +import org.apache.dubbo.config.annotation.Reference; +import org.apache.dubbo.event.Event; +import org.apache.dubbo.rpc.Invoker; + +/** + * The {@link ReferenceConfig Dubbo service ReferenceConfig} initialized {@link Event event} + * + * @see Reference + * @see ReferenceConfig#get() + * @see Event + * @since 2.7.2 + */ +public class ReferenceConfigInitializedEvent extends Event { + + private final Invoker invoker; + + public ReferenceConfigInitializedEvent(ReferenceConfig referenceConfig, Invoker invoker) { + super(referenceConfig); + this.invoker = invoker; + } + + public ReferenceConfig getReferenceConfig() { + return (ReferenceConfig) getSource(); + } + + public Invoker getInvoker() { + return invoker; + } +} diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java index d1e02636dd7..f9afb355945 100644 --- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java +++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java @@ -21,20 +21,30 @@ import org.apache.dubbo.config.annotation.Reference; import org.apache.dubbo.config.api.DemoService; import org.apache.dubbo.config.context.ConfigManager; +import org.apache.dubbo.config.event.ReferenceConfigDestroyedEvent; +import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent; import org.apache.dubbo.config.provider.impl.DemoServiceImpl; +import org.apache.dubbo.event.EventDispatcher; +import org.apache.dubbo.event.EventListener; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.concurrent.atomic.AtomicReference; + import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL; +import static org.junit.jupiter.api.Assertions.assertEquals; public class ReferenceConfigTest { + private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension(); + @BeforeEach public void setUp() { ConfigManager.getInstance().clear(); + eventDispatcher.removeAllEventListeners(); } @AfterEach @@ -67,12 +77,38 @@ public void testInjvm() throws Exception { rc.setInterface(DemoService.class.getName()); rc.setInjvm(false); + AtomicReference reference = new AtomicReference<>(); + + eventDispatcher.addEventListener(new EventListener() { + @Override + public void onEvent(ReferenceConfigInitializedEvent event) { + reference.set(event.getReferenceConfig()); + } + }); + try { System.setProperty("java.net.preferIPv4Stack", "true"); demoService.export(); rc.get(); + + assertEquals(rc, reference.get()); + + reference.compareAndSet(rc, null); + Assertions.assertTrue(!LOCAL_PROTOCOL.equalsIgnoreCase( rc.getInvoker().getUrl().getProtocol())); + + eventDispatcher.addEventListener(new EventListener() { + @Override + public void onEvent(ReferenceConfigDestroyedEvent event) { + reference.set(event.getReferenceConfig()); + } + }); + + rc.destroy(); + + assertEquals(rc, reference.get()); + } finally { System.clearProperty("java.net.preferIPv4Stack"); demoService.unexport(); @@ -134,17 +170,17 @@ public void testConstructWithReferenceAnnotation() throws NoSuchFieldException { Reference reference = getClass().getDeclaredField("innerTest").getAnnotation(Reference.class); ReferenceConfig referenceConfig = new ReferenceConfig(reference); Assertions.assertTrue(referenceConfig.getMethods().size() == 1); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello"); Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getTimeout() == 1300); Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getRetries() == 4); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random"); Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getActives() == 3); Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getExecutes() == 5); Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).isAsync()); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i"); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r"); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t"); - Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t"); + assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c"); }