Spring配置文件是集成了Spring框架的项目的核心,引擎从哪里开始,中间都执行了哪些操作,小谈一下它的执行流程。
容器先是加载web .xml
接着是applicationContext.xml在web .xml里的注册
一种方法是加入ContextLoaderServlet这个servlet
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB -INF/applicationContext.xml</param-value> </context-param> <servlet> <servlet-name>context</servlet-name> <servlet-class> org.springframework.web .context.ContextLoaderServlet </servlet-class> <load-on-startup>0</load-on-startup> </servlet>
还有一种是添加ContextLoaderListener这个监听器
<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> </listener>
下面是ContextLoaderServlet源代码
package org.springframework.web .context; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class ContextLoaderServlet extends HttpServlet { private ContextLoader contextLoader ; /** * Initialize the root web application context. */ public void init() throws ServletException { this.contextLoader = createContextLoader(); this.contextLoader .initWebApplicationContext(getServletContext()); } /** * Create the ContextLoader to use. Can be overridden in subclasses. * @return the new ContextLoader */ protected ContextLoader createContextLoader() { return new ContextLoader (); } /** * Return the ContextLoader used by this servlet. * @return the current ContextLoader */ public ContextLoader getContextLoader() { return this.contextLoader ; } /** * Close the root web application context. */ public void destroy() { if (this.contextLoader != null) { this.contextLoader .closeWebApplicationContext(getServletContext()); } } /** * This should never even be called since no mapping to this servlet should * ever be created in web .xml. That's why a correctly invoked Servlet 2.3 * listener is much more appropriate for initialization work ;-) */ public void service(HttpServletRequest request, HttpServletResponse response) throws IOException { getServletContext().log( "Attempt to call service method on ContextLoaderServlet as [" + request.getRequestURI() + "] was ignored"); response.sendError(HttpServletResponse.SC_BAD_REQUEST); } public String getServletInfo() { return "ContextLoaderServlet for Servlet API 2.3 " + "(deprecated in favor of ContextLoaderListener for Servlet API 2.4)"; } }
ContextLoaderListener源代码
package org.springframework.web .context; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; public class ContextLoaderListener implements ServletContextListener { private ContextLoader contextLoader ; /** * Initialize the root web application context. */ public void contextInitialized(ServletContextEvent event) { this.contextLoader = createContextLoader(); this.contextLoader .initWebApplicationContext(event.getServletContext()); } /** * Create the ContextLoader to use. Can be overridden in subclasses. * @return the new ContextLoader */ protected ContextLoader createContextLoader() { return new ContextLoader (); } /** * Return the ContextLoader used by this listener. * @return the current ContextLoader */ public ContextLoader getContextLoader() { return this.contextLoader ; } /** * Close the root web application context. */ public void contextDestroyed(ServletContextEvent event) { if (this.contextLoader != null) { this.contextLoader .closeWebApplicationContext(event.getServletContext()); } } }
以上都提到了ContextLoader 这个类
package org.springframework.web .context; public class ContextLoader { public static final String CONTEXT_CLASS_PARAM = "contextClass"; public static final String CONFIG_LOCATION_PARAM = "contextConfigLocation"; public static final String LOCATOR_FACTORY_SELECTOR_PARAM = "locatorFactorySelector"; public static final String LOCATOR_FACTORY_KEY_PARAM = "parentContextKey"; private static final String DEFAULT_STRATEGIES_PATH = "ContextLoader .properties"; private static final Properties defaultStrategies; static { try { ClassPathResource resource = new ClassPathResource(DEFAULT_STRATEGIES_PATH, ContextLoader .class); defaultStrategies = PropertiesLoaderUtils.loadProperties(resource); } catch (IOException ex) { throw new IllegalStateException("Could not load 'ContextLoader .properties': " + ex.getMessage()); } } private static final Log logger = LogFactory.getLog(ContextLoader .class); private static final Map currentContextPerThread = CollectionFactory.createConcurrentMapIfPossible(1); private WebApplicationContext context; private BeanFactoryReference parentContextRef; public WebApplicationContext initWebApplicationContext(ServletContext servletContext) throws IllegalStateException, BeansException { if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null) { 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!"); } 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. ApplicationContext parent = loadParentContext(servletContext); // Store context in local instance variable, to guarantee that // it is available on ServletContext shutdown. this.context = createWebApplicationContext(servletContext, parent); servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this.context); currentContextPerThread.put(Thread.currentThread().getContextClassLoader(), 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() - startTime; 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; } } protected WebApplicationContext createWebApplicationContext( ServletContext servletContext, ApplicationContext parent) throws BeansException { Class contextClass = determineContextClass(servletContext); if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) { throw new ApplicationContextException("Custom context class [" + contextClass.getName() + "] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]"); } ConfigurableWebApplicationContext wac = (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass); wac.setParent(parent); wac.setServletContext(servletContext); wac.setConfigLocation(servletContext.getInitParameter(CONFIG_LOCATION_PARAM)); customizeContext(servletContext, wac); wac.refresh(); return wac; } protected Class determineContextClass(ServletContext servletContext)
评论