为什么80%的码农都做不了架构师?>>>   

<context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring*.xml</param-value>
</context-param>
<listener><listener>org.springframework.web.context.ContextLoaderListener</listener>
</listener><servlet><servlet-name>test</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath*:config/test-servlet.xml</param-value></init-param><load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping><servlet-name>test</servlet-name><url-pattern>/</url-pattern>
</servlet-mapping>

从这个配置里面看见,一个配置上下文的监听器,这个监听器负责整个 IOC 容器 在 Web 环境中的启动工作,另外一个是配置 SpringMVC 的分发请求器。他们共同构成了 Spring 和 Web 容器的接口操作,他们与 Web容器的 耦合 是通过ServletContext 初始化的,而DispatcherServlet就负责 Web 请求转发的建立,完成 http 的请求响应。

在这个启动过程中可以看见系统加载是依赖 web 容器的  ServletContextListener 来触发的,这个Listener的触发会在如下时候:

当 Servlet 容器启动或终止 Web应用时,会触发 ServletContextEvent 事件,该事件由ServletContextListener 来处理。在 ServletContextListener 接口定义了处理 ServletContextEvent 事件的两个方法。

  1. contextInitialized( ServletContextEvent sce): 当 Servlet容器启动Web应用的时,调用该方法;调用完成之后,容器在对 Filter 初始化,并且对那些在 Web应用启动时就需要被初始化的 Servlet 进行初始化。
  2. contextDestroyed( ServletContextEvent sce) : 当Servlet容器终止 Web应用时候调用该方法;在调用该方法之前,容器会销毁所有的 Servlet 和 Filter。

在 Spring 会在 Web容器启动的过程中,借助这个监听器来创建它的上下文,而这个上下文其实就是 IOC 容器的初始化过程。而这个上下文初始化的过程同时也会把这个 ServletContext 给设置上,以供后面的 WebApplicationContext 来获取 Web容器级别的全局属性。

先看下这个创建的 XmlWebApplicationContext 上下文的类继承关系:

它的 refresh 过程其实是在 AbstractApplicationContext 完成的,如下代码:

    @Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {logger.warn("Exception encountered during context initialization - cancelling refresh attempt", ex);// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}}}

这个就是之前 spring ioc 中已经讲到过的容器启动过程,在 XmlWebApplicationContext它重写了 beanDefinition 的加载,如下代码

/*** Loads the bean definitions via an XmlBeanDefinitionReader.* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader* @see #initBeanDefinitionReader* @see #loadBeanDefinitions*/@Overrideprotected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {// Create a new XmlBeanDefinitionReader for the given BeanFactory.XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.beanDefinitionReader.setEnvironment(getEnvironment());beanDefinitionReader.setResourceLoader(this);beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.initBeanDefinitionReader(beanDefinitionReader);loadBeanDefinitions(beanDefinitionReader);}

对于这个实现类它主要添加了对 web 环境 和 xml配置类的定义处理,例如:

/** Default config location for the root context */public static final String DEFAULT_CONFIG_LOCATION = "/WEB-INF/applicationContext.xml";/** Default prefix for building a config location for a namespace */public static final String DEFAULT_CONFIG_LOCATION_PREFIX = "/WEB-INF/";/** Default suffix for building a config location for a namespace */public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = ".xml";

这三个静态的定义就是专门为 web 环境来设置的,相对于配置资源的获取从以下这段重写的代码可以看出:

/*** The default location for the root context is "/WEB-INF/applicationContext.xml",* and "/WEB-INF/test-servlet.xml" for a context with the namespace "test-servlet"* (like for a DispatcherServlet instance with the servlet-name "test").*/@Overrideprotected String[] getDefaultConfigLocations() {if (getNamespace() != null) {return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() + DEFAULT_CONFIG_LOCATION_SUFFIX};}else {return new String[] {DEFAULT_CONFIG_LOCATION};}}

在 启动时序中 有一个 initWebApplicationContext 的过程,这个过程里面有如下一段代码可以简单的说明一下:

if(this.context == null){this.context = createWebApplicationContext(servletContext);
}

也就是 context 创建过程,这个 createWebApplcationContext 的如下实现:

protected WebApplicationContext createWebApplicationContext(ServletContext sc) {Class<?> contextClass = determineContextClass(sc);if (!ConfigurableWebApplicationContext.class.isAssignableFrom(contextClass)) {throw new ApplicationContextException("Custom context class [" + contextClass.getName() +"] is not of type [" + ConfigurableWebApplicationContext.class.getName() + "]");}return (ConfigurableWebApplicationContext) BeanUtils.instantiateClass(contextClass);}

在创建 WebApplicationContext 的时候这里面有一个选择上下文 class 的方法:

protected Class<?> determineContextClass(ServletContext servletContext) {String contextClassName = servletContext.getInitParameter(CONTEXT_CLASS_PARAM);if (contextClassName != null) {try {return ClassUtils.forName(contextClassName, ClassUtils.getDefaultClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load custom context class [" + contextClassName + "]", ex);}}else {contextClassName = defaultStrategies.getProperty(WebApplicationContext.class.getName());try {return ClassUtils.forName(contextClassName, ContextLoader.class.getClassLoader());}catch (ClassNotFoundException ex) {throw new ApplicationContextException("Failed to load default context class [" + contextClassName + "]", ex);}}}

首先会判断在 web 容器的上下文全局属性里面没有做设置,如果做了设置就使用这个类。如果没有设置就从一个默认的策略 properties 里面去获取这个配置,这个配置的默认文件内容如下:

# Default WebApplicationContext implementation class for ContextLoader.
# Used as fallback when no explicit context implementation has been specified as context-param.
# Not meant to be customized by application developers.
org.springframework.web.context.WebApplicationContext=org.springframework.web.context.support.XmlWebApplicationContext  

也就是说 spring 的 MVC 默认上下文就是 XmlApplicationContext ,验证了对这个类的分析。

转载于:https://my.oschina.net/exit/blog/812688

Spring MVC 实现原理相关推荐

  1. Spring MVC工作原理

    转载自  Spring MVC工作原理 Spring MVC框架介绍 Spring MVC属于SpringFrameWork的后续产品,已经融合在Spring Web Flow里面. Spring M ...

  2. spring Mvc 执行原理 及 xml注解配置说明 (六)

    Spring MVC 执行原理 在 Spring Mvc 访问过程里,每个请求都首先经过 许多的过滤器,经 DispatcherServlet 处理; 一个Spring MVC工程里,可以配置多个的 ...

  3. Spring Mvc工作原理图解

    Spring Mvc工作原理图解 先来一张图: 目前还是有些疑惑,因为是初学 思考了大半天,整理了初步的一些工作原理: 如图上所述: 1.用户(打开网站,输入网址url)发送请求. 2.用户的请求会通 ...

  4. Spring Boot Spring MVC异常处理原理分析

    一.Spring MVC为处理异常的前期准备 DispatcherServlet 入口类,是一个Servlet,是所有请求的分发点 初始化 DispatcherServlet在初始化时会触发onRef ...

  5. Spring MVC工作原理 及注解说明

    转载自  http://blog.csdn.net/shuyeshangdemayi/article/details/50259493 SpringMVC框架介绍 1) Spring MVC属于Spr ...

  6. 详细述说spring mvc工作原理

    spring mvc是什么? springMVC是一个MVC的开源框架,springMVC=struts2+spring,springMVC就相当于是Struts2加上sring的整合,但是这里有一个 ...

  7. Spring mvc ContextLoaderListener 原理解析

    对于熟悉Spring MVC功能,首先应从web.xml 开始,在web.xml 文件中我们需要配置一个监听器 ContextLoaderListener,如下. <!-- 加载spring上下 ...

  8. spring MVC运行原理

    按照上边的执行流程图,我们可以看出一个SpringMVC整体的一个执行轮廓,下面我们具体来分析下 首先服务器接收到一个请求,匹配并调用了我们的前端控制器(DispatcherServlet)也叫中央处 ...

  9. spring mvc工作原理及组件说明

    组件说明 以下组件通常使用框架提供实现: DispatcherServlet:前端控制器 用户请求到达前端控制器,它就相当于mvc模式中的c,dispatcherServlet是整个流程控制的中心,由 ...

最新文章

  1. 精选Spring Boot三十五道必知必会知识点!
  2. recycleview 使用详解,添加头部尾部,混合item,侧滑菜单,跳转到指定位置,实现九宫格布局
  3. js unescape 对应php的函数,php实现Javascript的escape和unescape函数
  4. react中类组件this指向
  5. 系统新模块增加需要哪些步骤_想要吸引人流,儿童乐园需要增加哪些新设备呢...
  6. 拖动内容,滚动条滚动,横向
  7. 雷林鹏分享:PHP 表单 - 验证邮件和URL
  8. 19.卷1(套接字联网API)---密钥管理套接字
  9. gimp中文版教程_Gimp中文经典入门实用教程(合辑).pdf
  10. FME中GIS面分图层转为CAD填充并符号化,且图斑含面积属性
  11. 反激变压器结构设计学习笔记(进阶)
  12. 信息系统项目管理师必背核心考点(四十八)合同类型的选择
  13. 新一代的核心路由器的发展趋势分析
  14. iOS动画:粒子发射器(20)
  15. 9月编程排行榜新鲜出炉霸榜还得是它~
  16. 中断处理过程示意图_中断和中断处理流程
  17. git pull 与 git push 的区别
  18. Java-名片管理系统
  19. python自带sqlite_Python使用sqlite3模块内置数据库
  20. apktool,dex2jar,jd-gui简单使用

热门文章

  1. 代码审计-四叶草杯线下awd比赛源码web2
  2. 洛谷 [P1801] 黑匣子
  3. (转)HIBERNATE与 MYBATIS的对比
  4. Lingo 优化实例 出版社问题
  5. MSSQL 访问Mysql
  6. Java初学者都应该搞懂的六个问题
  7. csv文件简介(转载)
  8. Spring Countries在Apusic上部署
  9. 讲解启动CentOS Samba 服务的方法
  10. 深度:Leap Motion手势识别大揭秘