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/incubator-dubbo.git
The following commit(s) were added to refs/heads/master by this push: new 0d51bc4 Merge pull request #2725, problems of graceful shutdown in 2.6.3 and some recommendation. 0d51bc4 is described below commit 0d51bc4751583cc31e7b65c5a79e335fa76aae89 Author: Ian Luo <ian....@gmail.com> AuthorDate: Mon Nov 5 10:49:10 2018 +0800 Merge pull request #2725, problems of graceful shutdown in 2.6.3 and some recommendation. --- dubbo-all/pom.xml | 8 -- dubbo-bom/pom.xml | 5 - dubbo-bootstrap/pom.xml | 47 --------- .../org/apache/dubbo/bootstrap/DubboBootstrap.java | 111 --------------------- .../org/apache/dubbo/config/ProtocolConfig.java | 11 +- dubbo-config/dubbo-config-spring/pom.xml | 7 +- .../apache/dubbo/config/spring/AnnotationBean.java | 23 ++--- .../apache/dubbo/config/spring/ServiceBean.java | 26 +---- .../spring/extension/SpringExtensionFactory.java | 19 ++++ .../DubboApplicationContextInitializer.java | 39 -------- .../initializer/DubboApplicationListener.java | 49 --------- .../spring/initializer/DubboContextListener.java | 72 ------------- .../dubbo/config/spring/util/BeanFactoryUtils.java | 27 +++++ .../src/main/resources/META-INF/web-fragment.xml | 22 ---- .../DubboApplicationContextInitializerTest.java | 88 ---------------- .../initializer/DubboApplicationListenerTest.java | 59 ----------- dubbo-container/dubbo-container-spring/pom.xml | 7 +- .../dubbo/container/spring/SpringContainer.java | 6 +- dubbo-distribution/pom.xml | 5 - pom.xml | 1 - 20 files changed, 65 insertions(+), 567 deletions(-) diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml index 8e8fa66..12d9ec9 100644 --- a/dubbo-all/pom.xml +++ b/dubbo-all/pom.xml @@ -327,13 +327,6 @@ </dependency> <dependency> <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-bootstrap</artifactId> - <version>${project.version}</version> - <scope>compile</scope> - <optional>true</optional> - </dependency> - <dependency> - <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-compatible</artifactId> <version>${project.version}</version> <scope>compile</scope> @@ -439,7 +432,6 @@ <include>org.apache.dubbo:dubbo-serialization-kryo</include> <include>org.apache.dubbo:dubbo-serialization-jdk</include> <include>org.apache.dubbo:dubbo-serialization-protostuff</include> - <include>org.apache.dubbo:dubbo-bootstrap</include> </includes> </artifactSet> <transformers> diff --git a/dubbo-bom/pom.xml b/dubbo-bom/pom.xml index 15c8ae8..dac2456 100644 --- a/dubbo-bom/pom.xml +++ b/dubbo-bom/pom.xml @@ -285,11 +285,6 @@ </dependency> <dependency> <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-bootstrap</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> - <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-compatible</artifactId> <version>${project.version}</version> </dependency> diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml deleted file mode 100644 index a082550..0000000 --- a/dubbo-bootstrap/pom.xml +++ /dev/null @@ -1,47 +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. - --> -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> - <parent> - <artifactId>dubbo-parent</artifactId> - <groupId>org.apache.dubbo</groupId> - <version>2.7.0-SNAPSHOT</version> - </parent> - <modelVersion>4.0.0</modelVersion> - - <artifactId>dubbo-bootstrap</artifactId> - - - <dependencies> - <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-config-api</artifactId> - <version>${project.parent.version}</version> - </dependency> - <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-common</artifactId> - <version>${project.parent.version}</version> - </dependency> - <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-registry-api</artifactId> - <version>${project.parent.version}</version> - </dependency> - </dependencies> -</project> \ No newline at end of file diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java deleted file mode 100644 index b896c0e..0000000 --- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java +++ /dev/null @@ -1,111 +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.bootstrap; - -import org.apache.dubbo.config.DubboShutdownHook; -import org.apache.dubbo.config.ServiceConfig; - -import java.util.ArrayList; -import java.util.List; - -/** - * A bootstrap class to easily start and stop Dubbo via programmatic API. - * The bootstrap class will be responsible to cleanup the resources during stop. - */ -public class DubboBootstrap { - - /** - * The list of ServiceConfig - */ - private List<ServiceConfig> serviceConfigList; - - /** - * Whether register the shutdown hook during start? - */ - private final boolean registerShutdownHookOnStart; - - /** - * The shutdown hook used when Dubbo is running under embedded environment - */ - private DubboShutdownHook shutdownHook; - - public DubboBootstrap() { - this(true, DubboShutdownHook.getDubboShutdownHook()); - } - - public DubboBootstrap(boolean registerShutdownHookOnStart) { - this(registerShutdownHookOnStart, DubboShutdownHook.getDubboShutdownHook()); - } - - public DubboBootstrap(boolean registerShutdownHookOnStart, DubboShutdownHook shutdownHook) { - this.serviceConfigList = new ArrayList<ServiceConfig>(); - this.shutdownHook = shutdownHook; - this.registerShutdownHookOnStart = registerShutdownHookOnStart; - } - - /** - * Register service config to bootstrap, which will be called during {@link DubboBootstrap#stop()} - * @param serviceConfig the service - * @return the bootstrap instance - */ - public DubboBootstrap registerServiceConfig(ServiceConfig serviceConfig) { - serviceConfigList.add(serviceConfig); - return this; - } - - public void start() { - if (registerShutdownHookOnStart) { - registerShutdownHook(); - } else { - // DubboShutdown hook has been registered in AbstractConfig, - // we need to remove it explicitly - removeShutdownHook(); - } - for (ServiceConfig serviceConfig: serviceConfigList) { - serviceConfig.export(); - } - } - - public void stop() { - for (ServiceConfig serviceConfig: serviceConfigList) { - serviceConfig.unexport(); - } - shutdownHook.destroyAll(); - if (registerShutdownHookOnStart) { - removeShutdownHook(); - } - } - - /** - * Register the shutdown hook - */ - public void registerShutdownHook() { - Runtime.getRuntime().addShutdownHook(shutdownHook); - } - - /** - * Remove this shutdown hook - */ - public void removeShutdownHook() { - try { - Runtime.getRuntime().removeShutdownHook(shutdownHook); - } - catch (IllegalStateException ex) { - // ignore - VM is already shutting down - } - } -} diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ProtocolConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ProtocolConfig.java index 3ae3329..7582169 100644 --- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ProtocolConfig.java +++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ProtocolConfig.java @@ -470,13 +470,4 @@ public class ProtocolConfig extends AbstractConfig { ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).destroy(); } } - - /** - * Just for compatibility. - * It should be deleted in the next major version, say 2.7.x. - */ - @Deprecated - public static void destroyAll() { - DubboShutdownHook.getDubboShutdownHook().destroyAll(); - } -} \ No newline at end of file +} diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml index 995209d..626556c 100644 --- a/dubbo-config/dubbo-config-spring/pom.xml +++ b/dubbo-config/dubbo-config-spring/pom.xml @@ -35,11 +35,6 @@ <version>${project.parent.version}</version> </dependency> <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-bootstrap</artifactId> - <version>${project.parent.version}</version> - </dependency> - <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> </dependency> @@ -157,4 +152,4 @@ --> </plugins> </build> -</project> \ No newline at end of file +</project> diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java index 7612c33..6b54a39 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/AnnotationBean.java @@ -28,7 +28,6 @@ import org.apache.dubbo.config.ModuleConfig; import org.apache.dubbo.config.MonitorConfig; import org.apache.dubbo.config.ProtocolConfig; import org.apache.dubbo.config.ProviderConfig; -import org.apache.dubbo.config.ReferenceConfig; import org.apache.dubbo.config.RegistryConfig; import org.apache.dubbo.config.ServiceConfig; import org.apache.dubbo.config.annotation.Reference; @@ -111,17 +110,16 @@ public class AnnotationBean extends AbstractConfig implements DisposableBean, Be @Override public void destroy() { - - // This will only be called for singleton scope bean, and expected to be called by spring shutdown hook when BeanFactory/ApplicationContext destroys. - // We will guarantee dubbo related resources being released with dubbo shutdown hook. - - // for (ServiceConfig<?> serviceConfig : serviceConfigs) { - // try { - // serviceConfig.unexport(); - // } catch (Throwable e) { - // logger.error(e.getMessage(), e); - // } - // } + // no need to destroy here + // see org.apache.dubbo.config.spring.extension.SpringExtensionFactory.ShutdownHookListener + /* + for (ServiceConfig<?> serviceConfig : serviceConfigs) { + try { + serviceConfig.unexport(); + } catch (Throwable e) { + logger.error(e.getMessage(), e); + } + } for (ReferenceConfig<?> referenceConfig : referenceConfigs.values()) { try { @@ -130,6 +128,7 @@ public class AnnotationBean extends AbstractConfig implements DisposableBean, Be logger.error(e.getMessage(), e); } } + */ } @Override diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java index 6d7bc9b..19dcef1 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/ServiceBean.java @@ -34,13 +34,13 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.context.support.AbstractApplicationContext; -import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; import java.util.Map; +import static org.apache.dubbo.config.spring.util.BeanFactoryUtils.addApplicationListener; + /** * ServiceFactoryBean * @@ -72,23 +72,7 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; SpringExtensionFactory.addApplicationContext(applicationContext); - try { - Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class); // backward compatibility to spring 2.0.1 - method.invoke(applicationContext, this); - supportedApplicationListener = true; - } catch (Throwable t) { - if (applicationContext instanceof AbstractApplicationContext) { - try { - Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class); // backward compatibility to spring 2.0.1 - if (!method.isAccessible()) { - method.setAccessible(true); - } - method.invoke(applicationContext, this); - supportedApplicationListener = true; - } catch (Throwable t2) { - } - } - } + supportedApplicationListener = addApplicationListener(applicationContext, this); } @Override @@ -249,9 +233,7 @@ public class ServiceBean<T> extends ServiceConfig<T> implements InitializingBean @Override public void destroy() throws Exception { - // This will only be called for singleton scope bean, and expected to be called by spring shutdown hook when BeanFactory/ApplicationContext destroys. - // We will guarantee dubbo related resources being released with dubbo shutdown hook. - //unexport(); + // no need to export here, see org.apache.dubbo.config.spring.extension.SpringExtensionFactory.ShutdownHookListener } // merged from dubbox diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java index ea63a35..988bcec 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/extension/SpringExtensionFactory.java @@ -21,9 +21,14 @@ import org.apache.dubbo.common.extension.SPI; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ConcurrentHashSet; +import org.apache.dubbo.config.DubboShutdownHook; +import org.apache.dubbo.config.spring.util.BeanFactoryUtils; import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.NoUniqueBeanDefinitionException; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextClosedEvent; import java.util.Set; @@ -34,9 +39,11 @@ public class SpringExtensionFactory implements ExtensionFactory { private static final Logger logger = LoggerFactory.getLogger(SpringExtensionFactory.class); private static final Set<ApplicationContext> contexts = new ConcurrentHashSet<ApplicationContext>(); + private static final ApplicationListener shutdownHookListener = new ShutdownHookListener(); public static void addApplicationContext(ApplicationContext context) { contexts.add(context); + BeanFactoryUtils.addApplicationListener(context, shutdownHookListener); } public static void removeApplicationContext(ApplicationContext context) { @@ -93,4 +100,16 @@ public class SpringExtensionFactory implements ExtensionFactory { return null; } + private static class ShutdownHookListener implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationEvent event) { + if (event instanceof ContextClosedEvent) { + // we call it anyway since dubbo shutdown hook make sure its destroyAll() is re-entrant. + // pls. note we should not remove dubbo shutdown hook when spring framework is present, this is because + // its shutdown hook may not be installed. + DubboShutdownHook shutdownHook = DubboShutdownHook.getDubboShutdownHook(); + shutdownHook.destroyAll(); + } + } + } } diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializer.java deleted file mode 100644 index 36727e6..0000000 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializer.java +++ /dev/null @@ -1,39 +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.initializer; - -import org.springframework.context.ApplicationContextInitializer; -import org.springframework.context.ConfigurableApplicationContext; - -/** - * Automatically register {@link DubboApplicationListener} to Spring context - * A {@link org.springframework.web.context.ContextLoaderListener} class is defined in - * src/main/resources/META-INF/web-fragment.xml - * In the web-fragment.xml, {@link DubboApplicationContextInitializer} is defined in context params. - * This file will be discovered if running under a servlet 3.0+ container. - * Even if user specifies {@link org.springframework.web.context.ContextLoaderListener} in web.xml, - * it will be merged to web.xml. - * If user specifies <metadata-complete="true" /> in web.xml, this will no take effect, - * unless user configures {@link DubboApplicationContextInitializer} explicitly in web.xml. - */ -public class DubboApplicationContextInitializer implements ApplicationContextInitializer { - - @Override - public void initialize(ConfigurableApplicationContext applicationContext) { - applicationContext.addApplicationListener(new DubboApplicationListener()); - } -} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListener.java deleted file mode 100644 index 8b6409b..0000000 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListener.java +++ /dev/null @@ -1,49 +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.initializer; - -import org.apache.dubbo.bootstrap.DubboBootstrap; -import org.springframework.context.ApplicationEvent; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextClosedEvent; -import org.springframework.context.event.ContextRefreshedEvent; - -/** - * An application listener that listens the ContextClosedEvent. - * Upon the event, this listener will do the necessary clean up to avoid memory leak. - */ -public class DubboApplicationListener implements ApplicationListener<ApplicationEvent> { - - private DubboBootstrap dubboBootstrap; - - public DubboApplicationListener() { - dubboBootstrap = new DubboBootstrap(false); - } - - public DubboApplicationListener(DubboBootstrap dubboBootstrap) { - this.dubboBootstrap = dubboBootstrap; - } - - @Override - public void onApplicationEvent(ApplicationEvent applicationEvent) { - if (applicationEvent instanceof ContextRefreshedEvent) { - dubboBootstrap.start(); - } else if (applicationEvent instanceof ContextClosedEvent) { - dubboBootstrap.stop(); - } - } -} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboContextListener.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboContextListener.java deleted file mode 100644 index 35b2b70..0000000 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboContextListener.java +++ /dev/null @@ -1,72 +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.initializer; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import javax.servlet.ServletContext; -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -/** - * A Dubbo context listener is a delegation to org.springframework.web.context.ContextLoaderListener. This is necessary, - * because Dubbo is packaged into all-in-one jar, therefore it contains a web-fragment.xml from this sub module which's - * used for helping to assemble spring context listener automatically when it's not configured explicitly by user in - * web.xml. It works fine with spring, but it will lead to ClassNotFound exception and fail tomcat's bootup when user - * doesn't depend on spring framework. - */ -public class DubboContextListener implements ServletContextListener { - private static final Log logger = LogFactory.getLog(DubboContextListener.class); - - private static final String SPRING_CONTEXT_LISTENER = "org.springframework.web.context.ContextLoaderListener"; - private static final String SPRING_CONTEXT_ROOT = "org.springframework.web.context.WebApplicationContext.ROOT"; - - private ServletContextListener springContextListener; - private boolean executed = false; - - public DubboContextListener() { - try { - Class c = Class.forName(SPRING_CONTEXT_LISTENER); - springContextListener = (ServletContextListener) c.newInstance(); - } catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) { - logger.warn("Servlet container detects dubbo's web fragment configuration, and tries to load " + - "org.springframework.web.context.ContextLoaderListener but fails to find the class. " + - "If the application don't rely on Spring framework, pls. simply ignore"); - } - } - - @Override - public void contextInitialized(ServletContextEvent servletContextEvent) { - if (springContextListener != null) { - // if spring context listener has already been registered, then do nothing - ServletContext context = servletContextEvent.getServletContext(); - if (context.getAttribute(SPRING_CONTEXT_ROOT) == null) { - executed = true; - springContextListener.contextInitialized(servletContextEvent); - } - } - } - - @Override - public void contextDestroyed(ServletContextEvent servletContextEvent) { - if (springContextListener != null && executed) { - springContextListener.contextDestroyed(servletContextEvent); - } - } -} diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java index e787399..e9b1708 100644 --- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java +++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/util/BeanFactoryUtils.java @@ -20,7 +20,11 @@ import org.apache.dubbo.common.utils.StringUtils; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.ListableBeanFactory; import org.springframework.beans.factory.config.ConfigurableBeanFactory; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.support.AbstractApplicationContext; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -89,4 +93,27 @@ public class BeanFactoryUtils { } + public static boolean addApplicationListener(ApplicationContext applicationContext, ApplicationListener listener) { + try { + // backward compatibility to spring 2.0.1 + Method method = applicationContext.getClass().getMethod("addApplicationListener", ApplicationListener.class); + method.invoke(applicationContext, listener); + return true; + } catch (Throwable t) { + if (applicationContext instanceof AbstractApplicationContext) { + try { + // backward compatibility to spring 2.0.1 + Method method = AbstractApplicationContext.class.getDeclaredMethod("addListener", ApplicationListener.class); + if (!method.isAccessible()) { + method.setAccessible(true); + } + method.invoke(applicationContext, listener); + return true; + } catch (Throwable t2) { + // ignore + } + } + } + return false; + } } diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/web-fragment.xml b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/web-fragment.xml deleted file mode 100644 index e1eef6b..0000000 --- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/web-fragment.xml +++ /dev/null @@ -1,22 +0,0 @@ -<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"> - - <name>dubbo_fragment</name> - - <ordering> - <before> - <others/> - </before> - </ordering> - - <context-param> - <param-name>contextInitializerClasses</param-name> - <param-value>org.apache.dubbo.config.spring.initializer.DubboApplicationContextInitializer</param-value> - </context-param> - - <listener> - <listener-class>org.apache.dubbo.config.spring.initializer.DubboContextListener</listener-class> - </listener> - -</web-fragment> diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializerTest.java deleted file mode 100644 index 02dda03..0000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializerTest.java +++ /dev/null @@ -1,88 +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.initializer; - -import org.apache.catalina.core.StandardContext; -import org.apache.catalina.startup.ContextConfig; -import org.apache.catalina.startup.Tomcat; -import org.junit.Assert; -import org.junit.Test; -import org.springframework.web.context.ContextLoaderListener; - - -public class DubboApplicationContextInitializerTest { - - @Test - public void testSpringContextLoaderListenerInWebXml() throws Exception { - Tomcat tomcat = new Tomcat(); - tomcat.setBaseDir("target/test-classes"); - tomcat.setPort(12345); - StandardContext context = new StandardContext(); - context.setName("test"); - context.setDocBase("test"); - context.setPath("/test"); - context.addLifecycleListener(new ContextConfig()); - tomcat.getHost().addChild(context); - tomcat.start(); - // there should be 2 application listeners, one is spring context listener, - // the other is its wrapper dubbo introduces. - Assert.assertEquals(2, context.getApplicationLifecycleListeners().length); - // the first one should be Spring's built in ContextLoaderListener. - Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof ContextLoaderListener); - tomcat.stop(); - tomcat.destroy(); - } - - @Test - public void testNoListenerInWebXml() throws Exception { - Tomcat tomcat = new Tomcat(); - tomcat.setBaseDir("target/test-classes"); - tomcat.setPort(12345); - StandardContext context = new StandardContext(); - context.setName("test2"); - context.setDocBase("test2"); - context.setPath("/test2"); - context.addLifecycleListener(new ContextConfig()); - tomcat.getHost().addChild(context); - tomcat.start(); - // there should be 1 application listener, which is spring context listener's wrapper introduced by dubbo - Assert.assertEquals(1, context.getApplicationLifecycleListeners().length); - // the first one should be Spring's built in ContextLoaderListener. - Assert.assertTrue(context.getApplicationLifecycleListeners()[0] instanceof DubboContextListener); - tomcat.stop(); - tomcat.destroy(); - } - - @Test - public void testMetadataComplete() throws Exception { - Tomcat tomcat = new Tomcat(); - tomcat.setBaseDir("target/test-classes"); - tomcat.setPort(12345); - StandardContext context = new StandardContext(); - context.setName("test3"); - context.setDocBase("test3"); - context.setPath("/test3"); - context.addLifecycleListener(new ContextConfig()); - tomcat.getHost().addChild(context); - tomcat.start(); - // there should be no application listeners - Assert.assertEquals(0, context.getApplicationLifecycleListeners().length); - tomcat.stop(); - tomcat.destroy(); - } - -} diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListenerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListenerTest.java deleted file mode 100644 index 9b953d5..0000000 --- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationListenerTest.java +++ /dev/null @@ -1,59 +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.initializer; - -import org.apache.dubbo.config.DubboShutdownHook; -import org.apache.dubbo.bootstrap.DubboBootstrap; -import org.junit.Test; -import org.mockito.Mockito; -import org.springframework.context.support.ClassPathXmlApplicationContext; - -public class DubboApplicationListenerTest { - - @Test - public void testTwoShutdownHook() { - DubboShutdownHook spyHook = Mockito.spy(DubboShutdownHook.getDubboShutdownHook()); - ClassPathXmlApplicationContext applicationContext = getApplicationContext(spyHook, true); - applicationContext.refresh(); - applicationContext.close(); - // shutdown hook can't be verified, because it will executed after main thread has finished. - // so we can only verify it by manually run it. - try { - spyHook.start(); - spyHook.join(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - Mockito.verify(spyHook, Mockito.times(2)).destroyAll(); - } - - @Test - public void testOneShutdownHook() { - DubboShutdownHook spyHook = Mockito.spy(DubboShutdownHook.getDubboShutdownHook()); - ClassPathXmlApplicationContext applicationContext = getApplicationContext(spyHook, false); - applicationContext.refresh(); - applicationContext.close(); - Mockito.verify(spyHook, Mockito.times(1)).destroyAll(); - } - - private ClassPathXmlApplicationContext getApplicationContext(DubboShutdownHook hook, boolean registerHook) { - DubboBootstrap bootstrap = new DubboBootstrap(registerHook, hook); - ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext(); - applicationContext.addApplicationListener(new DubboApplicationListener(bootstrap)); - return applicationContext; - } -} diff --git a/dubbo-container/dubbo-container-spring/pom.xml b/dubbo-container/dubbo-container-spring/pom.xml index cbcc43e..987b2c9 100644 --- a/dubbo-container/dubbo-container-spring/pom.xml +++ b/dubbo-container/dubbo-container-spring/pom.xml @@ -38,10 +38,5 @@ <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> </dependency> - <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-config-spring</artifactId> - <version>${project.parent.version}</version> - </dependency> </dependencies> -</project> \ No newline at end of file +</project> diff --git a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java index 9aa9ca5..c6ec474 100644 --- a/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java +++ b/dubbo-container/dubbo-container-spring/src/main/java/org/apache/dubbo/container/spring/SpringContainer.java @@ -19,7 +19,6 @@ package org.apache.dubbo.container.spring; import org.apache.dubbo.common.logger.Logger; import org.apache.dubbo.common.logger.LoggerFactory; import org.apache.dubbo.common.utils.ConfigUtils; -import org.apache.dubbo.config.spring.initializer.DubboApplicationListener; import org.apache.dubbo.container.Container; import org.springframework.context.support.ClassPathXmlApplicationContext; @@ -44,10 +43,7 @@ public class SpringContainer implements Container { if (configPath == null || configPath.length() == 0) { configPath = DEFAULT_SPRING_CONFIG; } - context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+"), false); - context.addApplicationListener(new DubboApplicationListener()); - context.registerShutdownHook(); - context.refresh(); + context = new ClassPathXmlApplicationContext(configPath.split("[,\\s]+")); context.start(); } diff --git a/dubbo-distribution/pom.xml b/dubbo-distribution/pom.xml index 4611320..c5c6f0a 100644 --- a/dubbo-distribution/pom.xml +++ b/dubbo-distribution/pom.xml @@ -251,11 +251,6 @@ <version>${project.version}</version> </dependency> <dependency> - <groupId>org.apache.dubbo</groupId> - <artifactId>dubbo-bootstrap</artifactId> - <version>${project.version}</version> - </dependency> - <dependency> <groupId>com.alibaba</groupId> <artifactId>hessian-lite</artifactId> </dependency> diff --git a/pom.xml b/pom.xml index 5882557..8f3c0e5 100644 --- a/pom.xml +++ b/pom.xml @@ -139,7 +139,6 @@ <module>dubbo-demo</module> <module>dubbo-plugin</module> <module>dubbo-serialization</module> - <module>dubbo-bootstrap</module> <module>dubbo-compatible</module> <module>dubbo-dependencies-bom</module> <module>dubbo-bom</module>