coding++:Spring Boot全局事务解释及使用(一)
Spring 事务的入口:
TxAdviceBeanDefinitionParser 解释 <tx:advice/> 这里将解析tx的配置。 @Override protected Class<?> getBeanClass(Element element) { return TransactionInterceptor.class; }, 生成 TransactionInterceptor 对象, public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable 继承 TransactionAspectSupport 其中有个方法 invokeWithinTransaction() 特别重要:
invokeWithinTransaction():
//protected修饰,不允许其他包和无关类调用
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) throws Throwable {
// 获取对应事务属性.如果事务属性为空(则目标方法不存在事务)
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
// 根据事务的属性获取beanFactory中的PlatformTransactionManager(spring事务管理器的顶级接口),一般这里或者的是DataSourceTransactiuonManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
// 目标方法唯一标识(类.方法,如service.UserServiceImpl.save)
final String joinpointIdentification = methodIdentification(method, targetClass);
//如果txAttr为空或者tm 属于非CallbackPreferringPlatformTransactionManager,执行目标增强 ①
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//看是否有必要创建一个事务,根据事务传播行为,做出相应的判断
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
//回调方法执行,执行目标方法(原有的业务逻辑)
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 异常回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清除信息
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
//编程式事务处理(CallbackPreferringPlatformTransactionManager) 不做重点分析
else {
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
}); // Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
spring事务架构:
但是在此之前,必须要知道的是spring事务的架构定义。
spring 事物管理高层抽象主要包括3个接口:
PlatformTransactionManager(事务管理器)
TransactionDefinition(事物定义信息)
TransactionStatus(事物具体运行状态)。
1、PlatformTransactionManager
重点说说 DataSourceTransactionManager,是否大家还记得这个类,在以前没继承springboot快速开发的时候,这个就是我们配置的事务管理器。
首先这个类继承了抽象类 AbstractPlatformTransactionManager
这个类中,比较重要的是:
1):getTransaction()获取事务,在源码中是这样解释:
根据,返回当前活动的事务或创建一个新的事务指定的传播行为。
注意,隔离级别或超时等参数只会被应用用于新事务,因此在参与活动事务时将被忽略。
此外,不是所有的事务定义设置将被支持,每个事务管理器:一个正确的事务管理器实现.当遇到不支持的设置时,应该抛出异常。
上面规则的一个例外是只读标志,它应该是只读的.如果不支持显式只读模式,则忽略。本质上讲,只读标志只是潜在优化的一个提示。
2):commit(TransactionStatus status)方法,事务提交(回滚、提交):
其中遇到做多的坑,基本就是这个 Transaction rolled back because it has been marked as rollback-only
这个在方法命名时,需要注意方法命名规范(例如:查询就使用get,query等),以及在查询操作和更改操作的时候,抛异常时,需要特别注意事务的传播级别。
在方法 processCommit(defStatus);中有一个特别重要的代码:
主要的作用是无论成功与否都释放当前事务,以下是 DataSourceTransactionManager 的实现:
@Override
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; // Remove the connection holder from the thread, if exposed.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.unbindResource(this.dataSource);
} // Reset connection.
Connection con = txObject.getConnectionHolder().getConnection();
try {
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
}
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
} if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
}
DataSourceUtils.releaseConnection(con, this.dataSource);
} txObject.getConnectionHolder().clear();
}
2、Transactiondefinition事务传播行为:
spring 在 TransactionDefinition 接口中规定了7种类型的事务传播行为,它们规定了事务方法和事务方法发生嵌套调用时事务如何进行传播:
事务传播行为类型 事务传播行为类型 说明 PROPAGATION_REQUIRED 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
PROPAGATION_SUPPORTS 支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY 使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW 新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER 以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
3、TransactionStatus
coding++:Spring Boot全局事务解释及使用(一)的更多相关文章
- coding++:Spring Boot 全局事务解释及使用(二)
什么是全局事务: Spring Boot(Spring) 事务是通过 aop(aop相关术语:通知(Advice).连接点(Joinpoint).切入点(Pointcut).切面(Aspect).目标 ...
- spring boot入门
一.对spring boot的解释:(百度百科) Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化新Spring应用的初始搭建以及开发过程.该框架使用了特定的方式来进行 ...
- Spring Boot的学习之路(02):和你一起阅读Spring Boot官网
官网是我们学习的第一手资料,我们不能忽视它.却往往因为是英文版的,我们选择了逃避它,打开了又关闭. 我们平常开发学习中,很少去官网上看.也许学完以后,我们连官网长什么样子,都不是很清楚.所以,我们在开 ...
- 使用 CODING 进行 Spring Boot 项目的集成
本文作者:CODING 用户 - 高文 持续集成 (Continuous integration) 是一种软件开发实践,即团队开发成员经常集成他们的工作,通过每个成员每天至少集成一次,也就意味着每天可 ...
- Spring Boot + RabbitMQ 配置参数解释
最近生产RabbitMQ出了几次问题,所以抽时间整理了一份关于Spring Boot 整合RabbitMQ环境下的配置参数解释,通过官网文档和网上其他朋友一些文章参考归纳整理而得,有错误之处还请指正~ ...
- 1.spring boot起步之Hello World【从零开始学Spring Boot】
[视频&交流平台] àSpringBoot视频 http://study.163.com/course/introduction.htm?courseId=1004329008&utm ...
- (1)spring boot起步之Hello World【从零开始学Spring Boot】
Spring Boot交流平台 1.1 介绍 自从structs2出现上次的漏洞以后,对spring的关注度开始越来越浓. 以前spring开发需要配置一大堆的xml,后台spring加入了annot ...
- spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务
文章目录 一.综述 1.1 项目说明 1.2 项目结构 二.配置多数据源并支持分布式事务 2.1 导入基本依赖 2.2 在yml中配置多数据源信息 2.3 进行多数据源的配置 三.整合结果测试 3.1 ...
- 【微框架】之一:从零开始,轻松搞定SpringCloud微框架系列--开山篇(spring boot 小demo)
Spring顶级框架有众多,那么接下的篇幅,我将重点讲解SpringCloud微框架的实现 Spring 顶级项目,包含众多,我们重点学习一下,SpringCloud项目以及SpringBoot项目 ...
随机推荐
- 《Deep Learning of Graph Matching》论文阅读
1. 论文概述 论文首次将深度学习同图匹配(Graph matching)结合,设计了end-to-end网络去学习图匹配过程. 1.1 网络学习的目标(输出) 是两个图(Graph)之间的相似度矩阵 ...
- MySQL集群MGR架构for单主模式
本文转载自: https://www.93bok.com MGR简介 MySQL Group Replication(简称MGR)是MySQL官方于2016年12月推出的一个全新的高可用与高扩展的解决 ...
- 01 Taro_Mall 开源多端小程序框架设计
项目介绍 Taro_Mall是一款多端开源在线商城应用程序,后台是基于litemall基础上进行开发,前端采用Taro框架编写,现已全部完成小程序和h5移动端,后续会对APP,淘宝,头条,百度小程序进 ...
- 前端实现html转pdf方法总结
最近要搞前端html转pdf的功能.折腾了两天,略有所收,踩了一些坑,所以做些记录,为后来的兄弟做些提示,也算是回馈社区.经过一番调(sou)研(suo)发现html导出pdf一般有这几种方式,各有各 ...
- MacOS麦克风输入监听的方法
Windows上很多人都知道,然而实际上并没什么用——延迟太大,根本没法用. MacOS上有两种方法: QuickTime Player新建音频录制(不需要真的录音),如下图: 这个方法和Window ...
- webpack进阶(二)
1)webpack动态打包所有依赖项,避免打包未使用的模块. 2)转换css的loader有:css-loader,style-loader,加载图片或文件的loader是:file-loader,如 ...
- new Date在IOS下面的兼容问题
此问题坑爹啊,着实坑爹,要不是本宝宝鬼机灵再次进行了测试,不然测试都测不出来的问题,问题源头,有两个时间: let start = "2018-08-08 00:00:00" ; ...
- 一起了解 .Net Foundation 项目 No.18
.Net 基金会中包含有很多优秀的项目,今天就和笔者一起了解一下其中的一些优秀作品吧. 中文介绍 中文介绍内容翻译自英文介绍,主要采用意译.如与原文存在出入,请以原文为准. Protobuild Pr ...
- 手机抓包app在python中使用
使用python+airtesr+无线模式控制手机 官方文档中,在airtest.readthedocs.io/zh_CN/lates…有一段介绍如何连接安卓手机的例子: 但是这个线接模板,无线模式的 ...
- C++ 别踩白块小游戏练习
#include <iostream> #include <stdio.h> #include <stdlib.h> #include <easyx.h> ...