SpringMVC源码阅读(1)
试图用比较简的方法,一看就懂,直接来图:
说明:
粉色代表spring及springmvc组件初始化过程(起始点,是servlet的init方法)
蓝色代表springmvc处理请求的过程(起始点,是servlet的init方法)
public interface Servlet {
public void init(ServletConfig config) throws ServletException;
public ServletConfig getServletConfig();
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
public String getServletInfo();
public void destroy();
}
7是springMVC把spring初始的上下文,合并进来的地方,,,跳过一个标号10,嘿嘿
13是springMVC初始化9大组件地方
7是springMVC处理请求的核心流程代码
总结:
Spring在ioc的初始化步骤中,在bean的初始化前后,都有预留开发者再次定制的路径。
Spring mvc也同样预留了类似的途径。
ContextLoaderListener就是Spring根上下文(WebApplicationContext)生命周期监控的触发点。它规范了Spring根上下文根上下文容器生命周期的回调。WebApplicationContext的初始化执行者是ContextLoaderListener的父类ContextLoader
org.springframework.web.context.ContextLoaderListener.contextInitialized(ServletContextEvent)
public void contextInitialized(ServletContextEventevent){
initWebApplicationContext(event.getServletContext());
}
org.springframework.web.context.ContextLoader.initWebApplicationContext(ServletContext)
public WebApplicationContextinitWebApplicationContext(ServletContextservletContext) {
if (servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE) != null){//这里一定不存在,因为,这里一定是首先启动的初始化的地方。然后才是DispatcherServlet使用这里启动的ioc作为父容器。
throw new IllegalStateException(
"Cannot initialize context because there is alreadya root application context present - "+
"check whether you have multiple ContextLoader*definitions in your web.xml!");
}
Loglogger= LogFactory.getLog(ContextLoader.class);
servletContext.log("Initializing Spring rootWebApplicationContext");
if (logger.isInfoEnabled()) {
logger.info("Root WebApplicationContext: initializationstarted");
}
long startTime = System.currentTimeMillis();
try {
// Store context in local instance variable, to guaranteethat
// it is available on ServletContext shutdown.
if (this.context ==null) {
this.context =createWebApplicationContext(servletContext);
}
if (this.contextinstanceofConfigurableWebApplicationContext) {
ConfigurableWebApplicationContextcwac= (ConfigurableWebApplicationContext)this.context;
if (!cwac.isActive()) {
// The context has not yet been refreshed -> provideservices such as
// setting the parent context, setting the application contextid, etc
if (cwac.getParent() ==null) {
// The context instance was injected without an explicitparent ->
// determine parent for root web application context, ifany.
ApplicationContextparent= loadParentContext(servletContext);
cwac.setParent(parent);
}
configureAndRefreshWebApplicationContext(cwac,servletContext);
}
}
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,this.context);
ClassLoaderccl= Thread.currentThread().getContextClassLoader();
if (ccl == ContextLoader.class.getClassLoader()) {
currentContext=this.context;
}
else if (ccl != null) {
currentContextPerThread.put(ccl,this.context);
}
if (logger.isDebugEnabled()) {
logger.debug("Published root WebApplicationContext asServletContext attribute with name ["+
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE +"]");
}
if (logger.isInfoEnabled()) {
longelapsedTime = System.currentTimeMillis()-startTime;
logger.info("Root WebApplicationContext: initializationcompleted in " +elapsedTime +" ms");
}
return this.context;
}
catch (RuntimeExceptionex) {
logger.error("Context initialization failed",ex);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,ex);
throwex;
}
catch (Errorerr) {
logger.error("Context initialization failed",err);
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,err);
throwerr;
}
}