springmvc源码解析-初始化

1.      概述web

对于Web开发者,MVC模型是你们再熟悉不过的了,SpringMVC中,知足条件的请求进入到负责请求分发的DispatcherServlet,DispatcherServlet根据请求url到控制器的映射(HandlerMapping中保存),HandlerMapping最终返回HandlerExecutionChain,其中包含了具体的处理对象handler(也即咱们编程时写的controller)以及一系列的拦截器interceptors,此时DispatcherServlet会根据返回的HandlerExecutionChain中的handler找到支持这一处理器类型的适配器(handlerAdapter),在处理器适配器中最终会去调用控制器的请求响应方法并返回结果视图(ModelAndView),获得结果视图后,经过render方法完成结果的显示。spring

HanderMapping的继承体系:编程

1

 

HandlerAdapter的继承体系:mvc

2

 

一样的视图解析器ViewResolver针对不一样的输出格式也有一系列的实现类,具体可本身看。app

 

2.    实现分析jsp

以我本身的一个web项目中spring mvc的配置为例:函数

  1. <context:component-scan base-package="cn.ds.log" />
  2.  
  3. <bean id="defaultHandlerMapping"
  4. class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" />
  5.  
  6. <bean
  7. class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
  8. </bean>
  9.  
  10. <bean
  11. class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
  12. </bean>
  13.  
  14. <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter">
  15. </bean>
  16.  
  17. <bean id="viewResolver"
  18. class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  19. <property name="prefix">
  20. <value>/WEB-INF/jsp/</value>
  21. </property>
  22. <property name="suffix">
  23. <value>.jsp</value>
  24. </property>
  25. </bean>

这里由于是采用全注解的方式,因此先经过context:component-scan配置让spring自定扫描的包路径,接着配置handlerMapping、handlerAdapter及ViewResolver,几乎包含了SpringMVC的配置中须要涉及的全部元素。后面须要涉及具体的HanderMapping等的实现时,将以这里配置中的实现为例进行分析,其它的你们“同理可解”。⊙﹏⊙b汗源码分析

 

2.1  Spring MVC初始化流程this

DispatcherServlet的继承体系如:url

3

看到它们继承自HttpServlet,你就知道初始化过程应该是从init方法开始了,整个初始化的流程为:

4

 

很简单是么?我也以为是,至少从上面的时序图看来是这样,不过前提是你已经很了解Spring IOC的实现原理了。上面的时序图中,在5的initStragegies()中除了调用6,7的函数外,还有几个相似的初始化函数,由于这里主要是为了理解整个的流程,因此我都省略了。上面流程可能须要分析的地方就在于3,4步,咱们看看initWebApplicationContext函数的实现:

  1. protected WebApplicationContext initWebApplicationContext() {
  2. WebApplicationContext rootContext =
  3. WebApplicationContextUtils.getWebApplicationContext(getServletContext());
  4. WebApplicationContext wac = null;
  5.  
  6. if (this.webApplicationContext != null) {
  7. // A context instance was injected at construction time -&gt; use it
  8. wac = this.webApplicationContext;
  9. if (wac instanceof ConfigurableWebApplicationContext) {
  10. ConfigurableWebApplicationContext cwac = (ConfigurableWebApplicationContext) wac;
  11. if (!cwac.isActive()) {
  12. ……
  13. configureAndRefreshWebApplicationContext(cwac);
  14. }
  15. }
  16. }
  17. if (wac == null) {
  18. wac = findWebApplicationContext();
  19. }
  20. if (wac == null) {
  21. // No context instance is defined for this servlet -&gt; create a local one
  22. wac = createWebApplicationContext(rootContext);
  23. }
  24.  
  25. if (!this.refreshEventReceived) {
  26. // Either the context is not a ConfigurableApplicationContext with refresh
  27. // support or the context injected at construction time had already been
  28. // refreshed -&gt; trigger initial onRefresh manually here.
  29. onRefresh(wac);
  30. }
  31.  
  32. if (this.publishContext) {
  33. ……
  34. }
  35.  
  36. return wac;
  37. }

 

看起来貌似有点复杂,其实理解了IOC容器的实现原理(能够看下“spring ioc源码分析”一文,⊙﹏⊙多年前弄的,此次暑假实习时又以读书报告的形式写了,感受当年肿么能够写得这么乱……也是一种成长,不打算修改)就很简单,函数一开始会去获取WebApplicationContext对象,这个对象在ContextLoaderListener初始化IOC容器时就已经把它set到ServletContext的属性中,并且它也正是ConfigurableWebApplicationContext的实例,第一个if语句其实就是若是此时SpringIOC容器没有初始化的话就在这里启动IOC容器的初始化过程,由于看“省略(1)”中的代码你就知道,它会在这里调用refresh函数,“世人”都知道这就是IOC容器启动的入口,这里会解析配置文件springmvc-servlet.xml。

这里最终要执行onRefresh(),而这个就是SpringMVC初始化的入口。

(注:其实这里也能够配置log4j,经过其打印的info信息来看IOC与MVC的初始化顺序)

相关文章
相关标签/搜索