zoukankan      html  css  js  c++  java
  • Spring MVC工作原理及源码解析(一) MVC原理介绍、与IOC容器整合原理

    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

    作者:blayn
    出处:https://www.cnblogs.com/blayn/
    版权:本文版权归作者和博客园共有
    转载:欢迎转载,但未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
  • 相关阅读:
    接入SDK
    GSoap的使用(调用webservice接口)
    NSString/NSMutableString 字符串处理
    iOS Base SDK & Deployment Target 区别&设置
    No identities are available for signing 的解决办法
    GitHub 代码托管Mac下
    代理&Block 传值
    UItextField 的简单控制
    NSPredicate 的使用
    tableView 删除一行后下一行点击事件被忽略
  • 原文地址:https://www.cnblogs.com/blayn/p/14721250.html
Copyright © 2011-2022 走看看