本文以申明式事务为例,开始下探,分析spring事务的源码结构,再以mybatis为例,分析spring事务是如何作用于ORM的。
首先看看spring的配置文件,简而言之,TransactionAttributeSourceAdvisor采用AOP方式,将事务transactionInterceptor织入注解的特定的方法上
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"> <property name="transactionInterceptor"><ref bean="transactionInterceptor"/></property> </bean> <bean id="transactionInterceptor" class="com.CustomerTransactionInterceptor"> <constructor-arg name="ptm" ref="shardingTransactionManager"></constructor-arg> <constructor-arg name="tas" ref="transactionAttributeSource"></constructor-arg> </bean> <bean id="customerSpringTransactionAnnotationParser" class="com.CustomerSpringTransactionAnnotationParser"> <constructor-arg name="transactionManagerSpringBeanId"> <value>shardingTransactionManager</value> </constructor-arg> </bean> <bean id="transactionAttributeSource" class="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"> <constructor-arg name="annotationParser" ref="customerSpringTransactionAnnotationParser"></constructor-arg> </bean>
那实际上,transactionInterceptor是实际调用shardingTransactionManager入口,它的父类TransactionAspectSupport封装了操作事务的具体代码
public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
最终,在这个类里,我们找到了核心的事务操作代码,很清晰的,几步
1. 从属性中获取事务属性配置,从BeanFactory中去除TransactionManager
2. 开启事务,createTransactionIfNecessary
3. 执行业务方法
4. 遇错回滚,completeTransactionAfterThrowing方法判断,该Exception类型是否回滚,不回滚执行提交
5. 清理事务信息,cleanupTransactionInfo将当前TransactionInfo设置为old
6. 提交,commitTransactionAfterReturning执行提交
protected Object invokeWithinTransaction(Method method, Class targetClass, final InvocationCallback invocation)
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); final PlatformTransactionManager tm = determineTransactionManager(txAttr); final String joinpointIdentification = methodIdentification(method, targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); Object retVal = null; 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.proceedWithInvocation(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo); return retVal; }
事务的外围展现就是这么简单,内部的处理的复杂性主要有以下几点
1. 由于拦截事务是嵌套的,所以产生了以上6步执行的嵌套问题,这就产生了事务的传播特性
2. 底层数据库的不同,数据库驱动程序不同,产生了事务的兼容性问题
3. ORM框架百花齐放,如何能和spring事务无缝整合,也是一个棘手的问题
接下来我们先以JDBC事务为例进行说明
先看xml文件的配置,可以知道JDBC的事务管理器为DataSourceTransactionManager
<!-- Sharding start --> <bean id="shardingTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="shardingDataSource" /> </bean>首先,我们先看Spring是如何兼容JDBC驱动的事务的
DataSourceTransactionManager和JDBC事务的具体封装在spring-jdbc-xxx.jar中,DataSourceTransactionManager的父类AbstractPlatformTransactionManager在spring-tx-xxx.jar中,其中后者为spring对事务的抽象层,前者是JDBC事务的具体实现。代码中设计底层的交给DataSourceTransactionManager子类实现,AbstractPlatformTransactionManager封装上层接口,事务的调用都走上层接口。
接下来我们从上面的六步着手,逐层下探
1. 事务的创建,方法的调用流程如下
TransactionAspectSupport.createTransactionIfNecessary->AbstractPlatformTransactionManager.getTransaction->DataSourceTransactionManager.*
AbstractPlatformTransactionManager.getTransaction方法
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { //调用DataSourceTransactionManager获得transaction句柄对象 Object transaction = doGetTransaction(); //如果事务存在,根据事务的传播类型,进行对应的处理 if (isExistingTransaction(transaction)) { return handleExistingTransaction(definition, transaction, debugEnabled); } //以前不存在事务,doBegin启动事务 else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { doBegin(transaction, definition);
相关推荐
《互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析》以SSM 的核心代码剖析为基础,突破Java Web 研发瓶颈的束缚,选取Spring、SpringMVC 和MyBatis 框架中易于理解的版本,深入剖析了其中各个...
《互联网轻量级SSM框架解密:Spring、Spring MVC、MyBatis源码深度剖析》以SSM 的核心代码剖析为基础,突破Java Web 研发瓶颈的束缚,选取Spring、SpringMVC 和MyBatis 框架中易于理解的版本,深入剖析了其中各个...
第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有云遮雾罩的感觉。 第11章:讲解了如何使用Spring JDBC进行数据访问操作,我们还重点讲述了LOB字段处理、主键产生...
第10章:对实际应用中Spring事务管理各种疑难问题进行透彻的剖析,让读者对Spring事务管理不再有云遮雾罩的感觉。 第11章:讲解了如何使用Spring JDBC进行数据访问操作,我们还重点讲述了LOB字段处理、主键产生...
此外,该项目还附带了详细的毕业论文,从理论到实践,深入剖析了系统的设计和开发过程,对于学习SSM框架和Vue.js开发的同学来说,具有很高的参考价值。 该资源包的提供,为想要进行二次开发或定制的企业或个人提供...
《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》:资深程序员全力打造,深入剖析SSH框架整合开发的精髓 全方位解读Java Web开发的基础知识、高级技术及应用案例 内容全面,讲解详细,全面覆盖...
《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》特别介绍了Struts 2对AjAX的支持,还重点剖析了SSH框架的整合开发,并给出了两个综合案例来展示整合SSH框架开发Web应用。 和已经出版的同类图书...
《Java Web开发技术大全:JSP+Servlet+Struts+Hibernate+Spring+Ajax》特别介绍了Struts 2对AjAX的支持,还重点剖析了SSH框架的整合开发,并给出了两个综合案例来展示整合SSH框架开发Web应用。 和已经出版的同类图书...
│ Java面试题54.Spring事务的传播特性和隔离级别.mp4 │ Java面试题55.ORM是什么?ORM框架是什么?.mp4 │ Java面试题56.ibatis和hibernate有什么不同.mp4 │ Java面试题57.hibernate对象状态及其转换.mp4 │ Java...
该项目旨在通过实践应用,帮助学生深入理解分布式架构的原理和实现,掌握Spring Boot框架的开发技能,提升软件开发能力。 该项目采用了先进的分布式架构,通过微服务、容器化、负载均衡等技术手段,实现了商城系统...
Spring技术 Spring Ioc基础、Ioc注入技巧、对象高级装配(自动装配、模板装配、组件扫描特性、FactoryBean、对象生命周期)、Spring AOP原理、AspectJ、Spring JDBC支持、Spring事务及安全管理;Spring整合Hibernate...
分布式事务解决方案实战 高并发下的服务降级、限流实战 基于分布式架构下分布式锁的解决方案实战 分布式架构实现分布式定时调度 分布式架构-中间件 分布式消息通信 消息中间件在分布式架构中的应用 ActiveMQ...
深入剖析ASP.NET组件设计]一书第三章关于ASP.NET运行原理讲述的补白 asp.net 运行机制初探(httpModule加载) 利用反射来查看对象中的私有变量 关于反射中创建类型实例的两种方法 ASP.Net应用程序的多进程模型 NET委托...