Spring MVC项目中@Transactional不生效

要解释清我遇到的情况首先要了解以下几个知识点:

(Ps:造成@Transactional不生效的原因有很多种,可以参考:https://blog.csdn.net/qq_20597727/article/details/84900994)
1、Spring MVC项目中会有两个容器初始化,配置了Spring注解(例:@Transactional、@Controller、@Service等注解)的类(class)

  • DispatcherServlet一般用来加载MVC相关的类(本文这个过程简称:加载springmvc配置)
// springmvc配置文件在web.xml中如何配置的
 <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
 </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
// springmvc.xml的配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="cn.isdev.ssm.**" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <mvc:annotation-driven/>
</beans>
  • ContextLoaderListener一般用来加载整个Spring相关的类(本文这个过程简称:加载spring配置)
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:spring.xml</param-value>
</context-param>
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
// spring.xml的简单配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="cn.isdev.ssm.**">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
    </context:component-scan>
    <mvc:annotation-driven/>
	<!--
        4. 事务管理 : DataSourceTransactionManager dataSource:引用上面定义的数据源
    -->
    <bean id="txManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 5. 使用声明式事务
         transaction-manager:引用上面定义的事务管理器
     -->
    <tx:annotation-driven transaction-manager="txManager" />
</beans>
  • 为什么要分两个容器进行初始化可以参考文章:https://blog.csdn.net/py_xin/article/details/52052627

2、要使spring注解配置生效需要在springmvc.xml配置中或者spring.xml加入<context:component-scan>标签,如何配置<context:component-scan>是本文的关键

3、spring的配置文件与springmvc的配置文件分开加载,在spring容器初始化的时候,会先加载spring配置(即:web.xml中中的配置),之后再加载springmvc的配置(即:web.xml中中的中的配置)。加载springmvc的配置的时候,如果扫面到spring配置扫描加载过的bean也会重新加载,并覆盖spring配置扫描加载的bean,但springmvc加载的bean都是没有aop配置的(@Transactional本事也是一种aop),这样就会导致配置了@Transactional注解的bean事务失效。那么要解决@Transaction注解的方法就有了,只要保证配置了@Transactional的bean不被springmvc配置中的<context:component-scan>扫描到即可

解决方案

springmvc.xml

/**
* 1、配置白名单,只扫描controller层bean,其他交给spring.xml初始化
* 2、component-scan:黑白名单默认过滤
* 只配置黑名单(exclude-filter):黑名单内的bean不被初始化,其他的均被初始化
* 只配置白名单(include-filter):默认:::白名单内的bean初始化,既不在白名单也不在黑明单的bean也会被初始化
* 3、要想把component-scan默认过滤关闭,只初始化白名单中的bean,需配置use-default-filters="false"
*/
<context:component-scan base-package="cn.isdev.ssm.**" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

spring.xml

// 扫描时除controller意外的所有bean(这样就包括配置了@Transaction的service了)
<context:component-scan base-package="cn.isdev.ssm.**">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值