diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml
index dc333e7a8e4..995209db45e 100644
--- a/dubbo-config/dubbo-config-spring/pom.xml
+++ b/dubbo-config/dubbo-config-spring/pom.xml
@@ -112,18 +112,21 @@
javax.el
test
-
org.springframework
spring-tx
test
-
org.springframework
spring-test
test
+
+ org.apache.tomcat.embed
+ tomcat-embed-core
+ test
+
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
new file mode 100644
index 00000000000..36727e669f4
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializer.java
@@ -0,0 +1,39 @@
+/*
+ * 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 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/DubboWebApplicationInitializer.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboWebApplicationInitializer.java
deleted file mode 100644
index 582535bb8bf..00000000000
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/initializer/DubboWebApplicationInitializer.java
+++ /dev/null
@@ -1,40 +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.web.context.AbstractContextLoaderInitializer;
-import org.springframework.web.context.WebApplicationContext;
-import org.springframework.web.context.support.XmlWebApplicationContext;
-
-/**
- * An initializer to register {@link DubboApplicationListener}
- * to the ApplicationContext seamlessly.
- */
-public class DubboWebApplicationInitializer extends AbstractContextLoaderInitializer {
-
- /**
- * This method won't be triggered if running on spring-boot.
- * It only works when running under a servlet container.
- * @return a WebApplicationContext with DubboApplicationListener registered.
- */
- @Override
- protected WebApplicationContext createRootApplicationContext() {
- XmlWebApplicationContext webApplicationContext = new XmlWebApplicationContext();
- webApplicationContext.addApplicationListener(new DubboApplicationListener());
- return webApplicationContext;
- }
-}
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
new file mode 100644
index 00000000000..220874ab78c
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,22 @@
+
+
+ dubbo-fragment
+
+
+
+
+
+
+
+
+ contextInitializerClasses
+ org.apache.dubbo.config.spring.initializer.DubboApplicationContextInitializer
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
\ No newline at end of file
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
new file mode 100644
index 00000000000..2c84095f4e3
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/initializer/DubboApplicationContextInitializerTest.java
@@ -0,0 +1,87 @@
+/*
+ * 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("src/test/resources");
+ 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 1 application listener
+ Assert.assertEquals(1, 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("src/test/resources");
+ 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
+ Assert.assertEquals(1, 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 testMetadataComplete() throws Exception {
+ Tomcat tomcat = new Tomcat();
+ tomcat.setBaseDir("src/test/resources");
+ 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/resources/applicationContext.xml b/dubbo-config/dubbo-config-spring/src/test/resources/applicationContext.xml
new file mode 100644
index 00000000000..977a8a43d05
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/applicationContext.xml
@@ -0,0 +1,6 @@
+
+
+
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test/WEB-INF/web.xml b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test/WEB-INF/web.xml
new file mode 100644
index 00000000000..25214e23e35
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test/WEB-INF/web.xml
@@ -0,0 +1,14 @@
+
+
+ dubbo-demo
+
+
+ contextConfigLocation
+ classpath:applicationContext.xml
+
+
+
+ org.springframework.web.context.ContextLoaderListener
+
+
+
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test2/WEB-INF/web.xml b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test2/WEB-INF/web.xml
new file mode 100644
index 00000000000..0da8d8a5db2
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test2/WEB-INF/web.xml
@@ -0,0 +1,10 @@
+
+
+ dubbo-demo
+
+
+ contextConfigLocation
+ classpath:applicationContext.xml
+
+
+
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test3/WEB-INF/web.xml b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test3/WEB-INF/web.xml
new file mode 100644
index 00000000000..81a5a13f9ed
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/webapps/test3/WEB-INF/web.xml
@@ -0,0 +1,10 @@
+
+
+ dubbo-demo
+
+
+ contextConfigLocation
+ classpath:applicationContext.xml
+
+
+