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.
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.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
