难经6:小心,SpringAOP声明式事务的一个缺陷

难经6:小心,SpringAOP声明式事务的一个缺陷
关键字: spring aop 事务 声明式
[问题]

Spring的声明式事务,我想就不用多介绍了吧,一句话“自从用了Spring AOP啊,事务管理真轻松啊,真轻松;事务管理代码没有了,脑不酸了,手不痛了,一口气全配上了事务;轻量级,测试起来也简单,嘿!”。不管从哪个角度看,轻量级声明式事务都是一件解放生产力的大好事。所以,我们“一直用它”。



不过,最近的一个项目里,却碰到了一个事务管理上的问题:有一个服务类,其一个声明了事务的方法,里面做了三次插入SQL操作,但是在后面出错回滚时,却发现前面插入成功了,也是说,这个声明了事务的方法,实际上并没有真正启动事务!怎么回事呢?难道Spring的声明式事务失效了?



[探幽]

其实以前也会碰到有人说,Spring的事务配置不起作用,但是根据第一反应和以往经验,我总会告诉他,肯定是你的配置有问题啦;所以这一次,我想也不会例外,大概是把事务注解配在了接口上而不是实现方法上,或者,如果是用XML声明方式的话,很可能是切入点的表达式没有配对。



不过,在检查了他们的配置后,却发现没有配置问题,该起事务的实现方法上,用了@Transactional事务注解声明,XML里也配了注解驱动<tx:annotation-driven .../>,配置很正确啊,怎么会不起作用?



我很纳闷,于是往下问:

问1:其他方法有这种情况么?

答1:没有。

问2:这个方法有什么特别的么(以下简称方法B)?

答2:就是调后台插了三条记录啊,没啥特别的。

问3:这个方法是从Web层直接调用的吧?

答3:不是,是这个Service类(以下简称ServiceA)的另外一个方法调过来的(以下简称方法A)。

问4:哦,那个调用它的方法配了事务么(问题可能在这了)?

答4:没有。

问5:那WEB层的Action(用的是Struts2),调用的是没有声明事务的方法A,方法A再调用声明了事务的方法B?

答5:对的。

问6:你直接在方法A上加上事务声明看看

答6:好。。。



看来可能找到问题所在了,于是把@Transactional也加在方法A上,启动项目测试,结果是:事务正常生效,方法A和方法B都在一个事务里了。



好了,现在总结一下现象:

1、ServiceA类为Web层的Action服务

2、Action调用了ServiceA的方法A,而方法A没有声明事务(原因是方法A本身比较耗时而又不需要事务)

3、ServiceA的方法A调用了自己的方法B,而方法B声明了事务,但是方法B的事务声明在这种情况失效了。

4、如果在方法A上也声明事务,则在Action调用方法A时,事务生效,而方法B则自动参与了这个事务。



我让他先把A也加上事务声明,决定回来自己再测一下。



这个问题,表面上是事务声明失效的问题,实质上很可能是Spring的AOP机制实现角度的问题。我想到很久以前研究Spring的AOP实现时发现的一个现象:对于以Cglib方式增强的AOP目标类,会创建两个对象,一个事Bean实例本身,一个是Cglib增强代理对象,而不仅仅是只有后者。我曾经疑惑过这一点,但当时没有再仔细探究下去。



我们知道,Spring的AOP实现方式有两种:1、Java代理方式;2、Cglib动态增强方式,这两种方式在Spring中是可以无缝自由切换的。Java代理方式的优点是不依赖第三方jar包,缺点是不能代理类,只能代理接口。



Spring通过AopProxy接口,抽象了这两种实现,实现了一致的AOP方式:







现在看来,这种抽象同样带了一个缺陷,那就是抹杀了Cglib能够直接创建普通类的增强子类的能力,Spring相当于把Cglib动态生成的子类,当普通的代理类了,这也是为什么会创建两个对象的原因。下图显示了Spring的AOP代理类的实际调用过程:









因此,从上面的分析可以看出,methodB没有被AopProxy通知到,导致最终结果是:被Spring的AOP增强的类,在同一个类的内部方法调用时,其被调用方法上的增强通知将不起作用。



而这种结果,会造成什么影响呢:

1:内部调用时,被调用方法的事务声明将不起作用

2:换句话说,你在某个方法上声明它需要事务的时候,如果这个类还有其他开发者,你将不能保证这个方法真的会在事务环境中

3:再换句话说,Spring的事务传播策略在内部方法调用时将不起作用。不管你希望某个方法需要单独事务,是RequiresNew,还是要嵌套事务,要Nested,等等,统统不起作用。

4:不仅仅是事务通知,所有你自己利用Spring实现的AOP通知,都会受到同样限制。。。。



[解难]



问题的原因已经找到,其实,我理想中的AOP实现,应该是下面这样:







只要一个Cglib增强对象就好,对于Java代理方式,我的选择是毫不犹豫的抛弃。



至于前面的事务问题,只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务,那么一切OK。
Java开发者必看:5分钟搞定PaddleOCR表格识别,导出Excel和HTML超详细教程 本文为Java开发者提供了集成PaddleOCR实现智能表格识别的详细教程,包括环境配置、核心代码实现、结果导出到Excel和HTML的步骤,以及性能优化技巧。通过PaddleOCR技术,开发者可以快速将图片表格转换为结构化数据,大幅提升工作效率。 阅读详情

相关推荐

FFmpeg 部署与使用(含Docker部署)

ffmpeg 部署以及使用

weixin_38584583的博客 913

Spring中@Transactional事务失效原因

Transactional 注解的作用就是保证方法内的多个数据库操作具有事务特性,即要么都成功提交,要么都失败回滚。但是错误的使用会导致事务失效,这里总结了九种可能发生事务失效的原因。

weixin_47390965的博客 1663

使用podman 容器化安装DIFY

本文阐述了使用podman容器化安装DIFY的过程

wengad的博客 1902

spring aop的一些局限性。

spring的aop还是蛮好用的。尤其是基于annotation的pointcut,定义一个annotation,再在配置文件里配置一下,就搞定了。 但spring的aop还是有一些局限性的。 1.只能用在spring容器管理的类上面进行aop,对不是spring实例化的对象

fei1703的专栏 2084

基于Gardner环的QPSK定时同步MATLAB仿真:四倍采样与多场景性能分析

本文详细介绍了基于Gardner环的QPSK定时同步MATLAB仿真方法,重点分析了四倍采样技术在定时同步中的应用与性能优化。通过MATLAB代码实例展示了Gardner环的实现原理、多场景性能分析及常见问题解决方案,为数字通信系统的定时同步设计提供实用参考。

weixin_29083475的博客 374

Visual Studio报错TRK0005找不到CL.exe?三步彻底解决环境变量问题

本文详细解析了Visual Studio报错TRK0005找不到CL.exe的根本原因,并提供了三步彻底解决环境变量问题的方案。从验证安装完整性到配置永久环境变量,再到注册表级修复,帮助开发者建立健壮的开发环境配置体系,确保编译链稳定运行。

weixin_30839881的博客 459

spring事务@Transactional失效原因及解决办法

spring事务@Transactional失效原因及解决办法

liaomingwu的专栏 5332

遥感影像分割实战:LoveDA数据集从下载到训练全流程指南(附避坑技巧)

本文以LoveDA数据集为例,提供了一份详尽的遥感影像语义分割实战指南。内容涵盖从数据下载、理解与预处理,到环境配置、模型选择与训练,再到性能调优与部署的全流程,并重点分享了多个关键环节的避坑技巧,旨在帮助开发者和研究者高效上手并解决实际问题。

cherry的博客 930

Spring的@Transactional注解不生效的原因

Spring的@Transactional注解不生效的原因

qq_43526183的博客 4378

Python 爬虫教程:抓取视频平台数据(观看量、评论数、点赞数等)

爬虫(Crawler)是通过编写程序模拟浏览器行为,从互联网上抓取并提取信息的技术。爬虫的核心任务是模拟用户访问网页,获取网页内容并解析出我们需要的数据。爬虫技术被广泛应用于搜索引擎、数据分析、电商价格监控、内容抓取等领域。Bilibili和YouTube。这两个平台都提供丰富的用户生成内容(UGC),且在中国和全球范围内都非常流行。Bilibili:以二次元文化为主的视频平台,用户活跃,视频内容丰富。Bilibili的网页数据较为简单,可以通过传统的HTML解析抓取。YouTube。

2201_76125261的博客 1854

【YOLOv11】014、YOLOv11模型导出:PyTorch到ONNX格式转换与优化

摘要:本文详细介绍了如何将PyTorch训练的YOLOv11模型高效转换为ONNX格式。重点包括:分离模型特征提取与后处理、设置动态维度、优化ONNX算子、验证转换正确性等关键步骤。作者分享了实际项目中的经验教训,如版本对齐、算子兼容性处理、后处理分离等实用技巧,并推荐使用onnx-simplifier工具优化模型。文章强调模型转换是一个需要反复调试的过程,建议保留转换记录形成知识库,以提高部署效率并避免常见错误。

企鹅码农的专属播客,分享10多年的实战案例和经验解读,包含YOLO、RT-DETR、AI等各个工作领域。 307

Spring 事务(Transactional)失效的七种原因及解决方案(含项目代码)

Spring框架提供了强大的事务管理功能,能够确保数据库操作的一致性和可靠性。然而,有时候我们可能会遇到Spring事务失效的情况,导致数据不一致或操作失败。本文将探讨Spring事务失效的原因,以及如何避免和解决这些问题。通过深入了解失效原因,我们可以更好地利用Spring事务管理功能,确保系统的稳定性和可靠性。

qq_45607784的博客 7755

pandas教程:2012 Federal Election Commission Database 2012联邦选举委员会数据库

里面包含了支持者的名字,职业和雇主,地址,赞助金额。我们可以已经能想到如何切割、整理数据,来提取赞助者的统计数据,或提取宣传活动的模式,这里我们展示一些不同的分析方法。可以看到有些职业是同一种工作类型,指代的是同一个东西。这两个连续操作是分别独立执行的,一个结束后,另一个才开始。上,这里我是把数据集压缩成了ZIP格式,解压后能正常导入)。我觉得也有必要好好了解一下,这个网站做了很好的讲解,),所以我们最好添加这样的信息。这样的情况,即把两个索引操作连在一起。,发现映射关系被正常执行了,所以这里的。

Cachel Wood的博客 351

小心,SpringAOP声明式事务的一个缺陷

今天碰上一个spring不起作用的问题,明显感觉是AOP切面有问题,但是自己又不能解释清楚,还好,晚上查询下资料,正好碰上一个说的这么明白的主,真是很好很明白啊,文章链接地址: http://liuu.iteye.com/blog/422810 具体内容如下: [问题]        Spring的声明式事务,我想就不用多介绍了吧,一句话“自

click726的专栏 1379

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

转自liuu的一些spring文章

liuu 永久域名 http://liuu.iteye.com难经7:被忽略的Spring3小改进——支持多数据源的@Transactional事务注解难经6:小心,SpringAOP声明式事务的一个缺陷 

小菜的粉丝——专栏 653

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

工作中使用到的单词(软件开发)

1.エイリアス   alias 别名 powershell使用 get-help 命令时,会得到与此命令 相关(别名)的命令 2.プロキシ proxy 代 理 3.プロモート   promote 促进,提升   开发的系统新功能上线发布,有时会使用到这个词,比如 STプロモート 还有使用リリース这个词的。比如STリリース。个人认为两者含义相同。 4.見逃し み................................................................

sun0322 6万+

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

spring事务(注解 @Transactional )失效的12种场景

文章目录一 、事务不生效【七种】1.访问权限问题 (只有public方法会生效)2. 方法用final修饰,不会生效3.同一个类中的方法直接内部调用,会导致事务失效3.1 新加一个Service方法3.2 在该Service类中注入自己3.3 通过AopContent类4.(类本身) 未被spring管理5.多线程调用6.(存储引擎)表不支持事务7.未开启事务二、事务不回滚【五种】1.错误的传播特性2.自己吞了异常3.手动抛了别的异常4.自定义了回滚异常5.嵌套事务回滚多了三、大事务与编程式事务1. 大事务

憧憬的专栏 4万+

声明式事务

声明式事务 @Transactional是基于Spring AOP实现,方法就是在方法前后进行拦截。 这种事务的开启简单优雅,是Spring官方推荐的用法。 声明式事务的缺点 1.声明式他是作用在方法上 也就是说,如果需要给哪部分代码增加事务的话,需要把这部分代码独立出来,作为一个方法。 这种通过注解(配置也可以)的方式,很容易被人开发同学忽略。 忽略的是让开发同学没有意识到使用的方法是被事务嵌套的 也就是在编码过程中,在事务方法中加入如下方法 1. RPC调用 2. 文件写入 3. 缓存更新 4. 消息发

qq_40457631的博客 1686

【AOP的实现之SpringAop(一)】:spring和aspectj结合实现Aop的局限性,以及性能比较

AOP操作术语 Spring的aop操作 SpringAOP局限性 只能对spring管理的bean增加aop功能 1 在spring里面进行aop操作,使用aspectj实现 (1)aspectj不是spring一部分,和spring一起使用进行aop操作 (2)Spring2.0以后新增了对AspectJ支持 2 使用aspectj实现aop有两种方式 (1)基于aspectj的x...

qq_20610631的博客 541

【spring】@Transactional 注解失效的原因及解决办法

面试中经常会被问到事务失效的场景有哪些,其实在开发中,若是不了解事务失效的场景,当你觉得加了事务,就会回滚,就大错特错了,今天就来了解一下吧。

来到人间不过是个蹭饭的客人,还挑什么酸甜苦辣。 7493

spring aop的优劣

博主认为java spring的aop切面编程,类似于python的装饰器,方便将日志记录、测试等通用功能提取,在不改变原来代码的基础上增强功能。部分单一需求场景适用,对于复杂的业务场景并不能总是适用,一味的追求aop反而会带来很多副作用。因此,aop可以作为一种设计模式去参考,而不能作为一种必选方式应用的日常的架构设计,程序开发中,否则会适得其反。

海若_matrix的博客 1011

【示例】Spring-AOP理解

System.out.println("---------基于XML自定义类方式实现,前置通知:方法执行前---------");System.out.println("---------基于XML自定义类方式实现,后置通知:方法执行前---------");

HMTeen 1118

Spring/SpringBoot中的声明式事务和编程式事务源码、区别、优缺点、适用场景以及实战

在现代软件开发中,事务处理是必不可少的一部分。当多个操作需要作为一个整体来执行时,事务可以确保数据的完整性和一致性,并避免出现异常和错误情况。在SpringBoot框架中,我们可以使用声明式事务和编程式事务来管理事务处理。其中事务的坑也是不少,比较常见的就是事务失效,大家可以看看!后面小编在出一篇事务失效场景哈,喜欢的可以关注,等待更新哈!这篇博客将重点探讨这两种事务处理方式的源码实现、区别、优缺点、适用场景以及实战。我们来接着说事务,里面还涉及到三个知识点,大家可以自行百度好好了解!事务的特性。

xxxzzzqqq_的博客 966
上一篇: spring 异常 事务
下一篇: spring aop 注释
kakarot_java
博客等级 码龄19年 0粉丝 32原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值