在web应用启动入口是ContextLoaderListener,它是怎么完成启动过程的呢?
首先:
public class ContextLoaderListenerextends Object implements ServletContextListener //Bootstrap listener to start up Spring's root WebApplicationContext. Simply delegates to ContextLoader. //This listener should be registered after Log4jConfigListener in web.xml, if the latter is used.
public abstract interface javax.servlet.ServletContextListener extends java.util.EventListener
1.ContextLoaderListener.java
1 public void contextInitialized(ServletContextEvent event) { 2 this.contextLoader = createContextLoader(); 3 this.contextLoader.initWebApplicationContext(event.getServletContext()); 4 }
2.ContextLoader.java
1 /** 2 * Initialize Spring's web application context for the given servlet context, 3 * according to the "{@link #CONTEXT_CLASS_PARAM contextClass}" and 4 * "{@link #CONFIG_LOCATION_PARAM contextConfigLocation}" context-params. 5 * @param servletContext current servlet context 6 * @return the new WebApplicationContext 7 * @throws IllegalStateException if there is already a root application context present 8 * @throws BeansException if the context failed to initialize 9 * @see #CONTEXT_CLASS_PARAM 10 * @see #CONFIG_LOCATION_PARAM 11 */ 12 public WebApplicationContext initWebApplicationContext(ServletContext servletContext) 13 throws IllegalStateException, BeansException { 14 15 if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { 16 throw new IllegalStateException( 17 "Cannot initialize context because there is already a root application context present - " + 18 "check whether you have multiple ContextLoader* definitions in your web.xml!"); 19 } 20 21 servletContext.log("Initializing Spring root WebApplicationContext"); 22 if (logger.isInfoEnabled()) { 23 logger.info("Root WebApplicationContext: initialization started"); 24 } 25 long startTime = System.currentTimeMillis(); 26 27 try { 28 // Determine parent for root web application context, if any. 29 ApplicationContext parent = loadParentContext(servletContext); 30 31 // Store context in local instance variable, to guarantee that 32 // it is available on ServletContext shutdown. 33 this.context = createWebApplicationContext(servletContext, parent); 34 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); 35 currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), this.context); 36 37 if (logger.isDebugEnabled()) { 38 logger.debug("Published root WebApplicationContext as ServletContext attribute with name [" + 39 WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE + "]"); 40 } 41 if (logger.isInfoEnabled()) { 42 long elapsedTime = System.currentTimeMillis() - startTime; 43 logger.info("Root WebApplicationContext: initialization completed in " + elapsedTime + " ms"); 44 } 45 46 return this.context; 47 } 48 catch (RuntimeException ex) { 49 logger.error("Context initialization failed", ex); 50 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex); 51 throw ex; 52 } 53 catch (Error err) { 54 logger.error("Context initialization failed", err); 55 servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, err); 56 throw err; 57 } 58 }
3.ContextLoader.java
1 protected WebApplicationContext createWebApplicationContext( 2 ServletContext servletContext, ApplicationContext parent) throws BeansException { 3 4 Class contextClass = determineContextClass(servletContext); 5 if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { 6 throw new ApplicationContextException("Custom context class [" + contextClass.getName() + 7 "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); 8 } 9 10 ConfigurableWebApplicationContext wac = 11 (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); 12 wac.setParent(parent); 13 wac.setServletContext(servletContext); 14 wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM)); 15 customizeContext(servletContext, wac); 16 wac.refresh(); 17 18 return wac; 19 }
4.回到了我们上两节提到的AbstractApplicationContext.java
public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. prepareRefresh(); // Tell the subclass to refresh the internal bean factory. ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. beanFactory.destroySingletons(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }
5.下面就不再赘述,详情参考上面两节
微信公众号: 架构师日常笔记 欢迎关注!