Java Spring AOP源码解析之事务实现原理
作者:Java识堂 发布时间:2023-09-10 02:39:46
不用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启动的事务内嵌于外部事务中 (如果存在外部事务的话),此时内嵌事务并不是一个独立的事务,它依赖于外部事务。只有通过外部事务的提交,才能引起内部事务的提交,嵌套的子事务不能单独提交
参考博客
https://www.jb51.net/article/229456.htm
来源:https://blog.csdn.net/zzti_erlie/article/details/122276188
猜你喜欢
- 本文实例讲述了Java泛型与数据库应用。分享给大家供大家参考,具体如下:一 点睛BaseDao定义了基本的数据库增删查改, 之后可以继承该泛
- 定义:动态给一个对象添加一些额外的职责,就象在墙上刷油漆.使用Decorator模式相比用生成子类方式达到功能的扩充显得更为灵活。设计初衷:
- 本文实例为大家分享了Java实现分页功能的具体代码,供大家参考,具体内容如下不用根据改变SQL的形式去查询; 直接查询所有的数据,根据页码自
- Map接口Map类似y(x)=x;这样的函数(key对应x,value对应y)Map与Collection并列存在。用于保存具有映射关系的数
- 1.jsch官方API查看地址(附件为需要的jar) http://www.jcraft.com/jsch/2.jsch简介 JSch(Ja
- 本文实例为大家分享了C++实现企业职工工资管理系统的具体代码,供大家参考,具体内容如下课程设计目的和要求工资管理要和人事管理相联系,生成企业
- 如图所示的效果相信大家都不陌生,我们可以使用很多种方法去实现此效果,这里自己采用CountDownTimer定时器简单封装下此效果,方便我们
- 本文介绍了SpringCloud +Zookeeper完成配置中心,分享给大家,具有如下:使用场景项目配置更改不需要打包,重启提供配置文件的
- spring Boot 熟悉后,集成一个外部扩展是一件很容易的事,集成Redis也很简单,看下面步骤配置:一、添加pom依赖
- 最近需要对接支付宝的支付接口,官方文档写得内容有点分散,整理了一下发布出来,用作记录,同时也希望对不了解情况的人有所帮助,这里以电脑端的网页
- 1.使用的是maven项目,添加依赖<!-- mybatis-plus begin --> <depend
- instanceof关键字用于判断一个引用类型变量所指向的对象是否是一个类(或接口、抽象类、父类)的实例。 举个例子:public
- 首先来看看以下程序将会打印出什么:class Dog { public static void bark
- 这篇文章主要介绍了JAVA基于SnakeYAML实现解析与序列化YAML,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考
- java中引用数据类型有哪些Java中有俩种数据类型,其中主要有8中基本数据类型和引用数据类型,除了8中基本数据类型以外都是引用数据类型,8
- 在本文中,我们将介绍一个非常有用的Spring功能,该功能允许我们基于一个或多个Spring注释创建自己的注释。假设我们有一组经常一起使用的
- 此解决方案是针对window的,因为日志默认保存路径在C盘,linux忽略。学习RocketMQ过程中,总是出现com.alibaba.ro
- 如何实现封装可以分为两步:第一步:将类的变量声明为private。第二步:提供公共set和get方法来修改和获取变量的值。代码展示publi
- 一、使用@Profile1.1、@Profile修饰类开发环境package com.example.demo.config;import
- 很多核心 Java 面试题来源于多线程(Multi-Threading)和集合框架(Collections Framework),理解核心线