Transaction 在同一个类中不生效
参考:https://blog.csdn.net/qq_30336433/article/details/83338835
最近在开发项目中踩到一个坑,以此记录下来。以备后来人借鉴
1、相信使用spring开发的小伙伴对@Transaction这个注解应该不会陌生。
spring提供了非常强大的事务管理机制,之前一直以为只要在方法上加上@Transaction就万事大吉了

但是最近发现有些情况下 这个注解会失效。
当这个方法被同一个类调用的时候,spring无法将这个方法加到事务管理中。
下面我们来看看为什么会失效?
其实 spring的@Transactional事务生效的一个前提是方法调用前经过拦截器TransactionInterceptor , 也就是说只有通过TransactionInterceptor拦截器的方法才会被加入到Spring事务管理中,
查看spring源码可以知道,在AdvisedSupport.getInterceptorsAndDynamicInterceptionAdvice方法中会调用方法中获取@Transactional注解,如果有该注解则启用事务,否则不启用注解

这个方法是通过spring的AOP类CglibAopProxy的内部类DynamicAdviseInterceptor调用的,而DynamicAdvisedInterceptor继承了MethodInterceptor,用于拦截方法调用,并从中获取调用链。
如果是在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用,必须将方法放入另外一个类中,并且该类通过spring注入
总结一下:Transactional是Spring提供的事务管理注解
spring 采用动态代理(AOP)实现对Bean的管理和切片,它为我们的每个class生成一个代理对象,只有在代理对象之间进行调用时,可以触发切面逻辑。
而在同一个类中,方法B调用A,调用的事元对象的方法,而不是通过代理对象,所以spring无法切到这次调用,也就是无法通过注解保证事务性。
解决方案:
- 可以将方法放入另一个类,并且该类通过spring注入,即符合了在对象之间调用的条件。
- 获取本对象的代理对象,再进行调用。具体操作如:
1)Spring-content.xml上下文中,增加配置:<aop:aspectj-autoproxy expose-proxy=“true”/>
2)在xxxServiceImpl中,用(xxxService)(AopContext.currentProxy()),获取到xxxService的代理类,再调用事务方法,强行经过代理类,激活事务切面。 - 很多时候,方法内调用又希望激活事务,是由于同一个方法既有DAO操作又有I/O等耗时操作,不想让耗时的I/O造成事务的太长耗时(比如新增商品同时需要写入库存)。此时,可以将I/O做成异步操作(如加入线程池),而加入线程池的操作即便加入事务也不会导致事务太长,问题可以迎刃而解。
???这条不太懂
Transaction 在同一个类中不生效的更多相关文章
- SpringCache @Cacheable 在同一个类中调用方法,导致缓存不生效的问题及解决办法
由于项目需要使用SpringCache来做一点缓存,但自己之前没有使用过(其实是没有听过)SpringCache,于是,必须先学习之. 在网上找到一篇文章,比较好,就先学习了,地址是: https:/ ...
- Spring @Cacheable注解 && 事务@Transactional 在同一个类中的方法调用不生效
@Cacheable 注解在对象内部调用不会生效 代码示例:ProductServiceImpl.java public List<ProductInfoVO> getProductLis ...
- 分析spring事务@Transactional注解在同一个类中的方法之间调用不生效的原因及解决方案
问题: 在Spring管理的项目中,方法A使用了Transactional注解,试图实现事务性.但当同一个class中的方法B调用方法A时,会发现方法A中的异常不再导致回滚,也即事务失效了. 当这个方 ...
- 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法
参考原贴地址:https://blog.csdn.net/clementad/article/details/47339519 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Trans ...
- 【转】在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational)的方法,注解失效的原因和解决方法
参考 原文链接 @Transactional does not work on method level 描述 在同一个类中,一个方法调用另外一个有注解(比如@Async,@Transational) ...
- @Transactional 同一个类中无事务方法a()内部调用有事务方法b()的问题
https://blog.csdn.net/u010235716/article/details/90171802 1. 事务的4种特性 序号 参数 含义1 原子性(Atomicity) ...
- Spring同一个类中的注解方法调用AOP失效问题总结
public interface XxxService { // a -> b void a(); void b(); } @Slf4j public class XxxServiceImpl ...
- 《同一个类中不同方法之间的调用相关问题(省略的类名或者this)》
//同一个类中不同方法之间的调用相关问题(省略的类名或者this) class A { public void B() { System.out.println("b方法运行"); ...
- 梳理:python—同一个类中的方法调用
为什么突然在此提到这个梳理问题呢? 因为在自己实践综合练习学过的知识时,突然觉得有些知识点的运用总是不成功,于是翻过课本进行回顾,总是觉得是对的,可是当再进一步思考“既然是对的,为什么在程序中总是不成 ...
随机推荐
- 阶段1 语言基础+高级_1-3-Java语言高级_04-集合_07 Collections工具类_3_Collections集合工具类的方法
第二个参数传递了一个匿名内部类.结果就出现了下面的代码 源码里面有Compare方法,对比两个参数 要重写比较的方法 对对象进行排序 创建学生类.对学生类进行排序 重写Person的ToString方 ...
- php-fpm启动不起来,php-fpm无法启动的一种情况
今天碰了一个很奇怪的问题,平时好好的php-fpm修改了一个参数后,突然启动不起来了,试着把参数还原.甚至用备份的配置文件还原都没办法启动php,而且不给任务启动错误的提示,纳闷!!!后来上网找了个资 ...
- Learn Python the hard way, ex41 来自Percal 25 号星星的哥顿人
我承认,我偷懒了,少打了大量代码(剧情),英文太差,下次可以编个中文的试试 #!/urs/bin/python #coding:utf-8 from sys import exit from rand ...
- 创建DSN
DSN:ata Source Name (DSN)的PDO命名惯例为:PDO驱动程序的名称,后面为一个冒号,再后面是可选的驱动程序连接数据库变量信息,如主机名.端口和数据库名. 有三种类型的DSN,三 ...
- levelDB Block
http://blog.csdn.net/sparkliang/article/details/8635821 BlockBuilder的接口 首先从Block的构建开始,这就是BlockBuilde ...
- Java-集合第二篇Set集合
1.Set集合与Collection基本相同,没有提供额外的方法.实际上Set就是Collection,只是行为略有所不同(Set不允许有重复元素). Set下的HashSet.TreeSet.Enu ...
- document.domain location.hostname location.host
document.domain location.hostname location.host :https://www.cnblogs.com/shd-study/p/103031 ...
- wxpython中复选框的基本使用源码实例
#coding=utf-8 import wx class MyFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self,None,-1, ...
- ASP.NET MVC @html帮助类
原文:https://www.cnblogs.com/caofangsheng/p/10462494.html HTML Helpers是用来创建HTML标签进而创建HTML控件的.HTML Help ...
- spark复习笔记(2)
之前工作的时候经常用,隔了段时间,现在学校要用学的东西也忘了,翻翻书谢谢博客吧. 1.什么是spark? Spark是一种快速.通用.可扩展的大数据分析引擎,2009年诞生于加州大学伯克利分校AMPL ...