DispatcherServlet类继承结构分析
springmvc核心类是DispatcherServlet,所以分析springmvc可以从DispatcherServlet作为入口
打断点查看调用栈
如果不知道一个程序的调用流程,可以通过打断点清晰的查看调用流程
DispatcherServlet 有一个很明显的方法 initStrategies,在此处打断点可以获取到如下调用栈
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)
开始从下往上分析调用流程
- GenericServlet.init
传递ServletConfig配置信息,用于子类使用
2. HttpServletBean.init
- 解析ServletConfig放入PropertyValues
- 加载配置信息
- 初始化ServletBean
3. HttpServletBean.initServletBean
此处是空实现,具体实现逻辑由子类实现,而实现此方法的是FrameworkServlet
- FrameworkServlet.initServletBean
此处主要是打印日志信息,然后调用initWebApplicationContext方法来初始化配置
FrameworkServlet.initWebApplicationContext
- 获取root applicationContext, 一般是web.xml文件对应的初始化配置
- 如果当前servlet已经初始化了一个applicationContext, 那么设置parent applicationContext为第一步设置的context然后读取配置文件。
- 如果applicationContext为空,那么根据配置文件中设置的contextAttribute值从ServletContext中查找
- 如果没有设置contextAttribute,那么就调用createWebApplicationContext()方法创建一个新的applicationContext,并将root applicationContext作为父容器。
6. FrameworkServlet.createWebApplicationContext
- 获取contextClass,这个类可以在web.xml中配置,如果为空就使用默认的XmlWebApplicationContext.class,然后创建XmlWebApplicationContext实例,并从xml配置文件中加载配置信息
- 设置环境变量
- 设置父容器
- 设置配置文件地址
- 加载配置,刷新上下文
7. FrameworkServlet.configureAndRefreshWebApplicationContext
- 设置当前webApplicationContext所属于的ServletContext
- 设置ServletConfig
- 设置命名空间
- 设置监听器
- 最终加载配置
8. AbstractApplicationContext.refresh
这个方法熟悉SpringIoc流程的应该很熟悉,这里就不详细说了
之后最终调用的是finishRefresh方法,主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
然后FrameworkServlet有个监听此事件的方法,继续往下分析
- FrameworkServlet.onApplicationEvent
- DispatcherServlet.onRefresh
从上图中就明白了,springmvc九大组件都在这个地方初始化,下面选择一个流程分析
- initHandlerMappings(context);
- 默认策略
- 默认组件配置文件 DispatcherServlet.properties
- 文件上传解析器的初始化必须按照id=multipartResolver注册对象,从下图就可以清晰的明白其中原因。
以上就是九大组件初始化的流程,所有组件初始化完成后就开始等待接收web请求并处理,后面的文章会详细分析处理请求的过程。