Tomcat加载资源流程

10 篇文章 1 订阅
9 篇文章 1 订阅
本文详细解析了Spring与SpringMVC框架整合时的资源配置过程,包括DispatcherServlet与ContextLoaderListener的初始化时机与加载流程,揭示了Tomcat启动过程中资源加载的内部机制。
摘要由CSDN通过智能技术生成

资源配置

  • 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的继承结构如下,具体代码就不用分析了。
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值