MVC原理介绍

Spring MVC原理图

上图是Spring MVC工作原理图(图片来自网上搜索),根据上图,我们可以得知Spring MVC的工作流程如下:

1、用户(客户端,即浏览器)发送请求至前端控制器(DispatcherServlet) 。

2、前端控制器收到请求后调⽤处理器映射器(HandlerMapping)。

3、处理器映射器根据请求Url找到具体的处理器(Handler,也叫后端控制器),生成处理器对象及处理器拦截器(如果有)一并返回给前端控制器。

4、前端控制器收到处理器对象及处理器拦截器(如果有)后调用处理器适配器(HandlerAdapter)去调用Handler。

5、处理器适配器执行处理器。

6、处理器执行完后给处理器适配器返回ModelAndView。

7、处理器适配器将ModelAndView(ModelAndView是SpringMVC框架的⼀个底层对象,包括 Model 和 View)返回给前端控制器。

8、前端控制器接收到ModelAndView后,请求视图解析器(ViewResolver)去进⾏视图解析,根据逻辑视图名来解析真正的视图。

9、视图解析器将解析完的View返回给前端控制器。

10、前端控制器进⾏视图渲染,就是将模型数据(在 ModelAndView 对象中)填充到 request 域。

11、前端控制器向⽤户响应结果。

与IOC容器整合原理

下图是Spring MVC的IOC容器与Spring的IOC容器整合的示意图,采用SSM框架的整合方式:

当用户发送请求到服务器时,Spring MVC的前端控制器DispatcherServlet会启动一个IOC容器,而Spring的核心监听器ContextLoaderListener也会启动一个IOC容器。

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
id="WebApp_ID" version="2.5"> <servlet>
<servlet-name>springDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!-- 自定义Spring MVC配置文件的位置和名称 -->
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-mvc.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet> <servlet-mapping>
<servlet-name>springDispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping> <!-- 在Servlet的上下文参数中指定Spring配置文件的配置 -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring-tx.xml</param-value>
</context-param> <listener>
<!-- 配置ContextLoaderListener监听器,初始化WebApplicationContext这个类型的IOC容器 -->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> </web-app>

多IOC容器整合导致的对象重复创建问题

当两个IOC容器分别扫描不同的包时不会有重复创建对象问题

比方说,

Spring MVC的IOC容器扫描:com.ioc.component.handler,

Spring的IOC容器扫描:com.ioc.component.service,com.ioc.component.dao。

此时不会出现重复创建对象的问题。

当两个IOC容器扫描同一个包时会有重复创建对象问题

比方说,在特定情况下 两个IOC容器都扫描同一个包:com.ioc.component,此时如果不做特殊处理,会存在对象重复创建问题。

在实际开发中,一般需要将两者分开,避免出现扫描同一个包的问题。

1、同时配置两个IOC容器

为了实现更好的解耦,我们在实际开发中往往还是需要将数据源、Service、Dao等组件配置到传统的Spring配置文件中,并通过ContextLoaderListener启动这个IOC容器,而负责处理请求的handler组件则是由SpringMVC自己来启动,这就会产生一个问题:同样的组件可能会被创建两次

2、两个IOC容器各自的配置

为避免对象被重复创建,两个IOC容器需要分别进行如下配置。

对于Spring的IOC容器,将标记了@Controller注解的bean排除,不进行该类对象的创建工作。

Spring配置文件:spring-tx.xml

<context:component-scan base-package="com.ioc.component.*">
<!-- 过滤规则:exclude-filter 排除指定的类 -->
<!-- 将@Controller注解标记的类从自动扫描的包中排除 -->
<!-- 效果:当前IOC容器不会创建@Controller注解标记的类的bean -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

对于Spring MVC的IOC容器,仅创建标记了@Controller注解的bean。

SpringMVC配置文件:spring-mvc.xml

<!-- 关键:仅 -->
<!-- 配置use-default-filters="false"将默认的扫描包规则取消,参考include-filter仅创建@Controller注解标记的类的bean -->
<context:component-scan base-package="com.ioc.component.*" use-default-filters="false">
<!-- 过滤规则:include-filter 创建指定的类 -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

这两个IOC容器中,先启动的那个将成为后启动的IOC容器的父容器。

小结

Spring MVC的前端控制器DispatcherServlet读取spring-mvc.xml配置文件,Spring的核心监听器ContextLoaderListener读取spring-tx.xml配置文件。

要想避免两个IOC容器重复创建对象的问题,就需要分别在两个配置文件中进行配置,指定两个容器分别需要创建哪些对象。

IOC容器部分 参考文章链接:https://blog.csdn.net/java_wxid/article/details/84798991

Spring MVC工作原理及源码解析(一) MVC原理介绍、与IOC容器整合原理的更多相关文章

  1. 【Spring源码解析】—— 结合SpringMVC过程理解IOC容器初始化

    关于IOC容器的初始化,结合之前SpringMVC的demo,对其过程进行一个相对详细的梳理,主要分为几个部分: 一.IOC的初始化过程,结合代码和debug过程重点说明 1. 为什么要debug? ...

  2. Spring MVC工作原理及源码解析(三) HandlerMapping和HandlerAdapter实现原理及源码解析

    1.HandlerMapping实现原理及源码解析 在前面讲解Spring MVC工作流程的时候我们说过,前端控制器收到请求后会调⽤处理器映射器(HandlerMapping),处理器映射器根据请求U ...

  3. Spring-Session实现Session共享实现原理以及源码解析

    知其然,还要知其所以然 ! 本篇介绍Spring-Session的整个实现的原理.以及对核心的源码进行简单的介绍! 实现原理介绍 实现原理这里简单说明描述: 就是当Web服务器接收到http请求后,当 ...

  4. 【Java实战】源码解析Java SPI(Service Provider Interface )机制原理

    一.背景知识 在阅读开源框架源码时,发现许多框架都支持SPI(Service Provider Interface ),前面有篇文章JDBC对Driver的加载时应用了SPI,参考[Hibernate ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理、源码解析及测试

    机器学习实战(Machine Learning in Action)学习笔记————03.决策树原理.源码解析及测试 关键字:决策树.python.源码解析.测试作者:米仓山下时间:2018-10-2 ...

  6. Spring AOP的实现及源码解析

    在介绍AOP之前,想必很多人都听说AOP是基于动态代理和反射来实现的,那么在看AOP之前,你需要弄懂什么是动态代理和反射及它们又是如何实现的. 想了解JDK的动态代理及反射的实现和源码分析,请参见下面 ...

  7. Redux异步解决方案之Redux-Thunk原理及源码解析

    前段时间,我们写了一篇Redux源码分析的文章,也分析了跟React连接的库React-Redux的源码实现.但是在Redux的生态中还有一个很重要的部分没有涉及到,那就是Redux的异步解决方案.本 ...

  8. LinkedList原理及源码解析

    简介 LinkedList是一个双向线性链表,但是并不会按线性的顺序存储数据,而是在每一个节点里存到下一个节点的指针(Pointer).由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度, ...

  9. ORB原理与源码解析

    转载: http://blog.csdn.net/luoshixian099/article/details/48523267 CSDN-勿在浮沙筑高台 没有时间重新复制代码,只能一股脑的复制,所以代 ...

随机推荐

  1. python tempfile 创建临时目录

    一.tempfile介绍 该模块创建临时文件和目录.它适用于所有支持的平台.TemporaryFile,NamedTemporaryFile,TemporaryDirectory,和SpooledTe ...

  2. 翻译:《实用的Python编程》06_02_Customizing_iteration

    目录 | 上一节 (6.1 迭代协议) | 下一节 (6.3 生产者/消费者) 6.2 自定义迭代 本节探究如何使用生成器函数自定义迭代. 问题 假设你想要自定义迭代模式. 例如:倒数: >&g ...

  3. Android Studio 之 制作 Nine-Patch 图片(.9图片)

    •引言 9.png 可以保证图片在合适的位置进行局部拉伸,避免了图片全局缩放造成的图片变形问题. 但是由于Android Studio对于.9图片的检查更加严格,所以不符合AS要求的.9图片会带来很多 ...

  4. Python函数参数和注解是什么

    四种参数 Python函数func定义如下: def func(first, *args, second="Hello World", **kwargs): print(first ...

  5. java面试一日一题:mysql事务是如何实现的

    问题:请讲下mysql的事务是如何实现的 分析:该问题主要考察对事务的理解及实现方式: 回答要点: 主要从以下几点去考虑, 1.对事务的概念的理解? 2.事务的实现方式? 讲到mysql的事务,很快可 ...

  6. ansible:playbook详解

    Blog:博客园 个人 概述 playbook是由一个或者多个play组成的列表. 主要功能是将预定义的一组主机装扮成事先通过ansible中的task定义好的角色.task实际是调用ansible的 ...

  7. Java实现操作系统中四种动态内存分配算法:BF+NF+WF+FF

    1 概述 本文是利用Java实现操作系统中的四种动态内存分配方式 ,分别是: BF NF WF FF 分两部分,第一部分是介绍四种分配方式的概念以及例子,第二部分是代码实现以及讲解. 2 四种分配方式 ...

  8. 【学习底层原理系列】重读spring源码3-加载beanDefinition的方法obtainFreshBeanFactory

    obtainFreshBeanFactory()方法概述 定义BeanFactory,并加载以下两种bean的定义,装配到BeanFactory: 1.配置文件中定义的bean 2.通过<con ...

  9. 详谈lastIndex对正则结果的影响

    前言 今天遇到一个问题,用正则表达式去检查同一个字符串时,交替返回true和false.无奈之下,重新翻了翻权威指南,发现罪魁祸首原来是lastIndex.可在控制台尝试下 ? 1 2 3 4 5 6 ...

  10. 【vim】复制粘贴相关操作

    复制: 首先,可以在命令模式下输入v进入自由选取模式,选择需要剪切的文字后,按下d就可以进行剪切了. 其他命令模式下剪切命令: yy:复制当前行 nyy:n表示大于1的数字,复制n行 yw:从光标处复 ...