Java Spring AOP源码解析之事务实现原理
不用spring管理事务?
让我们先来看一下不用spring管理事务时,各种框架是如何管理事务的
使用jdbc来管理事务
使用hibernate来管理事务
业务逻辑和事务代码是耦合到一块的,并且和框架的具体api绑定了。当我们换一种框架来实现时,里面对事务控制的代码就要推倒重写,并不一定能保证替换后的api和之前的api有相同的行为。
基于这些问题,spring抽象了一些事务相关的顶层接口,我们面向接口编程,换框架时只要换具体的实现即可。有点像jdbc api的味道了
常用api | 接口 |
---|---|
platformtransactionmanager | 对事务进行管理 |
transactiondefinition | 定义事务的相关属性,例如隔离级别,传播行为 |
transactionstatus | 保存事务状态 |
针对不同的数据访问技术,使用不用的platformtransactionmanager类即可
数据访问技术 | platformtransactionmanager实现类 |
---|---|
jdbc/mybatis | datasourcetransactionmanager |
hibernate | hibernatetransactionmanager |
jpa | jpatransactionmanager |
jms | jmstransactionmanager |
编程式事务管理
使用platformtransactionmanager
使用transactiontemplate
当我们直接使用platformtransactionmanager来管理事务时,有很多模版代码。例如业务代码正常执行,提交事务,否则回滚事务。我们可以把这部分模版代码封装成一个模版类,这样使用起来就很方便了,如下所示
如下图所示,transactiontemplate#execute方法就是一个典型的模版方法
我们可以传入如下2个接口的实现类来执行业务逻辑,transactioncallback(需要返回执行结果)或transactioncallbackwithoutresult(不需要返回结果)
声明式事务管理
为了让使用更加简洁,spring直接把事务代码的执行放到切面中了,我们只需要在业务代码方法上加上一个@transactional注解即可,这种方式我们最常用哈
使用@transactional注解
此时事务相关的定义我们就可以通过@transactional注解来设置了
属性名 | 类型 | 描述 | 默认值 |
---|---|---|---|
value(和transactionmanager互为别名) | string | 当在配置文件中有多个platformtransactionmanager ,用该属性指定选择哪个事务管理器 | 空字符串"" |
propagation | 枚举:propagation | 事务的传播行为 | required |
isolation | 枚举:isolation | 事务的隔离度 | default |
timeout | int | 事务的超时时间。如果超过该时间限制但事务还没有完成,则自动回滚事务 | -1 |
readonly | boolean | 指定事务是否为只读事务 | false |
rollbackfor | class[] | 需要回滚的异常 | 空数组{} |
rollbackforclassname | string[] | 需要回滚的异常类名 | 空数组{} |
norollbackfor | class[] | 不需要回滚的异常 | 空数组{} |
norollbackforclassname | string[] | 不需要回滚的异常类名 | 空数组{} |
源码解析
我们需要在配置类上加上@enabletransactionmanagement注解,来开启spring事务管理功能,@enabletransactionmanagement最主要的功能就是注入一个transactioninterceptor拦截器,来控制事务开启,提交或者回滚
proxytransactionmanagementconfiguration
transactioninterceptor#invoke
transactionaspectsupport#invokewithintransaction
transactionaspectsupport#createtransactionifnecessary
当开启事务的时候,可以看到各种传播属性的行为
abstractplatformtransactionmanager#gettransaction
spring事务的传播行为在propagation枚举类中定义了如下几种选择
支持当前事务
-
required
:如果当前存在事务,则加入该事务。如果当前没有事务,则创建一个新的事务 -
supports
:如果当前存在事务,则加入该事务 。如果当前没有事务, 则以非事务的方式继续运行 -
mandatory
:如果当前存在事务,则加入该事务 。如果当前没有事务,则抛出异常
不支持当前事务
-
requires_new
:创建一个新事务,如果当前存在事务,则把当前事务挂起 -
not_supported
: 以非事务方式运行,如果当前存在事务,则把当前事务挂起 -
never
: 以非事务方式运行,如果当前存在事务,则抛出异常
其他情况
-
nested
:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来执行 。如果当前没有事务,则该取值等价于required
以nested启动的事务内嵌于外部事务中 (如果存在外部事务的话),此时内嵌事务并不是一个独立的事务,它依赖于外部事务。只有通过外部事务的提交,才能引起内部事务的提交,嵌套的子事务不能单独提交
参考博客
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注的更多内容!
上一篇: python将天气预报可视化
下一篇: VSCode编辑器和开发环境搭建
推荐阅读
-
Spring AOP原理解析——基于自动代理AOP是如何实现的?
-
Spring源码学习【六】AOP原理解析(一)代理对象的生成
-
Spring的AOP实现原理源码解析
-
并发编程(十三)—— Java 线程池 实现原理与源码深度解析 之 Executors(三)
-
互联网架构-Spring5.0源码深度解析:SpringBean声明事务底层实现原理
-
Java Spring AOP源码解析之事务实现原理
-
Spring源码剖析7:AOP实现原理详解
-
spring5 源码深度解析----- Spring事务 是怎么通过AOP实现的?(100%理解Spring事务)
-
互联网架构-Spring5.0源码深度解析:SpringBean声明事务底层实现原理
-
并发编程(十三)—— Java 线程池 实现原理与源码深度解析 之 Executors(三)