As I understand, a Spring based web application is initialized as below:
Step 1: Servlet container (e.g. Tomcat)
locates the implementation of ServletContainerInitializer
, which is SpringServletContainerInitializer
.
Step 2: SpringServletContainerInitializer
creates DispatcherServlet
and ContextLoaderListener
Step 3: DispatcherServlet
creates servlet application context
. And ContextLoaderListener
creates root application context
.
Step 1 is defined by Servlet 3.0 spec. Step 2, 3 are totally defined by Spring.
I can see the rational of putting web
beans in servlet context and non-web
beans in root context. But why do we have to create these 2 contexts in different places, i.e. DispatcherServlet
and ContextLoaderListener
?
If all we want is just to prepare everything necessary, why not just create both contexts in ContextLoaderListener
since it can be seen as the main()
method of the whole web application. I think that's more logic and current approach only complicates things up.
Based on @Shailendra's reply, I draw this:
My understanding is, Spring introduced the application context
concepts and store them in the Servlet Context
. Servlet Context is a concept introduced by java servlet technolgoy.
I guess the DispatcherServlet
implementation should have a member variable to hold the key
to its servlet application context
in the servlet context
. So it can access it's own context. Maybe the key is the servlet name.
And the root application context
should have a well-known key so everyone can access it.
The well-known key for root application context
is this:
(in org.springframework.web.context.WebApplicationContext
)
String ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE = WebApplicationContext.class.getName() + ".ROOT";
The DispatcherServlet
does have a reference to its WebApplicationContext
. It inherits the following memeber from FrameworkServlet
:
/** WebApplicationContext for this servlet */
private WebApplicationContext webApplicationContext;
And
public FrameworkServlet(WebApplicationContext webApplicationContext) {
this.webApplicationContext = webApplicationContext;
}
We can have multiple application contexts that share a parent-child relationship. A context hierarchy allows multiple child contexts to share beans which reside in the parent context. Each child context can override configuration inherited from the parent context.
As you are using Spring boot, there is only one context by default: ApplicationContext . This will contain all your things (Beans) and Components you need.
The need is for multiple application contexts (for different parts of the application). To enable that, you can use multiple dispatcher servlets.
Beans/configuraiton loaded by the ContextLoaderListener is the root context, everything loaded by a DispatcherServlet (or MessageDispatcherServlet for Spring-WS) is a child context. You can have multiple servlets which all have access to the root context (should contain shared resources like services, etc.).
But why do we have to create these 2 contexts in different places, i.e. DispatcherServlet and ContextLoaderListener
Because the two contexts are supposed to be different but yet have a hierarchical relation in order to be able to override. Typically the context loaded using ContextLoaderListener
is "root" context which belongs to the whole application while the one initialized using DispatcherServlet
is actually specific to that servlet. Technically you can have multiple servlets in an application and so multiple such contexts each specific for respective servlet but having same root context. For more details see another of my answer here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With