ChatGPT解决这个技术问题 Extra ChatGPT

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?

can anyone let me know difference between RequestContextListener and ContextLoaderListener

s
sathishs4r

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 the ServletContext 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.


I have a doubt regarding your second point. You said ServletContextListener provides access to ServletContext. But, even if web.xml does not have ServletContextListener, ServletContext can be accessed through WebApplicationContext (WebApplicationContext is to be autowired). So, what does it exactly does related to ServletContext?
It creates the WebApplicationContext. Otherwise it would need to be created manually.
does ContextLoaderListener implement a destroy method to destroy all beans when the web container shuts down?
yes - it does that when contextDestroyed is called. See the API docs.
@sourcedelica I have one doubt after reading this I have checked my applications web.xml. In my xml file there are two listeners ContextLoaderListener and DispatcherServlet. So I guess there is no need of both, is it safe to remove ContextLoaderListener why I am asking because application live since 7-8 months. web.xml is here for your reference.
k
kuporific

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>

If it's optional, when would you want to use it? It seems Spring Security requires it to use the DelegatingFilterProxy.
You have to use it when you want to put your Servlet file in your custom location or with custom name, rather than the default name "[servlet-name]-servlet.xml" and path under "Web-INF/"
Is it good idea to define bean in dispatcher-servlet.xml than applicationContext.xml?
Usually it's better to distribute the beans by reflecting the layers of the architecture of your application. Beans for the presentation layer (for example mvc controllers) can be in dispatcher-servlet.xml. Beans belonging to the service layer should be defined applicationContext.xml. It's not a strict rule, but it's a good practice to achieve separation of concern.
@Ramesh Karna I don't think it's needed for name and location change. I think it's needed when we are initializing multiple Dispatcher servlets and still want a Root context to be shared by all DispaterServlets own context then we need to use ContextLoaderListener.
x
xli

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


the article shared here really ensures deep understanding of the concepts
D
Dileepa

The blog, "Purpose of ContextLoaderListener – Spring MVC" gives a very good explanation.

According to it, Application-Contexts are hierarchial and hence DispatcherSerlvet's context becomes the child of ContextLoaderListener's context. Due to which, technology being used in the controller layer (Struts or Spring MVC) can independent of root context created ContextLoaderListener.


Thanks for sharing it buddy.. :)
s
siddharth nawani

Root and child contexts Before reading further, please understand that –

Spring can have multiple contexts at a time. One of them will be root context, and all other contexts will be child contexts.

All child contexts can access the beans defined in root context; but opposite is not true. Root context cannot access child contexts beans.

ApplicationContext :

applicationContext.xml is the root context configuration for every web application. Spring loads applicationContext.xml file and creates the ApplicationContext for the whole application. There will be only one application context per web application. If you are not explicitly declaring the context configuration file name in web.xml using the contextConfigLocation param, Spring will search for the applicationContext.xml under WEB-INF folder and throw FileNotFoundException if it could not find this file.

ContextLoaderListener Performs the actual initialization work for the root application context. Reads a “contextConfigLocation” context-param and passes its value to the context instance, parsing it into potentially multiple file paths which can be separated by any number of commas and spaces, e.g. “WEB-INF/applicationContext1.xml, WEB-INF/applicationContext2.xml”. 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.

DispatcherServlet DispatcherServlet is essentially a Servlet (it extends HttpServlet) whose primary purpose is to handle incoming web requests matching the configured URL pattern. It take an incoming URI and find the right combination of controller and view. So it is the front controller.

When you define a DispatcherServlet in spring configuration, you provide an XML file with entries of controller classes, views mappings etc. using contextConfigLocation attribute.

WebApplicationContext Apart from ApplicationContext, there can be multiple WebApplicationContext in a single web application. In simple words, each DispatcherServlet associated with single WebApplicationContext. xxx-servlet.xml file is specific to the DispatcherServlet and a web application can have more than one DispatcherServlet configured to handle the requests. In such scenarios, each DispatcherServlet would have a separate xxx-servlet.xml configured. But, applicationContext.xml will be common for all the servlet configuration files. Spring will by default load file named “xxx-servlet.xml” from your webapps WEB-INF folder where xxx is the servlet name in web.xml. If you want to change the name of that file name or change the location, add initi-param with contextConfigLocation as param name.

Comparison and relation between them :

ContextLoaderListener vs DispatcherServlet

ContextLoaderListener creates root application context. DispatcherServlet entries create one child application context per servlet entry. Child contexts can access beans defined in root context. Beans in root context cannot access beans in child contexts (directly). All contexts are added to ServletContext. You can access root context using WebApplicationContextUtils class.

After reading the Spring documentation, following is the understanding:

a) Application-Contexts are hierarchial and so are WebApplicationContexts. Refer documentation here.

b) ContextLoaderListener creates a root web-application-context for the web-application and puts it in the ServletContext. This context can be used to load and unload the spring-managed beans ir-respective of what technology is being used in the controller layer(Struts or Spring MVC).

c) DispatcherServlet creates its own WebApplicationContext and the handlers/controllers/view-resolvers are managed by this context.

d) When ContextLoaderListener is used in tandem with DispatcherServlet, a root web-application-context is created first as said earlier and a child-context is also created by DispatcherSerlvet and is attached to the root application-context. Refer documentation here.

When we are working with Spring MVC and are also using Spring in the services layer, we provide two application-contexts. The first one is configured using ContextLoaderListener and the other with DispatcherServlet

Generally, you will define all MVC related beans (controller and views etc) in DispatcherServlet context, and all cross-cutting beans such as security, transaction, services etc. at root context by ContextLoaderListener.

Refer this for more details : https://siddharthnawani.blogspot.com/2019/10/contextloaderlistener-vs.html


P
Prashant_M

ContextLoaderListner is a Servlet listener that loads all the different configuration files (service layer configuration, persistence layer configuration etc) into single spring application context.

This helps to split spring configurations across multiple XML files.

Once the context files are loaded, Spring creates a WebApplicationContext object based on the bean definition and stores it in the ServletContext of your web application.


A
Anil Agrawal

Basically you can isolate your root application context and web application context using ContextLoaderListner.

The config file mapped with context param will behave as root application context configuration. And config file mapped with dispatcher servlet will behave like web application context.

In any web application we may have multiple dispatcher servlets, so multiple web application contexts.

But in any web application we may have only one root application context that is shared with all web application contexts.

We should define our common services, entities, aspects etc in root application context. And controllers, interceptors etc are in relevant web application context.

A sample web.xml is

<!-- language: xml -->
<web-app>

    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextClass</param-name>
        <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </context-param>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>example.config.AppConfig</param-value>
    </context-param>
    <servlet>
        <servlet-name>restEntryPoint</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>example.config.RestConfig</param-value>
        </init-param>       
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>restEntryPoint</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
    <servlet>
        <servlet-name>webEntryPoint</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextClass</param-name>
            <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
        </init-param>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>example.config.WebConfig</param-value>
        </init-param>       
        <load-on-startup>1</load-on-startup>
    </servlet>  
    <servlet-mapping>
        <servlet-name>webEntryPoint</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

</web-app> 

Here config class example.config.AppConfig can be used to configure services, entities, aspects etc in root application context that will be shared with all other web application contexts (for example here we have two web application context config classes RestConfig and WebConfig)

PS: Here ContextLoaderListener is completely optional. If we will not mention ContextLoaderListener in web.xml here, AppConfig will not work. In that case we need to configure all our services and entities in WebConfig and Rest Config.


r
rulhaniam

https://i.stack.imgur.com/hiv9t.gif

2nd use of this listener is when you want to use spring security.


A
Ajeet Shah

When you want to put your Servlet file in your custom location or with custom name, rather than the default naming convention [servletname]-servlet.xml and path under Web-INF/ ,then you can use ContextLoaderListener.


j
jmj

It will give you point of hook to put some code that you wish to be executed on web application deploy time


Jigar, actually this is what i am trying to find out.What is the feature , default context loader class provides at deployment time?
Changing properties/xml files and let them be reloaded at runt time without restarting the server
b
bharanitharan

Listener class - Listens on an event (Eg.. Server startup/shutdown)

ContextLoaderListener -

Listens during server start up/shutdown Takes the Spring configuration files as input and creates the beans as per configuration and make it ready (destroys the bean during shutdown) Configuration files can be provided like this in web.xml contextConfigLocation /WEB-INF/dispatcher-servlet.xml


S
Salahin Rocky

In the context of spring framework purpose of ContextLoaderListener is to load the other beans in your application such as the middle-tier and data-tier components that drive the back end of the application.


e
evg

Your understanding is correct. I wonder why you don't see any advantages in ContextLoaderListener. For example, you need to build a session factory (to manage database). This operation can take some time, so it's better to do it on startup. Of course you can do it with init servlets or something else, but the advantage of Spring's approach is that you make configuration without writing code.


S
SathishSakthi

If we write web.xml without ContextLoaderListener then we cant give the athuntication using customAuthenticationProvider in spring security. Because DispatcherServelet is the child context of ContextLoaderListener, customAuthenticationProvider is the part of parentContext that is ContextLoaderListener. So parent Context cannot have the dependencies of child context. And so it is best practice to write spring-context.xml in contextparam instead of write it in the initparam.


u
user666

I believe its real use comes when you want to have more than one config files or you have xyz.xml file instead of applicationcontext.xml for eg

<context-param><param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/training-service.xml, /WEB-INF/training-data.xml</param-value> </context-param>

Another approach to ContextLoaderListener is using ContextLoaderServlet like below

<servlet> <servlet-name>context</servlet-name> <servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet>