资源配置
- spring和springmvc整合的时候资源加载入口配置在web.xml中,代码如下
<web-app>
<display-name>Archetype Created Web Application</display-name>
<!--springioc容器管理bean及aop声明式事务配置文件-->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:applicationContext*.xml</param-value>
</context-param>
<!--spring框架启动-->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--springmvc启动-->
<servlet>
<servlet-name>springmvc</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath*:springmvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springmvc</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
- 由上图可知有两种资源,一个是DispatcherServlet,初始化DispatcherServlet的同时会读取springmvc.xml中的资源,另一个通过ContextLoaderListener加载applicationContext*.xml中的资源
- 上面两种资源都是通过Tomcat加载的,在上一篇文章父子容器中已经说明了他们的加载顺序,不了解请点击父子容器,下面开始分析他们是在什么时候以及哪个地方加载的
ContextLoaderListener
- 这个类的代码很简单,具体如下
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中的initWebApplicationContext方法,在此处打断点,分析代码调用栈,具体如下
contextInitialized:103, ContextLoaderListener (org.springframework.web.context)
listenerStart:4939, StandardContext (org.apache.catalina.core)
startInternal:5434, StandardContext (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
call:1559, ContainerBase$StartChild (org.apache.catalina.core)
call:1549, ContainerBase$StartChild (org.apache.catalina.core)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
- Async stack trace
<init>:132, FutureTask (java.util.concurrent)
newTaskFor:108, AbstractExecutorService (java.util.concurrent)
submit:139, AbstractExecutorService (java.util.concurrent)
startInternal:1117, ContainerBase (org.apache.catalina.core)
startInternal:800, StandardHost (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
call:1559, ContainerBase$StartChild (org.apache.catalina.core)
call:1549, ContainerBase$StartChild (org.apache.catalina.core)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
- 由上述代码可知是tomcat启动的时候加载的,前面省略部分,最终通过StandardContext.startInternal方法中调用ContextLoaderListener.contextInitialized
- 下面开始分析代码
StandardContext.startInternal部分代码片段
DispatcherServlet
- 核心初始化代码如下
/**
* This implementation calls {@link #initStrategies}.
*/
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
/**
* Initialize the strategy objects that this servlet uses.
* <p>May be overridden in subclasses in order to initialize further strategy objects.
*/
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
- 由上面的代码可知初始化方法为onRefresh,在此处打断点,代码调用找如下
onRefresh:495, DispatcherServlet (org.springframework.web.servlet)
onApplicationEvent:842, FrameworkServlet (org.springframework.web.servlet)
onApplicationEvent:1190, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:1186, FrameworkServlet$ContextRefreshListener (org.springframework.web.servlet)
onApplicationEvent:64, GenericApplicationListenerAdapter (org.springframework.context.event)
onApplicationEventInternal:109, SourceFilteringListener (org.springframework.context.event)
onApplicationEvent:73, SourceFilteringListener (org.springframework.context.event)
doInvokeListener:172, SimpleApplicationEventMulticaster (org.springframework.context.event)
invokeListener:165, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:402, AbstractApplicationContext (org.springframework.context.support)
publishEvent:359, AbstractApplicationContext (org.springframework.context.support)
finishRefresh:896, AbstractApplicationContext (org.springframework.context.support)
refresh:552, AbstractApplicationContext (org.springframework.context.support)
configureAndRefreshWebApplicationContext:702, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:668, FrameworkServlet (org.springframework.web.servlet)
createWebApplicationContext:716, FrameworkServlet (org.springframework.web.servlet)
initWebApplicationContext:591, FrameworkServlet (org.springframework.web.servlet)
initServletBean:530, FrameworkServlet (org.springframework.web.servlet)
init:170, HttpServletBean (org.springframework.web.servlet)
init:160, GenericServlet (javax.servlet)
initServlet:1280, StandardWrapper (org.apache.catalina.core)
loadServlet:1193, StandardWrapper (org.apache.catalina.core)
load:1088, StandardWrapper (org.apache.catalina.core)
loadOnStartup:5176, StandardContext (org.apache.catalina.core)
startInternal:5460, StandardContext (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
call:1559, ContainerBase$StartChild (org.apache.catalina.core)
call:1549, ContainerBase$StartChild (org.apache.catalina.core)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
- Async stack trace
<init>:132, FutureTask (java.util.concurrent)
newTaskFor:108, AbstractExecutorService (java.util.concurrent)
submit:139, AbstractExecutorService (java.util.concurrent)
startInternal:1117, ContainerBase (org.apache.catalina.core)
startInternal:800, StandardHost (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
call:1559, ContainerBase$StartChild (org.apache.catalina.core)
call:1549, ContainerBase$StartChild (org.apache.catalina.core)
run$$$capture:264, FutureTask (java.util.concurrent)
run:-1, FutureTask (java.util.concurrent)
- Async stack trace
<init>:132, FutureTask (java.util.concurrent)
newTaskFor:108, AbstractExecutorService (java.util.concurrent)
submit:139, AbstractExecutorService (java.util.concurrent)
startInternal:1117, ContainerBase (org.apache.catalina.core)
startInternal:302, StandardEngine (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
startInternal:443, StandardService (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
startInternal:732, StandardServer (org.apache.catalina.core)
start:150, LifecycleBase (org.apache.catalina.util)
start:341, Tomcat (org.apache.catalina.startup)
- 由上面的流程可知依然是tomcat启动的时候加载的,入口是org.apache.catalina.startup,最终是在StandardWrapper.initServlet时加载的,DispatcherServlet的继承结构如下,具体代码就不用分析了。