Role/Purpose of ContextLoaderListener in Spring?
I am learning Spring Framework which is being used in my project. I found the ContextLoaderListener entry in my web.xml file. But could not figure out how exactly it helps a developer?
In the official documentation of ContextLoaderListener it says it is to start WebApplicationContext. Regarding WebApplicationContext JavaDocs say:
Interface to provide configuration for a web application.
But I am not able to understand what I am achieving with ContextLoaderListener which internally initializes the WebApplicationContext ?
As per my understanding, ContextLoaderListener reads the Spring configuration file (with value given against contextConfigLocation in web.xml), parses it and loads the singleton bean defined in that config file. Similarly when we want to load prototype bean, we will use same webapplication context to load it. So we initialize the webapplication with ContextLoaderListener so that we read/parse/validate the config file in advance and whenever we wan to inject dependency we can straightaway do it without any delay. Is this understanding correct?
Solution 1:
Your understanding is correct. The ApplicationContext
is where your Spring beans live. The purpose of the ContextLoaderListener
is two-fold:
-
to tie the lifecycle of the
ApplicationContext
to the lifecycle of theServletContext
and -
to automate the creation of the
ApplicationContext
, so you don't have to write explicit code to do create it - it's a convenience function.
Another convenient thing about the ContextLoaderListener
is that it creates a WebApplicationContext
and provides access to the ServletContext
via ServletContextAware
beans and the getServletContext
method.
Solution 2:
ContextLoaderListener
is optional. Just to make a point here: you can boot up a Spring application without ever configuring ContextLoaderListener
, just a basic minimum web.xml
with DispatcherServlet
.
Here is what it would look like:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID"
version="2.5">
<display-name>Some Minimal Webapp</display-name>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
Create a file called dispatcher-servlet.xml
and store it under WEB-INF
. Since we mentioned index.jsp
in welcome list, add this file under WEB-INF
.
dispatcher-servlet.xml
In the dispatcher-servlet.xml
define your beans:
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="bean1">
...
</bean>
<bean id="bean2">
...
</bean>
<context:component-scan base-package="com.example" />
<!-- Import your other configuration files too -->
<import resource="other-configs.xml"/>
<import resource="some-other-config.xml"/>
<!-- View Resolver -->
<bean
id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>
Solution 3:
For a simple Spring application, you don't have to define ContextLoaderListener
in your web.xml
; you can just put all your Spring configuration files in <servlet>
:
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc-core-config.xml, classpath:spring/business-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
For a more complex Spring application, where you have multiple DispatcherServlet
defined, you can have the common Spring configuration files that are shared by all the DispatcherServlet
defined in the ContextLoaderListener
:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/common-config.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<servlet>
<servlet-name>mvc1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc1-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet>
<servlet-name>mvc2</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/mvc2-config.xmll</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Just keep in mind, ContextLoaderListener
performs the actual initialization work for the root application context.
I found this article helps a lot: Spring MVC – Application Context vs Web Application Context