`

spring的事务处理详解[原blog转载]

 
阅读更多

spring的事务处理详解[原blog转载]
注:此文为原blog转载过来,原文见:http://blog.sina.com.cn/sylilzy

sylilzy@163.com 施祖阳 http://hi.baidu.com/sylilzy
2008-6-16 11:47:16 星期一

spring的事务处理详解:调用一个方法后的事务处理过程

spring调用一个方法后的事务处理过程:
请参照TransactionInterceptor的invoke方法:
try {
// This is an around advice.
// Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceed();
}
catch (Throwable ex) {
// target invocation exception
doCloseTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
doFinally(txInfo);
}
doCommitTransactionAfterReturning(txInfo);
return retVal;
}

调用目标方法时没有抛出异常时会调用:
doCommitTransactionAfterReturning(txInfo);
然后直接提交事务

如果抛异常则检查是否需要回滚事务(doCloseTransactionAfterThrowing方法会根据在spring中设备的Transaction Attribute),否则提交事务.

--------------------------------------

spring的事务处理详解:调用一个方法前的事务处理过程(源代码分析)


实际上,在spring的事务中,只要该类被设置为了事务代理:

拦截器都会创建一个TransactionInfo 对象:

TransactionInfo txInfo = new TransactionInfo(txAttr, method);


而且如果只要被调用的方法设置了事务属性(txAttr),不管是什么属性都会调用:

txInfo.newTransactionStatus(this.transactionManager.getTransaction(txAttr));

根据该方法的事务属性(definition )的不同,this.transactionManager.getTransaction(txAttr)的返回值会有所不同(代码见 AbstractPlatformTransactionManager),具体为以下几种情况:
1.当前没有事务时(即以下代码中的((HibernateTransactionObject) transaction).hasTransaction()返回false),会返回以下几种:

// Check definition settings for new transaction.
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}

// No existing transaction found -> check propagation behavior to find out how to behave.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"Transaction propagation 'mandatory' but no existing transaction found");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]");
}
doBegin(transaction, definition);
boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);
}

2.当前有事务时
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Transaction propagation 'never' but existing transaction found");
}

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
Object suspendedResources = suspend(transaction);
boolean newSynchronization = (this.transactionSynchronization == SYNCHRONIZATION_ALWAYS);
return newTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
Object suspendedResources = suspend(transaction);
doBegin(transaction, definition);
boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
return newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
}

if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
newTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
doBegin(transaction, definition);
boolean newSynchronization = (this.transactionSynchronization != SYNCHRONIZATION_NEVER);
return newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, null);
}
}

最后,txInfo被绑定到当前线程上作为当前事务:

txInfo.bindToThread()

然后,调用实际的目标类的方法并捕捉异常:

try {
// This is an around advice.
// Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceed();
}
catch (Throwable ex) {
// target invocation exception
doCloseTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
doFinally(txInfo);
}
doCommitTransactionAfterReturning(txInfo);
return retVal;
}


另外一点,TransactionInfo的newTransactionStatus调用时如果参数的不是null,TransactionInfo.hasTransaction()方法返回true;

重要提示:
在spring中创建的事务代理类并是目标类的超类,只是一个实现这目标类接口的类,该类会调用目标类的方法,所在如果一个目标类中的方法调用自身的另一个事务方法,另一个方法只是作为普通方法来调用,并不会加入事务机制
--------------------------------------------------------------------------------


spring的事务处理详解:事务创建


在配置spring的事务处理时,无论使用TransactionProxyFactoryBean,还是使用BeanNameAutoProxyCreator
spring的事务处理都是主要由TransactionInterceptor来拦截完成,此类扩展自org.aopalliance.intercept.MethodInterceptor,要查看spring的事务处理过程,首先要了解
TransactionInterceptor类的执行过程:


1.事务拦截器拦截调用方法:invoke();
2.调用TransactionAspectSupport的createTransactionIfNecessary,


createTransactionIfNecessary中:
首先创建TransactionInfo对象,然后
如果被调用的方法设置了事务属性(不管是什么属性,只要设置了),输出日志:

TransactionInterceptor 221 - Getting transaction for ...

并调用TransactionManager.getTransaction方法,

如果被调用的方法设置未设备事务,输出:Don't need to create transaction for ...

调用返回后然后将事务绑定到当前线程.createTransactionIfNecessary方法返回.

3.调用目标类的方法,并依次完成其它拦截器的调用
4.如果在上一步操作中有异常抛出,则会处理异常,处理过程:根据配置决定是提交还是回滚事务
5.如无异常,调用doFinally()将上一个事务(旧事务)设置为当前事务
4.调用doCommitTransactionAfterReturning提交事务,此为最重要的一步,与事务相关的操作在此实际生效.

调用TransactionManager.getTransaction过程 :
1.调用doGetTransaction()查找事务(此对象并不代表一个事务已经存在),返回的对象中包含事务的相关信息:如事务是否开始等.此对象将在以后作为doBegin and doCommit等方法的参数.

2.输出日志:
Using transaction object...
如:
HibernateTransactionManager 254 - Using transaction object...

3.调用isExistingTransaction(...)检查事务是否存在(是否已经开始一个事务),此方法为abstract方法,需要concreate类来实现,例如hibernate

4.如果isExistingTransaction为true,
如果是PROPAGATION_NEVER,则抛异常
PROPAGATION_NOT_SUPPORTED,则suspend当前事务并返回
PROPAGATION_REQUIRES_NEW,则suspend后创建一个新事务,
其它则
输出日志:"Participating in existing transaction"
然后
处理完后返回一个TransactionStatus对象,包含是否为新transaction,是否为新的newSynchronization,suspendedResources等,getTransaction()同时也返回

5.如果isExistingTransaction为false
检查超时是否小于默认时间,如果是则抛异常
如果当前方法的事务属性为PROPAGATION_MANDATORY,则抛异常,否则
如果当前方法的事务属性为PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED
输出日志:"Creating new transaction with name ..."
调用doBegin(...)创建并开始一个事务,然后返回
否则返回的return newTransactionStatus(definition, null, false, newSynchronization, debugEnabled, null);

--------------------------------------------------------------------------------

参考资料:
1.Spring Reference Manual:http://static.springframework.org/spring/docs/1.2.x/reference/index.html
2.Spring API doc:http://static.springframework.org/spring/docs/1.2.x/api/index.html

--------------------------------------------------------------------------------

作者简介:
施祖阳,网名sylilzy,1979年生。
2002年起从事软件开发工作,主要研究为JAVA、Linux及相关技术。
你可通过sylilzy@163.com 与作者联系。

分享到:
评论

相关推荐

    SSM整合,参考尚硅谷视频,转载笔记,非原创,侵权删

    "SSM整合,参考尚硅谷视频"提到的学习资源可能包括一系列的视频教程,这些教程通常会逐步指导开发者如何从零开始搭建SSM项目,涵盖环境配置、项目结构设计、配置文件详解、异常处理、单元测试等多个方面。...

    Java面试题

    对于【JAVA面试常被问到的题目[转载+解答] - Moon Face - 博客园.png】这个文件,通常它可能包含了一篇博客文章的截图,其中详细解答了一些Java面试题。如果能够查看这个文件,你将得到更具体的答案和解析,帮助你在...

    信通商务网2025修正版

    中国电子商务平台,打造中国最具影响力的企业电子商务平台,商机信息,产品资料,企业名录,行业展览会,商务新闻。

    经典文学作品阅读体验.doc

    经典文学作品阅读体验

    python-30.判断 2 的幂-反正你没它快.py

    python-30.判断 2 的幂——反正你没它快.py

    基于随机森林实现特征选择降维及回归预测 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    元胞自动机模拟病毒传染(SEIR模型) 附Python代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    2004-2020年各省货运量数据

    2004-2020年各省货运量数据 1、时间:2004-2020年 2、来源:国家统计j、统计nj 3、指标:行政区划代码、地区、年份、货运量(万吨) 4、范围:31省

    ADC推理软件AI程序

    ADC推理软件AI程序

    【轴承故障检测】滚动轴承中进行基于振动的故障诊断研究 附Matlab代码.rar

    1.版本:matlab2014/2019a/2024a 2.附赠案例数据可直接运行matlab程序。 3.代码特点:参数化编程、参数可方便更改、代码编程思路清晰、注释明细。 4.适用对象:计算机,电子信息工程、数学等专业的大学生课程设计、期末大作业和毕业设计。

    java-springboot+vue景区民宿预约系统实现源码(完整前后端+mysql+说明文档+LunW+PPT).zip

    java-springboot+vue景区民宿预约系统实现源码(完整前后端+mysql+说明文档+LunW+PPT).zip

    漫画作品与增强现实体验.doc

    漫画作品与增强现实体验

    漫画作品改编舞台剧经验.doc

    漫画作品改编舞台剧经验

    ,,ABC-DQ:基于MATLAB Simulink的三相静止坐标系到两相静止坐标系(Clark变)到两相旋转坐标系变(Park变)的仿真模型 仿真条件:MATLAB Simulink R2015b

    ,,ABC_DQ:基于MATLAB Simulink的三相静止坐标系到两相静止坐标系(Clark变)到两相旋转坐标系变(Park变)的仿真模型。 仿真条件:MATLAB Simulink R2015b ,MATLAB Simulink;三相静止坐标系;两相静止坐标系;Clark变换;Park变换;仿真模型;R2015b,MATLAB Simulink中的Clark-Park变换仿真模型研究

    武汉东湖高新集团智慧园区 22页PPT(21页).pptx

    在智慧城市建设的大潮中,智慧园区作为其中的璀璨明珠,正以其独特的魅力引领着产业园区的新一轮变革。想象一下,一个集绿色、高端、智能、创新于一体的未来园区,它不仅融合了科技研发、商业居住、办公文创等多种功能,更通过深度应用信息技术,实现了从传统到智慧的华丽转身。 智慧园区通过“四化”建设——即园区运营精细化、园区体验智能化、园区服务专业化和园区设施信息化,彻底颠覆了传统园区的管理模式。在这里,基础设施的数据收集与分析让管理变得更加主动和高效,从温湿度监控到烟雾报警,从消防水箱液位监测到消防栓防盗水装置,每一处细节都彰显着智能的力量。而远程抄表、空调和变配电的智能化管控,更是在节能降耗的同时,极大地提升了园区的运维效率。更令人兴奋的是,通过智慧监控、人流统计和自动访客系统等高科技手段,园区的安全防范能力得到了质的飞跃,让每一位入驻企业和个人都能享受到“拎包入住”般的便捷与安心。 更令人瞩目的是,智慧园区还构建了集信息服务、企业服务、物业服务于一体的综合服务体系。无论是通过园区门户进行信息查询、投诉反馈,还是享受便捷的电商服务、法律咨询和融资支持,亦或是利用云ERP和云OA系统提升企业的管理水平和运营效率,智慧园区都以其全面、专业、高效的服务,为企业的发展插上了腾飞的翅膀。而这一切的背后,是大数据、云计算、人工智能等前沿技术的深度融合与应用,它们如同智慧的大脑,让园区的管理和服务变得更加聪明、更加贴心。走进智慧园区,就像踏入了一个充满无限可能的未来世界,这里不仅有科技的魅力,更有生活的温度,让人不禁对未来充满了无限的憧憬与期待。

    自驾游中行程时间灵活调整.doc

    自驾游中行程时间灵活调整

    ,,基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样 之后基于抽样序列进行概率潮流计算 最后得到电网的电压概率出力曲线 程序

    ,,基于蒙特卡洛法的概率潮流 以IEEE33节点的电网为研究对象 建立了光伏和风电的概率出力模型 采用蒙特卡洛法进行随机抽样 之后基于抽样序列进行概率潮流计算 最后得到电网的电压概率出力曲线 程序有基于matpower和非matpower(效果好一点) ,核心关键词:蒙特卡洛法; 概率潮流; IEEE33节点电网; 光伏风电概率出力模型; 随机抽样; 电压概率出力曲线; matpower; 非matpower方法。,基于蒙特卡洛法的电网概率潮流分析:IEEE33节点光伏风电模型构建与验证

    基于视觉检测的机械臂药品自动分类与搬运仿真系统实现与优化(含详细可运行代码及解释)

    内容概要:本文详细介绍了基于视觉检测的机械臂药品自动分类与搬运仿真的实现方法。首先通过搭建环境和加载相关模型,接着利用 OpenCV 对摄像头捕获的画面进行药瓶识别,再通过 PyBullet 实现机械臂路径规划及其动作控制,最后通过主循环不断地完成对药物的分类抓取操作。为增强系统性能和稳定性进行了多项改进:采用先进的YOLOv8模型实现更精准的物体检测、增加更细致的夹爪开合逻辑提高物品抓取的成功率,同时加入碰撞检测机制保障运动过程的安全性。该仿真是用Python编程语言开发,并涉及多领域的技术集成。 适用人群:适用于自动化设备研究开发的技术专家或从事机器人相关专业学习的研究人员。 使用场景及目标:可用于研究自动化药房、医院仓库管理等医疗物资自动处理流程的设计;帮助理解并实践如何构建一个完整的机器人视觉引导下的机械手作业体系,以及针对具体应用场景提出有效的改进建议和技术路线图。 其他说明:为了使系统更接近真实环境,开发者还可以继续探索更多先进的机器视觉算法,并深入探讨机械臂硬件层面的选择,以期打造出更加智能化的产品应用于各行各业。

    初识Python-公共课-pdf.zip

    初识Python-公共课-pdf.zip

    Anaconda 2023 State of Data Science Report.pdf

    anaconda

Global site tag (gtag.js) - Google Analytics