在《Spring Boot事务管理(下)》中,已经介绍了如果在 protected、private 或者默认可见性的方法上使用@Transactional,事务将是摆设,也不会抛出任何异常,并简单的给出了一些使用时的注意事项。本文在此基础上进一步解释如何正确使用Spring声明式事务。
一、关于目标对象内部方法自我调用的不同情形和存在的问题
1、情形1:只给b方法上加事务注解,a方法上不加
public interface AService {
public void a();
public void b();
}
@Service()
public class AServiceImpl implements AService{
public void a() {
this.b();
}
@Transactional(rollbackFor={Exception.class})
public void b() {
insert();
update();
}
}
只要给目标类AServiceImpl的某个方法加上注解@Transactional,Spring就会为目标类生成对应的代理类,以后调用AServiceImpl中的所有方法都会先走代理类(即使调用未加事务注解的方法a,也走),即在通过getBean("AServiceImpl")获得业务类时,实际上得到的是一个代理类,假设这个类叫做AServiceImplProxy,Spring为AServiceImpl生成的代理类类似于如下代码:
public class AServiceImplProxy implements AService{
public void a() {
//反射调用目标类的a方法
}
public void b() {
//启动事务的代码
//反射调用目标类的b方法
//事务提交的代码
}
}
由于目标类中只有b方法加入了事务管理,所以代理类中只为b方法加入了横切事务逻辑,Spring事务管理的本质是通过aop为目标类生成动态代理类,并在需要进行事务管理的方法中加入事务管理的横切逻辑代码,如AServiceImplProxy中的b方法所示。
调用getBean("AServiceImpl").a()时,实际上执行的是AServiceImplProxy.a(),代理类的a方法会通过反射调用目标类的a方法, 再在目标类的a方法中调用b方法,故最终a中调用的b方法是来自于AServiceImpl中的b方法,AServiceImpl的b方法并没有横切事务逻辑代码(切记:事务逻辑代码在代理类中,@Transactional只是标记此方法在代理类中要加入事务逻辑代码)。所以调用a方法时,b方法的事务会失效。
其实,在proxy对象与目标对象之间还有一个InvocationHandler对象(以jdk动态代理为例),真正的横切逻辑是放到InvocationHandler对象中的,调用逻辑分离到InvocationHandler中主要是为了构造出具有通用性和简单性的代理类,此处为了简化处理过程,统一放到代理对象中来说明,动态代理简化的调用关系图如下:
aaarticlea/png;base64,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" alt="" width="540" height="331" />
AOP中存在方法嵌套调用时,相应的调用过程序列图如下:
aaarticlea/png;base64,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" alt="" width="648" height="429" />
2、情形2:给a方法加事务注解,b方法上加或不加
对1中的代码做修改,为a方法也加上事务注解:
@Service()
public class AServiceImpl implements AService{
@Transactional(rollbackFor={Exception.class})
public void a() {
this.b();
}
@Transactional(rollbackFor={Exception.class})
public void b() {
insert();
update();
}
}
此时生成的代理类类似如下代码:
public class AServiceImplProxy implements AService{
public void a() {
//启动事务的代码
//反射调用目标类的a方法
//事务提交的代码
}
public void b() {
//启动事务的代码
//反射调用目标类的b方法
//事务提交的代码
}
}
即为a和b都加入了事务横切逻辑。在这种情况下,调用顺序还和1中情形类似,区别在于在反射调用目标对象的a方法前,会对a方法开启事务管理,虽然调用的b方法还是目标对象中没有加事务逻辑的代码,spring却会把b合并到a的事务中去,此时相当于只有一个事务。如果再将目标类代码改为:
@Service()
public class AServiceImpl implements AService{
@Transactional(rollbackFor={Exception.class})
public void a() {
this.b();
}
public void b() {
insert();
update();
}
}
即只在a上加事务控制,由于b会合并到a的事务中,所以b中的逻辑也可以被事务管理。
由于a和b都合并到了a的事务中,所以这种情形下事务传递规则不适用。代理类中加了事务逻辑的b方法永远不会被调用。那么问题来了,如果我想让b也执行自己的事务逻辑,即调用b时执行代理类中b方法的事务逻辑,该怎么办?修改目标类中的a方法:
@Transactional(rollbackFor={Exception.class})
public void a() {
((AService) AopContext.currentProxy()).b();
//即调用AOP代理对象的b方法即可执行事务切面进行事务增强
}
这时,就会强制要求调用代理类中的b方法,从而开启b上的事务,此时b事务上标注的事务传递规则也就可以生效了,详情参见:http://jinnianshilongnian.iteye.com/blog/1487235
个人觉得这种方法不太好,会污染业务逻辑代码,使代码变复杂,而且不符合低侵入的开发理念。还有一种办法就是接口下沉,把b方法分离到另一个接口中,从根源上避免目标对象内部方法自我调用。
二、try catch的问题
有时需要在业务逻辑代码中显式try catch包裹事务代码,以便在出现异常时进行一些别的处理。目标类的接口和实现示例代码如下:
public interface AService {
public void a();
}
@Service()
public class AServiceImpl implements AService{
@Transactional(rollbackFor={Exception.class})
public void a() {
try{
insert();
update();
}catch(Exception e){
// to do something
}
}
}
自己在代码中显式捕获异常会导致spring事务回滚失效,原因:spring事务是通过aop捕获到异常后再执行回滚,如果业务代码中显式捕获了异常,会导致spring捕获不到,回滚自然失败。
有如下几种解决办法:
(1)业务代码catch住异常后重新抛出,如:
public void a() throws Exception{
try{
insert();
update();
}catch(Exception e){
throw new Exception(e);
}
}
不足是本方法的调用端也必须显式捕获异常。
(2)使用编程式事务显式回滚:
public void a() {
try{
insert();
update();
}catch(Exception e){
//显式回滚
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
不足是事务控制代码会侵入业务代码,也正是因为编程式事务管理会侵入业务逻辑代码,所以才有了申明式事务管理。
(3)接口下沉
将需要事务控制的代码分到另一个接口方法中,如:
public interface BService {
public void a();
public void b();
}
@Service()
public class BServiceImpl implements BService{
@Transactional(rollbackFor={Exception.class})
public void b() {
insert();
update();
}
}
相应的调用端a方法中变为:
- 【Java EE 学习 52】【Spring学习第四天】【Spring与JDBC】【JdbcTemplate创建的三种方式】【Spring事务管理】【事务中使用dbutils则回滚失败!!!??】
一.JDBC编程特点 静态代码+动态变量=JDBC编程. 静态代码:比如所有的数据库连接池 都实现了DataSource接口,都实现了Connection接口. 动态变量:用户名.密码.连接的数据库. ...
- spring事务管理器设计思想(二)
上文见<spring事务管理器设计思想(一)> 对于第二个问题,涉及到事务的传播级别,定义如下: PROPAGATION_REQUIRED-- 如果当前没有事务,就新建一个事务.这是最常见 ...
- spring事务管理器设计思想(一)
在最近做的一个项目里面,涉及到多数据源的操作,比较特殊的是,这多个数据库的表结构完全相同,由于我们使用的ibatis框架作为持久化层,为了防止每一个数据源都配置一套规则,所以重新实现了数据源,根据线程 ...
- 事务管理(下) 配置spring事务管理的几种方式(声明式事务)
配置spring事务管理的几种方式(声明式事务) 概要: Spring对编程式事务的支持与EJB有很大的区别.不像EJB和Java事务API(Java Transaction API, JTA)耦合在 ...
- Spring事务管理器的应对
Spring抽象的DAO体系兼容多种数据访问技术,它们各有特色,各有千秋.像Hibernate是非常优秀的ORM实现方案,但对底层SQL的控制不太方便:而iBatis则通过模板化技术让你方便地控制SQ ...
- Spring事务管理(转)
1 初步理解 理解事务之前,先讲一个你日常生活中最常干的事:取钱. 比如你去ATM机取1000块钱,大体有两个步骤:首先输入密码金额,银行卡扣掉1000元钱:然后ATM出1000元钱.这两个步骤必须是 ...
- [Spring框架]Spring 事务管理基础入门总结.
前言:在之前的博客中已经说过了数据库的事务, 不过那里面更多的是说明事务的一些锁机制, 今天来说一下Spring管理事务的一些基础知识. 之前的文章: [数据库事务与锁]详解一: 彻底理解数据库事务一 ...
- Spring 事务管理 01 ——
目录: 参考: 1.Spring 事务管理高级应用难点剖析: 第 1 部分
- Spring 事务管理原理探究
此处先粘贴出Spring事务需要的配置内容: 1.Spring事务管理器的配置文件: 2.一个普通的JPA框架(此处是mybatis)的配置文件: <bean id="sqlSessi ...
- Spring 事务管理高级应用难点剖析--转
第 1 部分 http://www.ibm.com/search/csass/search/?q=%E4%BA%8B%E5%8A%A1&sn=dw&lang=zh&cc=CN& ...
- (一)JNDI基础
一.简介 在Tomcat 4.1.27之后,在服务器上就直接增加了数据源的配置选项,直接在服务器上配置好数据源连接池即可.在J2EE服务器上保存着一个数据库的多个连接.每一个连接通过DataSourc ...
- MySQL INNER JOIN子句介绍
MySQL INNER JOIN子句介绍 MySQL INNER JOIN子句将一个表中的行与其他表中的行进行匹配,并允许从两个表中查询包含列的行记录. INNER JOIN子句是SELECT语句的可 ...
- javascript--HTML DOM常用元素对象
二,Select:访问select元素 属性:.selectedIndex 获取select中当前选中项的下标 .options 获取select中所有的option元素 返回值为数组 .opti ...
- ASE19团队项目 beta阶段 model组 scrum7 记录
本次会议于12月10日,19时30分在微软北京西二号楼sky garden召开,持续10分钟. 与会人员:Jiyan He, Lei Chai, Linfeng Qi, Xueqing Wu, Kun ...
- 关闭mysql严格模式
配置文件my.ini sql-mode="STRICT_TRANS_TABLES,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION" 修改为 s ...
- python-----将图片与标注的xml坐标水平翻转
我们做机器学习的时候,总会用到很多训练集,然后我们的数据比较少的时候,就可以将图片翻转标注.代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- # ...
- hive中使用spark执行引擎的常用参数
set hive.execution.engine=spark;set hive.exec.parallel=true;set hive.exec.parallel.thread.number=8;s ...
- BackGroundWorker组件使用、Winform控件的Invoke安全调用
BackgroundWorker是·net里用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作. 可以通过编程方式创建 BackgroundWorker,也可以将它从"工具 ...
- C语言I作业12一学期总结
一.我学到的内容 二.我的收获 作业 收获 C语言I博客作业01 学会了编程"Hello word" C语言I博客作业02 安装编译器,将代码建立在自己的文件里面 C语言I博客作业 ...
- Codeforces Round #551 (Div. 2) F. Serval and Bonus Problem (DP/FFT)
yyb大佬的博客 这线段期望好神啊... 还有O(nlogn)FFTO(nlogn)FFTO(nlogn)FFT的做法 Freopen大佬的博客 本蒟蒻只会O(n2)O(n^2)O(n2) CODE ...