Some time ago in the company to do a project, the project was implemented with the spring framework, the Web container is TOMCT 5, although the project is done, but it is not clear how the spring IOC container starts and functions in the Web container. So just take the time to look at the source code of spring and learn how it works.
We know that for Web applications that use spring, you do not have to create a spring container manually, but instead create a spring container declaratively through a configuration file. Therefore, there are two ways to create a spring container in a Web application:
1. Configure the Create spring container directly in the Web. xml file.
2. Create a spring container using the extensibility points of the third-party MVC framework.
In fact, the first way is more common. In order for the spring container to launch with the launch of the Web app, there are two ways:
1. Implement with Servletcontextlistener.
2. Use Load-on-startup servlet implementations.
Spring provides an implementation class Contextloaderlistener for Servletcontextlistener, which can be used as listener. It will automatically find the Applicationcontext.xml file under Web-inf when it is created, so if there is only one configuration file and the file name is Applicationcontext.xml, simply add the following configuration fragment to the Web. xml file.
<listener> <listener-class> Org.springframework.web.context.ContextLoaderListener < /listener-class>
If more than one configuration file needs to be loaded, consider using the <context-param...> element to determine the file name of the configuration file. When Contextloaderlistener loads, it looks for an initialization parameter named Contentconfiglocation. Therefore, when you configure <context-param...>, the parameter named Contextconfiglocation is specified.
The Web. xml file with multiple configuration files is as follows:
<context-param> <param-name>contextLoaderListener</param-name> <param-value> web-inf/*.xml, Classpath:spring/*.xml </param-value> </context-param> <listener > <listener-class> org.springframework.web.context.ContextLoaderListener </ Listener-class> </listener>
Separate multiple profiles with ",".
Let's take a look at the concrete implementation of the process, first we start with Contextloaderlistener, its code is as follows:
public class Contextloaderlistener implements Servletcontextlistener { private contextloader contextloader; /** * This method is used to initialize the Web application context of the * /public void contextinitialized (Servletcontextevent event) { This.contextloader = Createcontextloader (); This.contextLoader.initWebApplicationContext (Event.getservletcontext ()); } /** * Create a contextloader. * @return The new contextloader * /protected Contextloader Createcontextloader ( ) {return new Contextloader (); } ................ }
When we saw the initialization of the Web application context, we first created a contextloader with new Contextloader (),
What did new Contextloader () specifically do? Code snippet for Contextloader:
static { try { //Create a Classpathresource object here, load contextloader.properties, to create the corresponding ApplicationContext container // This file is in the same directory as the Contextloader class, and the file contents are as follows: //org.springframework.web.context.webapplicationcontext= Org.springframework.web.context.support.XmlWebApplicationContext //So, Spring defaults to initialize Xmlwebapplicationcontext classpathresource resource = new Classpathresource (default_strategies_ PATH, contextloader.class); Get a Properties object, followed by the class name to create the ApplicationContext container defaultstrategies = propertiesloaderutils.loadproperties ( Resource); } catch (IOException ex) { throw new IllegalStateException ("Could not load ' contextloader.properties ':" + Ex.getmessa GE ()); } }
The code comments have been made very clear, it is easy to understand it? Hey......
Again, let's take a look at the implementation process of the Initwebapplicationcontext method:
Public Webapplicationcontext Initwebapplicationcontext (ServletContext servletcontext) throws illegals Tateexception, Beansexception {//Gets ApplicationContext container from ServletContext, if it already exists, prompts initialization of container failed, checks web. xml file A description of whether there is more than one container loader//ServletContext interface: public interface ServletContext//defines a series of methods to be used with the corresponding servlet container such as obtaining a MIME type for a file, dispatching a request, or writing a log to a log file. Every web-app can have only one Servletcontext,web-app can be a folder with a Web application file, or a. war file. The ServletContext object is contained within the ServletConfig object, and the ServletConfig object provides the Servlet object when the servlet is initialized. if (Servletcontext.getattribute (webapplicationcontext.root_web_application_context_attribute) = null) { throw new IllegalStateException ("Cannot initialize context because there is already a root appli cation context Present-"+" check whether you had multiple contextloader* definitions in your Web.xml! "); } servletContext.log ("Initializing Spring root Webapplicationcontext"); if (logger.isinfoenabled ()) {Logger.info ("Root webapplicationcontext:initialization started"); } Long StartTime = System.currenttimemillis (); try {//Determine parent for root Web application context, if any. Gets the parent container applicationcontext parent = Loadparentcontext (ServletContext); Store context in local instance variable, to guarantee that//It's available on ServletContext SHUTD Own. Create ApplicationContext container This.context = Createwebapplicationcontext (ServletContext, parent); Put the container into the ServletContext Servletcontext.setattribute (webapplicationcontext.root_web_application_co Ntext_attribute, This.context); if (logger.isdebugenabled ()) { Logger.debug ("Published root webapplicationcontext as ServletContext attribute with name [" + Webapplicationcontext.root_web_application_context_attribute + "]"); } if (logger.isinfoenabled ()) {Long elapsedtime = System.currenttimemillis ()-Star Ttime; Logger.info ("Root Webapplicationcontext:initialization completed in" + ElapsedTime + "MS"); } return this.context; } catch (RuntimeException ex) {logger.error ("Context initialization Failed", ex); Servletcontext.setattribute (Webapplicationcontext.root_web_application_context_attribute, ex); Throw ex; } catch (Error err) {logger.error ("Context initialization Failed", err); Servletcontext.setattribute (Webapplicationcontext.root_web_appLication_context_attribute, err); throw err; As you can see from the code above, the ApplicationContext container we created is placed in the ServletContext. What is ServletContext? In the Web container, the ServletContext provides the hosting environment for the spring IOC container, corresponding to the system that establishes an IOC container. The first thing that needs to be established is the root context, which holds objects such as business objects, data access objects, resources, things managers, and other middle-tier objects. On the basis of this context, and web MVC, there will also be a context to hold MVC objects such as controllers, thus constituting a hierarchical context structure. From the initwebapplicationcontext you can see that the real creation of the ApplicationContext container is implemented by the Createwebapplicationcontext method, and its code is as follows: protected Webapplicationcontext Createwebapplicationcontext (ServletContext servletcontext, ApplicationContext Pare NT) throws Beansexception {//First decide the class of ApplicationContext container to create classes class Contextclass = det Erminecontextclass (ServletContext); If the obtained class is not of type configurablewebapplicationcontext, creating the container fails, so the container created here must be the Configurablewebapplicationcontext type if (! ConfigurableWebApplicationContext.class.isAssignableFrom (Contextclass)) {THRow new Applicationcontextexception ("Custom context class [" + Contextclass.getname () + "] is not of type ["+ ConfigurableWebApplicationContext.class.getName () +"] "); }//Instantiate spring container configurablewebapplicationcontext WAC = (configurabl Ewebapplicationcontext) Beanutils.instantiateclass (Contextclass); Wac.setparent (parent); Wac.setservletcontext (ServletContext); Gets the Contextconfiglocation initialization parameter, which records multiple configuration files that need to be loaded (that is, the configuration file that defines the bean) String configlocation = Servletcontext.getin Itparameter (Config_location_param); if (configlocation! = null) {wac.setconfiglocations (Stringutils.tokenizetostringarray (conf Iglocation, configurablewebapplicationcontext.config_location_delimiters)); } Wac.refresh (); return WAC; }
The Createwebapplicationcontext method implementation steps are:
1. First determine the class of the ApplicationContext container to be created
2. Instantiate the ApplicationContext container
But how does it decide which container class to create? Let's take a look at the Determinecontextclass method:
Protected Class Determinecontextclass (ServletContext servletcontext) throws Applicationcontextexception { Gets the class name of the container that needs to be initialized from web. Contextclassname = Servletcontext.getinitparameter (context_class_ PARAM); If the obtained class name is not empty, the container's class object is created if (contextclassname! = null) {try { Return Classutils.forname (Contextclassname); } catch (ClassNotFoundException ex) {throw new Applicationcontextexception ( "Failed to load Custom context class [" + Contextclassname + "]", ex); }}//otherwise create the default container's class object, i.e.: Org.springframework.web.context.support.XmlWebApplicationContext When creating contextloader, Defaultstrategies = propertiesloaderutils.loadproperties (Resource); The code is ready for the default container class else {contextclassname = defAultstrategies.getproperty (WebApplicationContext.class.getName ()); try {return classutils.forname (contextclassname); } catch (ClassNotFoundException ex) {throw new ApplicationContext Exception ("Failed to load Default context class [" + Contextclassname + "]", ex); } } }
The method first determines the initialization parameters from the Web. xml file Context_class_param (defined as public static final String Context_class_param = "Contextclass";) Gets whether the class name exists, if present, the container's class, otherwise returns the default class. How to get the default container class, notice the code comment when creating Contextloader.
As a result, spring not only has the default ApplicationContext container class, but also allows us to customize the ApplicationContext container class, but spring does not define our custom ApplicationContext container classes.
2, using Load-on-startup servlet implementation.
<servlet> <servlet-name>springServlet</servlet-name> <servlet-class> org.springframework.web.servlet.dispatcherservlet</servlet-class> <init-param> < Param-name>contextconfiglocation</param-name> <param-value>/web-inf/spring-mvc.xml</ param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet > <servlet-mapping> <servlet-name>springServlet</servlet-name> < Url-pattern>/</url-pattern> </servlet-mapping>
Well, that's the whole process of how spring's IOC container starts and works in the Web container. A careful friend can see that the ApplicationContext container is created while the Bean class defined in the configuration file is initialized, and the Wac.refresh () in the Createwebapplicationcontext method; This code is used to initialize the Bean class defined in the configuration file. Its specific implementation process is not fully understood, and so on to understand and share with you!
The IOC container for spring Source Research initializes the process in the Web container