能将事务管理配置到Controller层吗?

更多Spring事务问题请访问链接:Spring事务回滚疑难详解

我们通常会在Service层进行事务管理,难道不能在Contoller层实现?

(我觉得这个问题,对于每一个不仅仅是为了编程而编程的程序员在最初接触切面编程时都是一个比较大的疑问,尤其是强迫症患者或者懒得写Service层的快速开发者,但实际上真的不建议避开Service层,随着实践知识深入,你们会逐渐了解这一切面的重要性)

   有不少技术博客上都信誓旦旦的说,①controller层是无法实现事务管理的;②controller层只能实现基于注解@Transactional的事务管理。

    /* “实践是检验真理的唯一标准”—— 这句话对于技术者来说尤为重要,不要老听别人说,当大胆假设产生疑问的时候,我们除了查找文献资料,更重要的是亲自去尝试,总结经验 */

     实验结果表明:Controller层能够实现事务管理,并且兼容两种方式。

而且《Spring官方文档》

https://docs.spring.io/spring/docs/4.3.18.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#tx-annotation-driven-settings 也给出了明确解释:如果你把事务的注解驱动,配置在DispatcherServlet的上下文中,那么事务将会对Controller的Beans生效,而不是Service Beans。

@EnableTransactionManagement and <tx:annotation-driven/> only looks for @Transactional on beans in the same application context they are defined in. This means that, if you put annotation driven configuration in a WebApplicationContext for a DispatcherServlet, it only checks for @Transactional beans in your controllers, and not your services.

<aop:config expose-proxy="true">  
    <aop:pointcut id="transactionPointcut" expression="execution(* com.local.controller.*.*(..))" />  
    <aop:advisor pointcut-ref="transactionPointcut" advice-ref="transactionAdvice" />  
</aop:config>  

  相信不少热爱学习的初级程序员使用过这种修改方式,但是都失败了,尽管指定了expression="execution(* com.local.controller.*.*(..))" 拦截方法在Controller层,但是根本没有效果。

    其实我们应该做出如下修改:

<!--Controller层的事务管理需要将注解开启或者拦截配置,配置在ApplicationContext.XML或者Spring-Servlet.XML或者Spring-MVC.XMl-->  

    这样写只是我们命名方式不同产生的差异,本质上是:Controller层的事务管理需要将注解开启或者拦截配置,配置在 “开启Controller扫描”的XML中

<!--Controller层的事务管理需要将注解开启或者拦截配置,配置在 “开启Controller扫描”的XML中-->  
<context:component-scan base-package="com.local.controller" >  
    <!-- 只扫描@Controller的部分 -->  
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"  />  
</context:component-scan>  

或者  

<context:component-scan base-package="com.local.controller" />  

其实就是在含有上述代码的XML中添加以下任意一种:

 @Transactional注解式:

<!-- 注解方式配置事物 -->  
<tx:annotation-driven transaction-manager="transactionManager" />  

切点拦截配置方式:

<tx:advice id="transactionAdvice" transaction-manager="transactionManager">   
<!-- 切点拦截的位置下,所有形式类似的方法名,‘事务’都会交由相应事务管理工具管理-->  
    <tx:attributes >  
        <tx:method name="insert*" propagation="REQUIRED"  />  
        <tx:method name="get*" propagation="REQUIRED" read-only="true" />  
    </tx:attributes>  
</tx:advice>  
<aop:config expose-proxy="true">  
    <aop:pointcut id="transactionPointcut" expression="execution(* com.local.*.*.*(..))" />  
    <aop:advisor pointcut-ref="transactionPointcut"  advice-ref="transactionAdvice" />  
</aop:config>  

 

  • 3
    点赞
  • 5
    评论
  • 6
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

©️2021 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值