ssm整合时spring事务管理失效的问题

问题描述:

       整合ssm(Spring+Spring MVC+Mybatis)框架时,模拟用户之间转账操作时使用了Spring的事务管理器,当程序发生异常时,事务并没有进行回滚,和没配事务管理器一样,但是通过Junit进行单元测试,跳过Controller层直接调用Service层进行转账操作时,事务管理器又可以正常起作用。所以大致可以确定问题出现在Spring和SpringMVC的整合上。


原因分析:

        由于是JavaWeb项目,所以Spring的配置文件是通过ContextLoaderListener来加载的,也就是当Web容器一创建时便会加载Spring配置文件从而初始化IOC容器,此时由于Spring配置文件中配置了事务管理器,所以当扫描到@Service注解时实例化到IOC当中的Service是经过了事务增强的,然后将这个Service注入到Controller中。但是当SpringMVC的配置文件加载时,会再一次扫描@Service和@Controller,此时注入到Controller中的是没有经过事务增强的Service,在多上下文的情况下,如果同一个bean被定义了两次,后面一个优先,也就是后面的会覆盖前面的。这也就解释了问题描述当中出现的场景,当我们通过Tomcat启动整个项目时,这两个配置文件都会被加载,Controller中最终拿到的Service是没有经过事务增强的,当模拟异常时自然不会有事务回滚;而当我们通过Junit进行单元测试时,由于并没有使用tomcat,而是手动加载spring配置文件,此时Spring MVC的配置文件并没有起作用,所以我们在测试类中拿到的Service是经过了事务增强的,也就有了事务管理的功能,转账碰到异常自然会回滚。


解决方案:

        经过大致的原因分析,解决问题的思路已经很明显了,只要能保证Spring的配置文件不扫描@Controller注解,Spring MVC的配置文件不扫描@Service注解,让两者各司其职,互不影响,就不会出现上面的问题了。可以对配置文件进行如下修改,达到注解过滤的效果。

        ApplicationContext.xml:

<!--开启注解扫描-->
<context:component-scan base-package="com.dzp">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
</context:component-scan>

        对于SpringMVC.xml有如下三种配置方案:

第一种:让springMVC只扫描Controller层的包。这也是最简单最直接的办法,因为springMVC是web框架,主要负责表现层,一般不会涉及到其他层。

<!--开启注解扫描-->
<context:component-scan base-package="com.dzp.controller"/>

第二种: 通过将<context:component-scan>的use-default-filters属性设置为false,来关闭它的默认扫描行为,这时通过配置<context:include-filter>来扫描@Controller(以及可能会用到的@RestController)就可以了,意思就是其他的都不扫描,只扫描@Controller(和@RestController)

<!--开启注解扫描-->
<context:component-scan base-package="com.dzp" use-default-filters="false">
    <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.RestController"/>
</context:component-scan>

 第三种:通过配置<context:exclude-filter>来不扫描Service,其他的都正常扫描。

<!--开启注解扫描-->
<context:component-scan base-package="com.dzp">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>

        对于以上SpringMVC的三种配置方案,一般直接使用第一种,然后第三种虽然也能达到效果,但是是不推荐使用的,因为原因分析中涉及到的问题影响的不仅仅是事务管理,而是整个AOP(面向切面编程,Spring的两大核心之一),由于Spring内置的事务管理也是通过AOP思想实现的,所以才会间接被影响到。而在实际项目开发中,可能用到AOP的不仅仅只是Service层,所以如果使用的第三种配置方案的话,每次使用切面都需要考虑springMVC配置文件,无形之间增加了工作量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值