咱們首先指定咱們須要加載的Spring配置文件,在tomcat容器啓動後,會尋找項目中的web.xml文件,加載其中的信息,並建立一個ServletContext上下文對象,之後再web應用中能夠得到其中的值。web
最早加載的就是<context-param>節點,該節點加載咱們的Spring配置文件,配置文件中是咱們須要往Spring容器中註冊的Bean對象配置。有兩種加載方式,若是在web.xml中不指定<context-param>,會默認去加載/WEB-INF/下的ApplicationContext.xml。spring
<context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/config/application-context.xml /WEB-INF/config/zxw/zxw-context.xml </param-value> </context-param>
加載完配置文件後,須要配置監聽器。tomcat
<listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener>
監聽器的做用是監聽ServletContext的對象是否建立,web容器一旦啓動,就會建立一個ServletContext對象,因此監聽器必定會觸發,從而執行監聽器的contextInitialized方法。方法看Spring源碼以下app
public class ContextLoaderListener extends ContextLoader implements ServletContextListener { public ContextLoaderListener() { } public ContextLoaderListener(WebApplicationContext context) { super(context); }
//執行的監聽器方法 public void contextInitialized(ServletContextEvent event) { this.initWebApplicationContext(event.getServletContext()); } public void contextDestroyed(ServletContextEvent event) { this.closeWebApplicationContext(event.getServletContext()); ContextCleanupListener.cleanupAttributes(event.getServletContext()); } }
監聽器執行contextInitialized方法,從該方法的參數咱們也可以看出來,觸發的事件是ServletContext對象建立了沒,而後執行觸發事件,也就是執行initWebApplicationContext方法,實際上該方法定義在其父類ContextLoader中,咱們看該方法的具體實現以下ide
1 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) { 2 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { 3 throw new IllegalStateException("Cannot initialize context because there is already a root application context present - check whether you have multiple ContextLoader* definitions in your web.xml!"); 4 } else { 5 Log logger = LogFactory.getLog(ContextLoader.class); 6 servletContext.log("Initializing Spring root WebApplicationContext"); 7 if (logger.isInfoEnabled()) { 8 logger.info("Root WebApplicationContext: initialization started"); 9 } 10 11 long startTime = System.currentTimeMillis(); 12 13 try { 14 if (this.context == null) { 15 this.context = this.createWebApplicationContext(servletContext); 16 } 17 18 if (this.context instanceof ConfigurableWebApplicationContext) { 19 ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext)this.context; 20 if (!cwac.isActive()) { 21 if (cwac.getParent() == null) { 22 ApplicationContext parent = this.loadParentContext(servletContext); 23 cwac.setParent(parent); 24 } 25 26 this.configureAndRefreshWebApplicationContext(cwac, servletContext); 27 } 28 } 29 30 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 31 ClassLoader ccl = Thread.currentThread().getContextClassLoader(); 32 if (ccl == ContextLoader.class.getClassLoader()) { 33 currentContext = this.context; 34 } else if (ccl != null) { 35 currentContextPerThread.put(ccl, this.context); 36 } 37 38 if (logger.isDebugEnabled()) { 39 logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); 40 } 41 42 if (logger.isInfoEnabled()) { 43 long elapsedTime = System.currentTimeMillis() - startTime; 44 logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); 45 } 46 47 return this.context; 48 } catch (RuntimeException var8) { 49 logger.error("Context initialization failed", var8); 50 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var8); 51 throw var8; 52 } catch (Error var9) { 53 logger.error("Context initialization failed", var9); 54 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, var9); 55 throw var9; 56 } 57 } 58 }
該方法返回一個WebApplicationContext對象,WebApplicationContext接口繼承ApplicationContext接口,該接口繼承BeanFactory接口,由此看來,這幾個接口都是Spring容器,用來註冊配置文件中的Bean,Spring容器不只建立了配置文件中的Bean,並且還負責管理this
Bean的生命週期,上面的initWebApplicationContext方法返回一個WebApplicationContext對象context,咱們能夠經過該對象得到咱們配置在Bean中的對象。spa