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:

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

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.

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};
       }
   }
}

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).

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};
       }
   }
}

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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

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

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.