ApplicationContext is the core of spring, which we usually interpret as context, I want to use "container" to express it easier to understand some, ApplicationContext is "the container of Application", in the Web application, We'll use Webapplicationcontext,webapplicationcontext to inherit from ApplicationContext. The initialization of Webapplicationcontext is different from Beanfactory.applicationcontext because Webapplicationcontext needs to ServletContext instances, This means that it must have a web container in order to complete the startup work. Readers with web development experience know that you can configure a self-initiated servlet or a definition Web Container listener (servletcontextlistener) in XML. With either of these, we can start the work of the Spring Web application context.
Spring provides a servlet and Web container listener for starting Webapplicationcontext, respectively:
Org.springframework.web.context.contextloaderservlet;org.springframework.web.context.contextloaderlistener.
Both of these methods initialize the Webapplicationcontext when the Web App is launched, and I personally think that Listerner is better than the servlet because Listerner listens to the start and end of the application, And the servlet has to be started slightly delayed some, if at this time to do some business operations, the pre-and post-activation sequence is affected.
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/ web-inf/applicationcontext.xml</param-value> </context-param> <listener> <listener- Class>org.springframework.web.context.contextloaderlistener</listener-class
So what exactly did you do in Contextloaderlistener and Contextloaderservlet?
Taking Contextloaderlistener as an example, we can see
public class Contextloaderlistener Span style= "COLOR: #0000ff" >implements Servletcontextlistener { private Contextloader Contextloader; /** * Initialize the root Web application con Text. */ public void contextinitialized (Servletcontextevent event) { this . Contextloader = Createcontextloader (); this
Obviously, Contextloaderlistener implements the Serveletcontextlistenet, and when the ServletContext is initialized, it will initialize the spring, and you will certainly think, Spring initialization should have something to do with ServletContext, right? Does it matter? Now let's see
Contextloader.initwebapplicationcontext method.
Contextloader is a tool class used to initialize Webapplicationcontext, the main method is Initwebapplicationcontext, We continue to study Initwebapplicationcontext this method:
PublicWebapplicationcontext Initwebapplicationcontext (ServletContext servletcontext)throwsIllegalStateException, beansexception {//Find from ServletContext, whether there is a value with Webapplicationcontext.root_web_application_context_attribute as key if(Servletcontext.getattribute (webapplicationcontext.root_web_application_context_attribute)! =NULL) { Throw NewIllegalStateException ("Cannot initialize context because there is already a root application context present-" + "Check Wheth Er you has multiple contextloader* definitions in your web.xml! "); } Try { //determine parent for root Web application context, if any. ApplicationContext parent =Loadparentcontext (ServletContext); //it is available on ServletContext shutdown. This. Context =Createwebapplicationcontext (ServletContext, parent); //put the applicationcontext into the ServletContext, whose key is <webapplicationcontext.root_web_application_context_attribute Servletcontext.setattribute (Webapplicationcontext.root_web_application_context_attribute, This. Context); //Place the applicationcontext into the global static constant map of Contextloader, where key is: Thread.CurrentThread (). Getcontextclassloader () That is, the current thread class loaderCurrentcontextperthread.put (Thread.CurrentThread (). Getcontextclassloader (), This. Context); return This. Context; }
From the code above you should understand that after spring initialization, the applicationcontext is stored in two places (ServletContext and Currentcontextperthread), So does that mean we can get applicationcontext in two ways?
The first method of obtaining:
Note: Webapplicationcontext.root_web_application_context_attribute = Webapplicationcontext. class. GetName () + ". ROOT "" Org.springframework.web.context.WebApplicationContext.ROOT "
So can we get applicationcontext this way:
Request. getsession (). Getservletcontext (). getattribute (" Org.springframework.web.context.WebApplicationContext.ROOT ")
Yes, and when we think of this approach, spring has already provided us with an interface:
Public Abstract classWebapplicationcontextutils { Public StaticWebapplicationcontext Getrequiredwebapplicationcontext (ServletContext SC)throwsillegalstateexception {webapplicationcontext WAC=Getwebapplicationcontext (SC); if(WAC = =NULL) { Throw NewIllegalStateException ("No webapplicationcontext found:no contextloaderlistener registered?")); } returnWAC; }
The Getwebapplicationcontext method is as follows:
Public Static webapplicationcontext Getwebapplicationcontext (ServletContext SC) { return Getwebapplicationcontext (SC, webapplicationcontext.root_web_application_context_attribute);
The second method:
When it comes to spring initialization, the ApplicationContext is saved in a map to Contextloader, so can we pass map.get (key)??? Unfortunately, this map is private.
Private Static Final Map Currentcontextperthread = collectionfactory.createconcurrentmapifpossible (1);
Spring provides us with a way to:
Public Static Webapplicationcontext Getcurrentwebapplicationcontext () { return (webapplicationcontext ) Currentcontextperthread.get (Thread.CurrentThread (). Getcontextclassloader ()); }
What good is the second approach compared to the first? Is that it does not require parameters, as long as in the Web container, after spring initialization, you do not need to pass any parameters, you can get applicationcontext. However, this method does not exist in the Spring2.52 version, but it is available in version 2.5.5.
In fact, the second approach looks simple, but his principle is still somewhat difficult, and he is related to the thread context of the ClassLoader, which is useful in our common MySQL driver.
The Third Way:
The Help class that borrows Applicationcontextaware,applicationcontext can automatically load ApplicationContext as long as you implement this interface for a class and configure the implementation class in the spring configuration file , spring will automatically help you inject applicationcontext.applicationcontextaware with the following code structure:
Public Interface applicationcontextaware { voidthrows beansexception; }
On this one interface. A Applicationcontexthelper class can be implemented as simple as this:
Public classApplicationhelperImplementsApplicationcontextaware {PrivateApplicationContext ApplicationContext; Public voidSetapplicationcontext (ApplicationContext applicationcontext)throwsbeansexception { This. ApplicationContext =ApplicationContext; } PublicApplicationContext Getapplicationcontext () {return This. ApplicationContext; } }
By Applicationhelper we can get the Appilcationcontext class we want.
Three ways to initialize Webapplicationcontext