父子容器应用环境及初始化过程与实例配置

目录

1、Spring 父子容器是什么?

2、Spring MVC 环境下父子容器应用场景

3、Spring MVC 环境下父子容器的初始化过程

4、改造applicationContext.xml文件为父容器

5、改造springMVC-servlet.xml为子容器

6、整合之后要注意的问题


1、Spring 父子容器是什么?

        父子容器并非 Spring MVC 的专利,在普通的 Spring 环境下 Spring 就已经设计出具有层次结构的容器了,这种设计方式也并非 Spring 独创,其工作方式和 ClassLoader 很相似,每个容器有一个自己的父容器,但是与 ClassLoader 不同的是,通过容器查找 bean 时是优先从子容器查找,如果找不到才会从父容器中查找。当应用中存在多个容器时,这种设计方式可以将公共的 bean 放到父容器中,如果父容器中的 bean 不适用,子容器还可以覆盖父容器中的 bean。

Spring 中的容器有两种,一种是常用的 ApplicationContext,另一种容器是最底层的 BeanFactory,ApplicationContext 就依托于底层的 BeanFactory 查找 Bean。

2、Spring MVC 环境下父子容器应用场景

Spring MVC 负责控制整个请求流程的核心类是 DispatcherServlet,这个 DispatcherServlet 会关联一个 ApplicationContext,通常情况下,一个应用中有一个 DispatcherServlet 就足够了。

但是呢,凡事都有例外,如果你正在做一个商城,不同的模块如商品、购物车、订单模块使用了不同的 DispatcherServlet 来处理请求,这就意味着一个应用中出现了多个 ApplicationContext,由于每个 ApplicationContext 是独立的,因此订单模块就不能直接使用商品或购物车模块的服务来下单,订单模块把商品或购物车模块的服务注册到自身所在的容器中虽然能解决问题,但是这也意味着多个容器中保存了多个相同类型的 bean,那怎么解决呢?将这些公共的服务注册到相同的父容器中,这样每个子容器都能使用到父容器中的公共 bean。

 ApplicationContext 在 Spring MVC 环境下的实现是其子接口 WebApplicationConetxt,这个公共的 WebApplicationContext 也被称为 Root WebApplicationContext。通过父子容器对 bean 进行拆分之后,可以将与 Web 环境有关的 bean ,如 Controller、ViewResolver、HandlerMapping 等保存到 DispatcherServlet 中的 WebApplicationContext,而跨越多个 DispatcherServlet 共享的 Service、Repository bean 可以存放到 Root WebApplicationContext。

使用父容器之后的商城应用,自然而然,负责订单的 DispatcherServlet 子容器中的 Controller 可以使用父容器中的购物车 Service,达到了复用 bean 的目的。

3、Spring MVC 环境下父子容器的初始化过程

Spring 子容器依赖父容器,因此需要先对父容器初始化,然后才能对子容器初始化。Spring MVC是怎么保证父子容器初始化顺序的呢?

Spring MVC 依托于 Servlet 规范。Servlet 规范中 ,所有的 Servlet 具有一个相同的上下文 ServletContext,ServletContext 将优先于 Servlet 初始化,Spring 利用了这个特性,在 ServletContext 初始化时创建父容器,并将其绑定到 ServletContext 的属性中,然后在每个 DispatcherServlet 初始过程中创建子容器并将 ServletContext 中的容器设置为父容器。

4、改造applicationContext.xml文件为父容器

<context:component-scan base-package="com.woniuxy.ssm">
    <!---排除@Controller注解的扫描-->
   <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

5、改造springMVC-servlet.xml为子容器

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        https://www.springframework.org/schema/mvc/spring-mvc.xsd">
    <!--添加对子容器的扫描-->
    <context:component-scan base-package="com.xxx.ssm.controller"/>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
        <property name="prefix" value="/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
    <mvc:default-servlet-handler/>
    <!--再mvc中开启注解驱动,会在容器中注册处理器映射器以及处理器适配器,替代原来两个bean的配置-->
    <mvc:annotation-driven/>
</beans>

6、整合之后要注意的问题

父容器的作用是什么?

注册了除了controller相关组件之外的其他组件(service Dao等)

子容器的作用的是什么?

注册了控制器相关的组件

是否可以将控制器注册到父容器中?

项目启动正常,但是访问控制器的时候会404,找不到对应的资源,父容器中没有处理控制器相关的其他组件

是否可以将service注册到子容器中?

项目启动正常,但是业务层的事务没有正常工作,因为子容器没有返回业务层的代理对象。

最终结论:父容器子容器各司其职

整合总体流程:

启动tomcat------>加载web.xml------>监听器根据配置文件(applicationContext.xml)创建父容器,给父容器中注册了相关组件(dataSource sqlSessionFacotry mapper service)------>DispacherServlet根据MVC的配置文件创建子容器(注册的是控制器相关的组件)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值