spring aop和事务同时开启带来的一些问题
最近自己在写一个aop切面,主要是用来记录日志和打印一些信息的,在测试过程中,发现,业务方法在加了事务之后,如果有其他异常抛出,事务并没有回滚,于是,就Google了一把,发现有大佬遇到过这个问题,大部分博客给到的答案是:因为切面的优先级低于事务的优先级,导致事务advisor生成的代理对象被,切面生成的代理对象给覆盖了,需要在切面上加上@Order(1)注解,这样可以保证,切面的优先级较高
我自己忽然间想到之前,遇到过类似的问题,并且也记录到了线上问题模块,按照实际操作之后,确实:在切面上加了@Order(1)注解之后,事务就生效了
但是自己又想了下,之前学习spring源码的时候,并不记得会生成两个代理对象。。。所以这里就很好奇,所以,自己又撸了一遍aop的源码,最后发现原因了,我的结论是这样的:
- 因为我自己写的切面,在@Aroud环绕通知的方法,我手动加了try catch 捕获了throwable 然后打印了一行日志
- 在没有加@Order(1)的时候,确实是事务先执行,然后再执行aop的切面,但是在执行切面的时候,捕获到了数组越界的异常,然后打印了日志,没有继续上抛异常
- 继而导致事务在处理的时候,并没有捕获到异常,直接就提交事务了, 如果用一段伪代码来描述的话,那应该是这样的
try{
try{
执行目标方法
}catch(th){
log.error(“执行报错”)
}
}catch (Throwable ex) {
// target invocation exception
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
那么问题,就来了,按照我的这个代码,只有在切面中,记录了error日志之后,然后继续抛出异常就可以了,我自己试了下,不在切面上添加@Order(1)注解,也确实是ok的
所以,我写的这个代码,同时开启aop和事务不生效,是因为切面优先级高,先执行,但是把异常给吞掉了,导致事务不知道发生了异常
aop和事务源码
抛开这个问题,那到底会不会生成两个代理对象?我认为是不会生成两个代理对象的,因为我觉得,对于spring来讲,一个bean,既要开启事务,又有切面,如果生成两个代理对象,其实是没必要的,既然切面和事务有优先级,那就嵌套就ok了
在之前博客中,有介绍过springaop和事务的源码,其实,简单来说
- 在bean初始化流程中,依次会解析aop的切面和事务advisor
- 第八个后置处理器执行的时候,会获取到作用在当前bean的advisor(事务其实就是一个advisor)
- 假如此时获取到有两个advisor作用在该bean上,那就根据这两个advisor生成代理对象,在生成代理对象的时候,会专门有一个变量来存储所有的advisor
- 在目标方法被执行的时候,会获取方法所要执行的通知方法,按照优先级嵌套执行
所以,我觉得,对于一个问题,要有自己的思考,在解决了问题之后,需要确认下,真正的原因是什么
spring aop和事务同时开启带来的一些问题相关推荐
- Spring 如何在一个事务中开启另一个事务?
Spring项目,需要在一个事务中开启另一个事务. 上面提到的情景可能不常见,但是还是会有的,一旦遇到,如果业务比较复杂,就会很麻烦,但是还是有解决的方案的,比如将一个service方法拆成两个方法, ...
- spring aop xml事务配置
<aop:config> <!-- 通过aop定义事务增强切面--><aop:pointcut id="serviceMethod" expressi ...
- Spring AOP及事务说明
目录 1.事务管理 1.1 事务说明 1.2 Spring事务管理 1.3 事务进阶 (1)Transactional属性说明 (2)rollbackFor属性 (3)propagation属性 1. ...
- Spring AOP (事务管理)
一.声明式事务管理的概括 声明式事务(declarative transaction management)是Spring提供的对程序事务管理的方式之一. Spring的声明式事务顾名思义就是采用声明 ...
- Spring AOP在事务中的应用典范
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...
- 事务框架之声明事务(自动开启,自动提交,自动回滚)Spring AOP 封装
利用Spring AOP 封装事务类,自己的在方法前begin 事务,完成后提交事务,有异常回滚事务 比起之前的编程式事务,AOP将事务的开启与提交写在了环绕通知里面,回滚写在异常通知里面,找到指定的 ...
- 哪些方法不能够实施Spring AOP事务
2019独角兽企业重金招聘Python工程师标准>>> 哪些方法不能够实施Spring AOP事务 由于Spring事务管理是基于接口代理或动态字节码技术.通过AOP实施事务增强. ...
- 基于Spring中的事务管理机制
什么是事务? 通俗理解,事务其实就是一系列指令的集合. 为什么要使用事务管理? 我们在实际业务场景中,经常会遇到数据频繁修改读取的问题.在同一时刻,不同的业务逻辑对同一个表数据进行修改,这种冲突很可能 ...
- Spring--基于AOP实现事务控制
Spring–概念与模块 Spring–快速入门 Spring–基于IOC的CRUD操作 Spring–整合Junit Spring–AOP面向切面编程 Spring–基于注解的AOP配置 Sprin ...
- Spring AOP简单入门学习
Spring AOP 1.主要内容: 2.代理模式 代理模式在 Java 开发中是⼀种⽐较常⻅的设计模式.设计⽬的旨在为服务类与客户类之间插⼊其他功能,插⼊的功能对于调⽤者是透明的,起到伪装控制的 ...
最新文章
- 【洛谷P1697】货车运输
- 【细无巨细,包你学会】自学Python运行时会遇到的异常与解决方法
- 题目梳理(一)(2019.07.06~2019.07.20)
- Corosync Pacemaker 高可用 Mariadb
- 最后两周!60万奖金AI攻防赛进入冲刺(附baseline代码及实操)
- JavaFX逆运动学库2.0
- 冒泡排序 自带时间复杂度测试
- 前端学习(3167):react-hello-react之鼠标添加一个todoList
- 面试题,你什么时候可以入职?回答不好,容易被压薪资
- xiao77论坛php,论坛
- 【转】linux命令:ifconfig命令
- 微信取消支付再二次/多次支付及201商户订单号重复解决思路
- C51与MDK共存 Keil5安装教程 WIN10 亲测可用
- 熊猫关键词工具v2.8.1.0绿色版SEO工具
- PHP获取域名及域名IP的方法
- video视频播放中trank标签字幕显示问题
- leetcode 803.打砖块(C/C++/Java/python)
- 哪里有电,哪里就应该有网络 ,华为移动路由Pro评测
- Android破解九宫格密码
- 多服务器显卡使用状态监控工具实现
热门文章
- PageRank算法简单实现
- 容器技术Docker K8s 42 Serverless Kubernetes(ASK)详解-ASK应用管理
- 获取最顶层的ViewController top ViewController swift
- 易筋SpringBoot 2.1 | 第十一篇:SpringBoot使用actuator
- 2021-09-07客户端向 NameNode 请求创建文件,NameNode 根据元数据信息计算出文件的元数 据信息
- 295.数据流的中位数
- linux常用分区大小,Linux基本知识点总结——硬盘分区及LVM
- 深度学习笔记(二):简单神经网络,后向传播算法及实现
- 基于IDEA使用Spark API开放Spark程序(1)
- 每日一题/006/矩阵/设 n阶实对称矩阵 A满足 A^2=A,且 A 的秩为r,试求行列式 det(2E-A) 的值