This is an automated email from the ASF dual-hosted git repository. liujun pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/dubbo.git
commit 2d2341e544927244843fda934529bd8445ea99bf Author: Mercy Ma <[email protected]> AuthorDate: Wed Dec 18 10:44:58 2019 +0800 [Dubbo-5495] Services can't be exported for projects driven by annotation but with EnableDubbo/EnableDubboLifecycle not enabled (#5496) Fixes #5495 --- .../ServiceAnnotationBeanPostProcessor.java | 11 +++- .../context/DubboBootstrapApplicationListener.java | 63 +++++++++++++++++++ ...DubboLifecycleComponentApplicationListener.java | 60 +++++++----------- ...meExecutionApplicationContextEventListener.java | 71 ++++++++++++++++++++++ .../DubboLifecycleComponentRegistrar.java | 2 + .../beans/factory/ServiceBeanPostProcessor.java | 37 ----------- .../ServiceAnnotationTestConfiguration.java | 6 -- .../spring/context/annotation/EnableDubboTest.java | 6 -- .../annotation/provider/ProviderConfiguration.java | 6 -- 9 files changed, 167 insertions(+), 95 deletions(-) diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java index c96f7b9..08a0965 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessor.java @@ -23,6 +23,7 @@ import org.apache.dubbo.config.MethodConfig; import org.apache.dubbo.config.annotation.Method; import org.apache.dubbo.config.annotation.Service; import org.apache.dubbo.config.spring.ServiceBean; +import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener; import org.apache.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner; import org.springframework.beans.BeansException; @@ -63,6 +64,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import static com.alibaba.spring.util.AnnotatedBeanDefinitionRegistryUtils.registerBeans; import static com.alibaba.spring.util.ObjectUtils.of; import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create; import static org.apache.dubbo.config.spring.util.DubboAnnotationUtils.resolveServiceInterfaceClass; @@ -107,6 +109,9 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + // @since 2.7.5 + registerBeans(registry, DubboBootstrapApplicationListener.class); + Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan); if (!CollectionUtils.isEmpty(resolvedPackagesToScan)) { @@ -456,10 +461,10 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr } private List convertMethodConfigs(Object methodsAnnotation) { - if (methodsAnnotation == null){ + if (methodsAnnotation == null) { return Collections.EMPTY_LIST; } - return MethodConfig.constructMethodConfig((Method[])methodsAnnotation); + return MethodConfig.constructMethodConfig((Method[]) methodsAnnotation); } private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) { @@ -523,4 +528,4 @@ public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistr this.classLoader = classLoader; } -} +} \ No newline at end of file diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java new file mode 100644 index 0000000..fd11690 --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboBootstrapApplicationListener.java @@ -0,0 +1,63 @@ +/* + * 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.spring.context; + +import org.apache.dubbo.config.bootstrap.DubboBootstrap; + +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ApplicationContextEvent; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.core.Ordered; + +/** + * The {@link ApplicationListener} for {@link DubboBootstrap}'s lifecycle when the {@link ContextRefreshedEvent} + * and {@link ContextClosedEvent} raised + * + * @since 2.7.5 + */ +public class DubboBootstrapApplicationListener extends OneTimeExecutionApplicationContextEventListener + implements Ordered { + + private final DubboBootstrap dubboBootstrap; + + public DubboBootstrapApplicationListener() { + this.dubboBootstrap = DubboBootstrap.getInstance(); + } + + @Override + public void onApplicationContextEvent(ApplicationContextEvent event) { + if (event instanceof ContextRefreshedEvent) { + onContextRefreshedEvent((ContextRefreshedEvent) event); + } else if (event instanceof ContextClosedEvent) { + onContextClosedEvent((ContextClosedEvent) event); + } + } + + private void onContextRefreshedEvent(ContextRefreshedEvent event) { + dubboBootstrap.start(); + } + + private void onContextClosedEvent(ContextClosedEvent event) { + dubboBootstrap.stop(); + } + + @Override + public int getOrder() { + return LOWEST_PRECEDENCE; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java index 61cb66d..7aad776 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/DubboLifecycleComponentApplicationListener.java @@ -18,20 +18,18 @@ package org.apache.dubbo.config.spring.context; import org.apache.dubbo.common.context.Lifecycle; -import org.apache.dubbo.common.utils.CollectionUtils; -import org.apache.dubbo.config.DubboShutdownHook; -import org.apache.dubbo.config.bootstrap.DubboBootstrap; import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ApplicationContextEvent; import org.springframework.context.event.ContextClosedEvent; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.context.event.SmartApplicationListener; -import java.util.Map; +import java.util.LinkedList; +import java.util.List; +import static java.util.Collections.emptyList; import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors; /** @@ -41,15 +39,12 @@ import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncl * @see SmartApplicationListener * @since 2.7.5 */ -public class DubboLifecycleComponentApplicationListener implements ApplicationListener { +public class DubboLifecycleComponentApplicationListener extends OneTimeExecutionApplicationContextEventListener { - @Override - public void onApplicationEvent(ApplicationEvent event) { - - if (!supportsEvent(event)) { - return; - } + private List<Lifecycle> lifecycleComponents = emptyList(); + @Override + protected void onApplicationContextEvent(ApplicationContextEvent event) { if (event instanceof ContextRefreshedEvent) { onContextRefreshedEvent((ContextRefreshedEvent) event); } else if (event instanceof ContextClosedEvent) { @@ -58,40 +53,31 @@ public class DubboLifecycleComponentApplicationListener implements ApplicationLi } protected void onContextRefreshedEvent(ContextRefreshedEvent event) { - ApplicationContext context = event.getApplicationContext(); - DubboBootstrap bootstrap = loadBootsttrapAsBean(context); - if (bootstrap == null) { - bootstrap = DubboBootstrap.getInstance(); - } - bootstrap.start(); + initLifecycleComponents(event); + startLifecycleComponents(); } protected void onContextClosedEvent(ContextClosedEvent event) { - DubboShutdownHook.getDubboShutdownHook().doDestroy(); + destroyLifecycleComponents(); } - private DubboBootstrap loadBootsttrapAsBean(ApplicationContext context) { - Map<String, DubboBootstrap> beans = beansOfTypeIncludingAncestors(context, DubboBootstrap.class); - if (CollectionUtils.isNotEmptyMap(beans)) { - return beans.values().iterator().next(); - } - return null; + private void initLifecycleComponents(ContextRefreshedEvent event) { + ApplicationContext context = event.getApplicationContext(); + ClassLoader classLoader = context.getClassLoader(); + lifecycleComponents = new LinkedList<>(); + // load the Beans of Lifecycle from ApplicationContext + loadLifecycleComponents(lifecycleComponents, context); } - /** - * the specified {@link ApplicationEvent event} must be {@link ApplicationContextEvent} and - * its correlative {@link ApplicationContext} must be root - * - * @param event - * @return - */ - private boolean supportsEvent(ApplicationEvent event) { - return event instanceof ApplicationContextEvent && - isRootApplicationContext((ApplicationContextEvent) event); + private void loadLifecycleComponents(List<Lifecycle> lifecycleComponents, ApplicationContext context) { + lifecycleComponents.addAll(beansOfTypeIncludingAncestors(context, Lifecycle.class).values()); } + private void startLifecycleComponents() { + lifecycleComponents.forEach(Lifecycle::start); + } - private boolean isRootApplicationContext(ApplicationContextEvent event) { - return event.getApplicationContext().getParent() == null; + private void destroyLifecycleComponents() { + lifecycleComponents.forEach(Lifecycle::destroy); } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java new file mode 100644 index 0000000..569a67e --- /dev/null +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/OneTimeExecutionApplicationContextEventListener.java @@ -0,0 +1,71 @@ +/* + * 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.spring.context; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ApplicationContextEvent; + +import java.util.Objects; + +/** + * The abstract class {@link ApplicationListener} for {@link ApplicationContextEvent} guarantees just one-time execution + * and prevents the event propagation in the hierarchical {@link ApplicationContext ApplicationContexts} + * + * @since 2.7.5 + */ +abstract class OneTimeExecutionApplicationContextEventListener implements ApplicationListener, ApplicationContextAware { + + private ApplicationContext applicationContext; + + public final void onApplicationEvent(ApplicationEvent event) { + if (isOriginalEventSource(event) && event instanceof ApplicationContextEvent) { + onApplicationContextEvent((ApplicationContextEvent) event); + } + } + + /** + * The subclass overrides this method to handle {@link ApplicationContextEvent} + * + * @param event {@link ApplicationContextEvent} + */ + protected abstract void onApplicationContextEvent(ApplicationContextEvent event); + + /** + * Is original {@link ApplicationContext} as the event source + * + * @param event {@link ApplicationEvent} + * @return + */ + private boolean isOriginalEventSource(ApplicationEvent event) { + return (applicationContext == null) // Current ApplicationListener is not a Spring Bean, just was added + // into Spring's ConfigurableApplicationContext + || Objects.equals(applicationContext, event.getSource()); + } + + @Override + public final void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } + + public ApplicationContext getApplicationContext() { + return applicationContext; + } +} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboLifecycleComponentRegistrar.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboLifecycleComponentRegistrar.java index c192c8d..20fd1a9 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboLifecycleComponentRegistrar.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/context/annotation/DubboLifecycleComponentRegistrar.java @@ -17,6 +17,7 @@ package org.apache.dubbo.config.spring.context.annotation; import org.apache.dubbo.common.context.Lifecycle; +import org.apache.dubbo.config.spring.context.DubboBootstrapApplicationListener; import org.apache.dubbo.config.spring.context.DubboLifecycleComponentApplicationListener; import org.springframework.beans.factory.support.BeanDefinitionRegistry; @@ -35,5 +36,6 @@ public class DubboLifecycleComponentRegistrar implements ImportBeanDefinitionReg @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { registerBeans(registry, DubboLifecycleComponentApplicationListener.class); + registerBeans(registry, DubboBootstrapApplicationListener.class); } } diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/ServiceBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/ServiceBeanPostProcessor.java deleted file mode 100644 index 52c7500..0000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/ServiceBeanPostProcessor.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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.spring.beans.factory; - -import org.apache.dubbo.config.spring.ServiceBean; - -import org.springframework.beans.BeansException; -import org.springframework.beans.factory.config.BeanPostProcessor; - -public class ServiceBeanPostProcessor implements BeanPostProcessor { - @Override - public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - return bean; - } - - @Override - public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { - if (bean instanceof ServiceBean) { - ((ServiceBean) bean).export(); - } - return bean; - } -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java index daa95aa..7a206db 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationTestConfiguration.java @@ -21,7 +21,6 @@ import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.annotation.Service; -import org.apache.dubbo.config.spring.beans.factory.ServiceBeanPostProcessor; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; @@ -86,11 +85,6 @@ public class ServiceAnnotationTestConfiguration { return protocolConfig; } - @Bean - public ServiceBeanPostProcessor serviceBeanPostProcessor() { - return new ServiceBeanPostProcessor(); - } - @Primary @Bean public PlatformTransactionManager platformTransactionManager() { diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java index 54660b7..42fadfc 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java @@ -18,7 +18,6 @@ package org.apache.dubbo.config.spring.context.annotation; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.spring.api.DemoService; -import org.apache.dubbo.config.spring.beans.factory.ServiceBeanPostProcessor; import org.apache.dubbo.config.spring.context.annotation.consumer.test.TestConsumerConfiguration; import org.apache.dubbo.config.spring.context.annotation.provider.DemoServiceImpl; import org.apache.dubbo.rpc.model.ApplicationModel; @@ -152,11 +151,6 @@ public class EnableDubboTest { @EnableTransactionManagement public static class TestProviderConfiguration { - @Bean - public ServiceBeanPostProcessor serviceBeanPostProcessor() { - return new ServiceBeanPostProcessor(); - } - @Primary @Bean public PlatformTransactionManager platformTransactionManager() { diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/ProviderConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/ProviderConfiguration.java index b31e670..d168af8 100644 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/ProviderConfiguration.java +++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/provider/ProviderConfiguration.java @@ -19,7 +19,6 @@ package org.apache.dubbo.config.spring.context.annotation.provider; import org.apache.dubbo.config.ApplicationConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.RegistryConfig; -import org.apache.dubbo.config.spring.beans.factory.ServiceBeanPostProcessor; import org.apache.dubbo.config.spring.context.annotation.DubboComponentScan; import org.springframework.context.annotation.Bean; @@ -82,11 +81,6 @@ public class ProviderConfiguration { return protocolConfig; } - @Bean - public ServiceBeanPostProcessor serviceBeanPostProcessor() { - return new ServiceBeanPostProcessor(); - } - @Primary @Bean public PlatformTransactionManager platformTransactionManager() {
