SpringMVC和Spring配置重复扫描包导致事务失效问题


前言

在一次学习ssm框架整合的时候,spring和spring-mvc配置文件分开,配置component-scan时重复扫描包路径,导致事务失效的问题分析和解决方案。

一、问题描述

示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
上图可以看到,applicationContext.xml是Spring的配置文件,这里面配置了component-scan:

<context:component-scan base-package="com.ssm.test" />

这里就会吧com.ssm.test包下所有的被spring注解的类扫描进Spring的IOC容器中,包括@Controller,这里是没有什么问题的,但是在spring-mvc.xml中也是配置的一样的扫描路径:

<context:component-scan base-package="com.ssm.test" />

这时候事务就会失效,这是为什么呢,因为这里spring和spring-mvc是一个父子容器,就有两个ioc容器,不过spring是父容器,mvc是子容器。

二、问题分析

这里通过分析源码和断点方式进行分析:

  1. 首先在web.xml中配置了ContextLoaderLister监听器,在Servlet启动时触发这个监听器,来初始化spring父容器:
    在这里插入图片描述
  2. 可以看到初始化时已经把service、cntroller等Bean扫描进父容器了,并且service是一个代理对象,我们知道spring事务就是通过代理对象来实现的,所以父容器里面controller下注入的service是代理对象就有事务功能:
    在这里插入图片描述
  3. 然后我们再来看下mvc子容器初始化,这里首先获取父容器对象,然后创建mvc子容器里面会设置wac.setParent(parent)。
    在这里插入图片描述
  4. 再来看下mvc子容器里面的ioc单例池里面扫描的Bean对象信息,可以看到service对象不是一个代理对象,同时注入到controller里面的service也不是代理对象,所以这里肯定就没有事务的功能了:
    在这里插入图片描述

三、解决方案

经过上面的分析,很明显的发现了spring父容器和mvc子容器里面的Bean重复扫描了,而且父容器里面的service对象是代理对象,是我们需要的。

而spring的父子容器只能子容器访问父容器,而父容器不能访问子容器,所以这里我们可以把扫描对象在父子容器之间进行分配,那就是父容器扫描除了controller包的其他位置的Bean,而mvc子容器只需要扫描controller包下的对象就行了。

当某个controller需要注入service时,子容器可以访问父容器的特性,所以这里就可以把父容器中这个service代理对象注入到controller中,这样就完美解决了重复扫描和事务不生效的问题了。

  1. 首先修改spring配置文件applicationContext.xml下扫描包配置,排除掉controller包:
<context:component-scan base-package="com.ssm.test" >
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  1. 再修改spring-mvc.xml配置文件下扫描包配置,只扫描controller包:
<context:component-scan base-package="com.ssm.test.controller" />
  1. 这时再来看一下父容器下ioc单例池信息,这里就没有controller的Bean了:
    在这里插入图片描述
  2. 再来看下mvc子容器的ioc单例池信息,可以看到没有service等其他Bean了,只有和mvc相关的一些Bean信息,而且controller下注入的service正是父容器里面的那个service代理对象:
    在这里插入图片描述
  • 4
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值