Backend Development 12 min read

How Spring Initializes Parent and Child Containers via web.xml

This article explains how Spring 5.3.23 uses web.xml to configure a ContextLoaderListener that creates and refreshes the parent WebApplicationContext, and how DispatcherServlet initializes the child container, detailing the configuration parameters, default locations, and the refresh process.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
How Spring Initializes Parent and Child Containers via web.xml

Environment: Spring 5.3.23

Configuration file (web.xml)

If you don't use annotation‑based configuration, a typical Spring Web project defines the following entries in web.xml :

<code>&lt;web-app&gt;
   &lt;listener&gt;
     &lt;listener-class&gt;org.springframework.web.context.ContextLoaderListener&lt;/listener-class&gt;
   &lt;/listener&gt;
   &lt;context-param&gt;
     &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
     &lt;param-value&gt;/WEB-INF/app-context.xml&lt;/param-value&gt;
   &lt;/context-param&gt;
   &lt;servlet&gt;
     &lt;servlet-name&gt;app&lt;/servlet-name&gt;
     &lt;servlet-class&gt;org.springframework.web.servlet.DispatcherServlet&lt;/servlet-class&gt;
     &lt;init-param&gt;
       &lt;param-name&gt;contextConfigLocation&lt;/param-name&gt;
       &lt;param-value&gt;&lt;/param-value&gt;
     &lt;/init-param&gt;
     &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;
   &lt;/servlet&gt;
   &lt;servlet-mapping&gt;
     &lt;servlet-name&gt;app&lt;/servlet-name&gt;
     &lt;url-pattern&gt;/app/*&lt;/url-pattern&gt;
   &lt;/servlet-mapping&gt;
&lt;/web-app&gt;</code>

Parent container initialization

The listener configured above ( ContextLoaderListener ) initializes the parent WebApplicationContext . The source of ContextLoader shows how it loads ContextLoader.properties , determines the concrete ApplicationContext class, creates and refreshes it.

<code>public class ContextLoader {
   private WebApplicationContext context;
   private static final Properties defaultStrategies;
   public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation";
   static {
       try {
           String DEFAULT_STRATEGIES_PATH = "ContextLoader.properties";
           ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader.class);
           defaultStrategies = PropertiesLoaderUtils.loadProperties(resource);
       }
   }
   protected WebApplicationContext createWebApplicationContext(ServletContext sc) {
       Class<?> contextClass = determineContextClass(sc);
       return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
   }
   protected Class<?> determineContextClass(ServletContext servletContext) {
       String contextClassName = servletContext.getInitParameter("contextClass");
       if (contextClassName != null) {
           return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());
       } else {
           String contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());
           return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());
       }
   }
   protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac, ServletContext sc) {
       wac.setServletContext(sc);
       String configLocationParam = sc.getInitParameter(CONFIG_LOCATION_PARAM);
       if (configLocationParam != null) {
           wac.setConfigLocation(configLocationParam);
       }
       wac.refresh();
   }
}

public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
   public void contextInitialized(ServletContextEvent event) {
       initWebApplicationContext(event.getServletContext());
   }
   public WebApplicationContext initWebApplicationContext(ServletContext servletContext) {
       if (this.context == null) {
           this.context = createWebApplicationContext(servletContext);
       }
       if (this.context instanceof ConfigurableWebApplicationContext) {
           ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) this.context;
           if (!cwac.isActive()) {
               configureAndRefreshWebApplicationContext(cwac, servletContext);
           }
       }
       servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context);
       return this.context;
   }
}

public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
   public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
   public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
   public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
   protected String[] getDefaultConfigLocations() {
       if (getNamespace() != null) {
           return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
       } else {
           return new String[] {DEFAULT_CONFIG_LOCATION};
       }
   }
}
</code>

Summary of the parent‑container steps:

Obtain contextClass from the configuration; if absent, read ContextLoader.properties to get the default ApplicationContext implementation.

Refresh and initialize the XmlWebApplicationContext (or the class you configured), using contextConfigLocation or the default /WEB-INF/applicationContext.xml .

Store the created context in ServletContext under WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE .

Child container (DispatcherServlet) initialization

The child container is created by DispatcherServlet . Its init method reads the init‑param contextConfigLocation , sets it on the underlying FrameworkServlet , and then creates a WebApplicationContext (by default XmlWebApplicationContext ).

<code>public abstract class HttpServletBean extends HttpServlet implements EnvironmentCapable, EnvironmentAware {
   public final void init() throws ServletException {
       PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(), this.requiredProperties);
       if (!pvs.isEmpty()) {
           BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
           ResourceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());
           bw.registerCustomEditor(Resource.class, new ResourceEditor(resourceLoader, getEnvironment()));
           initBeanWrapper(bw);
           bw.setPropertyValues(pvs, true);
       }
       initServletBean();
   }
}

public abstract class FrameworkServlet extends HttpServletBean implements ApplicationContextAware {
   public static final Class<?> DEFAULT_CONTEXT_CLASS = XmlWebApplicationContext.class;
   public static final String DEFAULT_NAMESPACE_SUFFIX = "-servlet";
   private String contextConfigLocation;
   protected final void initServletBean() throws ServletException {
       this.webApplicationContext = initWebApplicationContext();
   }
   protected WebApplicationContext initWebApplicationContext() {
       WebApplicationContext rootContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
       WebApplicationContext wac = null;
       if (wac == null) {
           wac = findWebApplicationContext();
       }
       if (wac == null) {
           wac = createWebApplicationContext(rootContext);
       }
       return wac;
   }
   protected WebApplicationContext createWebApplicationContext(@Nullable WebApplicationContext parent) {
       return createWebApplicationContext((ApplicationContext) parent);
   }
   protected WebApplicationContext createWebApplicationContext(@Nullable ApplicationContext parent) {
       Class<?> contextClass = getContextClass();
       ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);
       wac.setEnvironment(getEnvironment());
       wac.setParent(parent);
       String configLocation = getContextConfigLocation();
       if (configLocation != null) {
           wac.setConfigLocation(configLocation);
       }
       configureAndRefreshWebApplicationContext(wac);
       return wac;
   }
   protected void configureAndRefreshWebApplicationContext(ConfigurableWebApplicationContext wac) {
       wac.setServletContext(getServletContext());
       wac.setServletConfig(getServletConfig());
       wac.setNamespace(getNamespace());
       wac.refresh();
   }
   public String getNamespace() {
       return (this.namespace != null ? this.namespace : getServletName() + DEFAULT_NAMESPACE_SUFFIX);
   }
   public String getContextConfigLocation() {
       return this.contextConfigLocation;
   }
}

public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
   public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";
   public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";
   public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";
   protected String[] getDefaultConfigLocations() {
       if (getNamespace() != null) {
           return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};
       } else {
           return new String[] {DEFAULT_CONFIG_LOCATION};
       }
   }
}
</code>

Key steps for the child container:

Read servlet‑specific configuration parameters (e.g., contextConfigLocation ).

Instantiate the Spring container, set the configuration file (or fall back to the default).

Determine the namespace ( servlet‑name‑servlet ) and refresh the context.

After both the parent and child containers are refreshed, the Spring MVC application is ready to handle incoming requests.

JavaSpringApplicationContextDispatcherServletContextLoaderListenerWeb.xml
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.