一、父子容器

通过HierarchicalBeanFactory接口,Spring的IoC容器可以建立父子层级关联的容器体系,子容器可以访问父容器中的Bean,但父容器不能访问子容器的Bean。在容器内,Bean的id必须是唯一的,但子容器可以拥有一个和父容器id相同的Bean。父子容器层级体系增强了Spring容器架构的扩展性和灵活性,因为第三方可以通过编程的方式,为一个已经存在的容器添加一个或多个特殊用途的子容器,以提供一些额外的功能。

Spring使用父子容器实现了很多功能,比如在Spring MVC中,展现层Bean位于一个子容器中,而业务层和持久层的Bean位于父容器中。这样,展现层Bean就可以引用业务层和持久层的Bean,而业务层和持久层的Bean则看不到展现层的Bean。

二、spring的启动过程

spring的启动过程其实就是其IoC容器的启动过程,对于web程序,IoC容器启动过程即是建立上下文的过程。

首先,对于一个web应用,其部署在web容器中,web容器提供其一个全局的上下文环境,这个上下文就是ServletContext,其为后面的spring IoC容器提供宿主环境;
其次,在web.xml中会提供有contextLoaderListener。在web容器启动时,会触发容器初始化事件,此时contextLoaderListener会监听到这个事件,其contextInitialized方法会被调用,在这个方法中,spring会初始化一个启动上下文,这个上下文被称为根上下文,即WebApplicationContext,这是一个接口类,确切的说,其实际的实现类是XmlWebApplicationContext。这个就是spring的IoC容器,其对应的Bean定义的配置由web.xml中的context-param标签指定。在这个IoC容器初始化完毕后,spring以WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE为属性Key,将其存储到ServletContext中,便于获取;
再次,contextLoaderListener监听器初始化完毕后,开始初始化web.xml中配置的Servlet,这个servlet可以配置多个,以最常见的DispatcherServlet为例,这个servlet实际上是一个标准的前端控制器,用以转发、匹配、处理每个servlet请求。DispatcherServlet上下文在初始化的时候会建立自己的IoC上下文,用以持有spring mvc相关的bean。在建立DispatcherServlet自己的IoC上下文时,会利用WebApplicationContext.ROOTWEBAPPLICATIONCONTEXTATTRIBUTE先从ServletContext中获取之前的根上下文(即WebApplicationContext)作为自己上下文的parent上下文。有了这个parent上下文之后,再初始化自己持有的上下文。这个DispatcherServlet初始化自己上下文的工作在其initStrategies方法中可以看到,大概的工作就是初始化处理器映射、视图解析等。这个servlet自己持有的上下文默认实现类也是mlWebApplicationContext。初始化完毕后,spring以与servlet的名字相关(此处不是简单的以servlet名为Key,而是通过一些转换,具体可自行查看源码)的属性为属性Key,也将其存到ServletContext中,以便后续使用。这样每个servlet就持有自己的上下文,即拥有自己独立的bean空间,同时各个servlet共享相同的bean,即根上下文(第2步中初始化的上下文)定义的那些bean。

三、父子容器的配置

1、父容器

web.xml中增加监听

<listener>  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>  

监听器会创建一个WebApplicationContext上下文,称为父上下文(父容器) ,保存在 ServletContext中,key是WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE的值。

可以使用Spring提供的工具类取出上下文对象:WebApplicationContextUtils.getWebApplicationContext(ServletContext);

2、子容器

web.xml中定义dispatcherServlet入口

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

dispatcherServlet是装载Controller的上下文。DispatcherServlet是一个Servlet,可以同时配置多个,每个 DispatcherServlet有一个自己的上下文对象(WebApplicationContext),称为子上下文(子容器),子上下文可以访问父上下文中的内容,但父上下文不能访问子上下文中的内容。 它也保存在 ServletContext中,key是"org.springframework.web.servlet.FrameworkServlet.CONTEXT"+Servlet名称。当一个Request对象产生时,会把这个子上下文对象(WebApplicationContext)保存在Request对象中,key是DispatcherServlet.class.getName() + ".CONTEXT"。

可以使用工具类取出上下文对象:RequestContextUtils.getWebApplicationContext(request);

四、实践

1、传统型

因为spring的context是父子容器,所以会产生冲突,由ServletContextListener产生的是父容器,springMVC产生的是子容器,子容器Controller进行扫描装配时装配了@Service注解的实例,此时得到的将是原样的Service(没有经过事务加强处理,故而没有事务处理能力,因为@Service注解的实例理应由父容器进行初始化以保证事务的增强处理)。 所以传统型将父容器和子容器各司其职:

父上下文容器中保存数据源、服务层、DAO层、事务的Bean。
子上下文容器中保存Mvc相关的Action的Bean.
事务控制在服务层。

在主容器中(applicationContext.xml),将Controller的注解排除掉

<context:component-scan base-package="com"><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

上述的配置指定了Spring框架所扫描的注解不包括@Controller(也可以直接通过包名来指定),当然其他的配置文件(如:事务配置、AOP配置、定时任务等)可以通过<import />引入进来。

而在springMVC配置文件中将Service注解给去掉

<context:component-scan base-package="com"><context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /><context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>

上面配置是指定了DispatcherServlet所创建的上下文只扫描控制层的beans,当然在dispatcher-servlet.xml中还可以指定视图解析、JSON转换、上传下载等配置信息。

2、激进型

没有接口、没有Service层、还可以没有众多的O(vo\po\bo)。那没有Service层事务控制在哪一层?只好上升的Action层。
由于父上下文容器不能访问子上下文容器中内容,事务的Bean在父上下文容器中,无法访问子上下文容器中内容,就无法对子上下文容器中Action进行AOP(事务)。解决方案是只使用子上下文容器,不要父上下文容器 。所以数据源、服务层、DAO层、事务的Bean、Action的Bean都放在子上下文容器中。就可以实现了,事务(注解事务)就正常工作了。这样才够激进。
总结:不使用listener监听器来加载spring的配置文件,只使用DispatcherServlet来加载spring的配置,不要父子上下文,只使用一个DispatcherServlet。

Spiring父子容器相关推荐

  1. 聊聊 SpringCloud 中的父子容器

    点击上方"方志朋",选择"置顶或者星标" 你的关注意义重大! 来源公号:吉姆餐厅ak 概述 在引入 SpringCloud 的项目中会多次创建 Spring 容 ...

  2. 面试高频题:Spring和SpringMvc父子容器你能说清楚吗

    引言 以前写了几篇关于SpringBoot的文章<面试高频题:springBoot自动装配的原理你能说出来吗>.<保姆级教程,手把手教你实现一个SpringBoot的starter& ...

  3. boot spring 没有父子容器_Spring父子容器问题

    这个问题老早就存在了,只是今天组长让我看AOP不生效的时候,才真实遇到这个问题,之前都是用的Spring Boot开发,不会存在这个问题. 问题描述 如果使用传统的方式来开发Spring项目,要部署在 ...

  4. Spring父子容器的关系分析--用实例说话

    Spring中父子容器的实现实例Spring的父子容器可以通过ConfigurableApplicationContext或ConfigurableBeanFactory来实现,这两个接口中分别有se ...

  5. SpringMVC——自定义拦截器、异常处理以及父子容器配置

    SpringMVC--自定义拦截器.异常处理以及父子容器配置 参考文章: (1)SpringMVC--自定义拦截器.异常处理以及父子容器配置 (2)https://www.cnblogs.com/so ...

  6. Spring和SpringMVC的父子容器关系

    容器 在Spring整体框架的核心概念中,容器是核心思想 就是用来管理Bean的整个生命周期的 在一个项目中,容器不一定只有一个 Spring中可以包括多个容器,而且,容器有上下层关系 一个项目中引入 ...

  7. spring的父子容器

    在创建ssm项目工程时,经常需要读取properties资源配置文件,传统的方法当然可以. 但是spring提供了更简便的方法,@value注解. 在page.properties文件中,配置分页信息 ...

  8. Spring MVC上下文父子容器

    2019独角兽企业重金招聘Python工程师标准>>> Spring MVC上下文父子容器 博客分类: java spring 在Spring MVC的启动依赖Spring框架,有时 ...

  9. Spring-SpringMVC父子容器

    转载自  Spring-SpringMVC父子容器 前言 Spring&SpringMVC作为bean管理容器和MVC默认框架,是大多数web应用都会选择的方案.在其使用过程中,尽管基于xml ...

最新文章

  1. Docker容器的导出和导入
  2. BZOJ 1800: [Ahoi2009]fly 飞行棋( 枚举 )
  3. Office基础和计算机操作基础的知识点(一)
  4. 第三周总结 类、对象、包
  5. HDOJ2035 人见人爱A^B
  6. 从网络读取数据并动态的显示在ListView中
  7. python函数介绍
  8. linux sleeping进程多_你知道Linux进程的睡眠和唤醒操作?
  9. php kindeditor远程图片上传,kindeditor 远程图片本地化,远程图片下载到本地自动更换图片路径...
  10. 电脑照片太大怎么压缩?照片怎么缩小kb?
  11. C语言猜数字游戏(超级详解)
  12. c语言生成excel文件简书,iOS 生成Excel xlsx文件
  13. 【BZOJ-4316】小C的独立集 仙人掌DP + 最大独立集
  14. 视频剪辑必备,5个视频素材网站,马住
  15. 年底打新将空前白热化:闭眼赚钱谁会放过?
  16. 基础算法一一股神问题
  17. 泰坦尼克号生存分析(新手入门)
  18. 微信录音amr音频文件转mp3格式
  19. 专访星陀资本合伙人秦毅:秉持理性投资之道,着眼于技术应用层
  20. 精度更高,视野更大的Photoneo3D相机

热门文章

  1. 细说Hash(哈希)
  2. 计算机无法连接苹果手机软件,iphone连接win10电脑后没反应怎么解决
  3. 正则表达式读取小说(txt文本)的章节
  4. js实现图片粘贴到网页
  5. C++ : 力扣_Top(189-217)
  6. 计算机网络之CSMA/CD协议
  7. 地址、指针、指针变量详解
  8. 数字版权保护技术及其应用---------作者:北京大学计算机研究所 汤帜
  9. 金庸笔下的程序员 | 附金庸武侠全集
  10. 用U盘安装Linux图解