Spring AOP原理分析介绍了AOP的一些细节,有了这篇文章的基础,我们再来分析Spring中声明式事务的实现就能够轻车熟路一些。
一些概念
事务可以分为2种,全局事务与本地事务。
全局事务可以保证多数据源下的事务特性(关于事务的ACID特性这里不详说),本地事务则可以保证单个数据源下的事务特性。全局事务使用JTA,支持多事务源事务(通过XA协议来支持,然而XA性能较低,一般都会采取别的分布式事务方案,比如事务消息,补偿方案等);本地事务则基于JDBC连接,不支持分布式事务。
事务管理器
Spring使用事务管理器来管理事务,下面的接口是Spring事务管理器的统一抽象接口,我们可以根据需要实现自己的事务管理器。Spring提供了许多事务平台默认的实现,比如基于JDBC的DataSourceTransactionManager,基于JTA的JtaTransactionManager,基于Hibernate的HibernateTransactionManager等。
其中getTransaction(..)方法根据TransactionDefinition参数返回一个TransactionStatus对象。如果当前调用堆栈中存在匹配的事务,则返回的TransactionStatus可能表示一个新事务,也可能表示一个现有事务,由TransactionDefinition来决定。
TransactionDefinitionTransactionDefinition定义了很多常量,代表着不同的含义
以Propagation开头的代表传播行为:在事务范围内执行的所有代码都在该事务中运行,但是,如果事务方法在事务上下文已经存在时执行,则可以指定行为。例如,代码可以在现有事务中继续运行(通常情况下),或者可以挂起现有事务并创建一个新事务
以Isolation开头的代表隔离程度:即事务的隔离级别
getTimeout方法:获取事务的超时时间
isReadOnly方法(只读状态):是否为只读状态
getPropagationBehavior方法:获取传播行为
getIsolationLevel:获取隔离程度
传播行为与隔离级别
由接口中的常量可知,共有7种传播行为,分别为:
REQUIRED:如果当前范围不存在事务,则新建一个事务(默认)
REQUIRES_NEW:总是新建一个事务。
NESTED:如果当前有事务,则在嵌套事务内执行,如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。仅适用于JDBC事务,本质上是根据JDBC回滚点回滚指定范围内的操作,NESTED和REQUIRES_NEW都可以做到内部方法事务回滚而不影响外围方法事务。但是因为NESTED是嵌套事务,所以外围方法回滚之后,作为外围方法事务的子事务也会被回滚。而REQUIRES_NEW是通过开启新的事务实现的,内部事务和外围事务是两个事务,外围事务回滚不会影响内部事务。
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:使用当前的事务,如果当前没有事务,就抛出异常。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
一般情况下我们使用默认的传播行为即可。
隔离级别对应的就是数据库的隔离级别,其中有个DEFAULT,代表着默认的隔离级别,他是跟着底层数据库变化的,例如如果是MySQL的话,那么默认的隔离级别就是可重复读。
声明式事务
Spring中事务管理分为编程式事务与声明式事务,Spring官方建议使用声明式事务进行事务管理,对代码侵入性较小。
声明式事务执行流程回滚:默认情况下,Spring只对RunTimeException与Error类型的异常进行回滚,我们也可以指定发生某些异常不会滚或者发生某些异常回滚
声明式事务使用@Transactional来实现,由于Spring中事务由代理实现,所以AOP的问题事务管理同样会有:应该只将@Transactional应用于public方法。如果使用@Transactional注释private,事务并不会生效。在代理模式(这是缺省模式)中,只拦截通过代理传入的外部方法调用。这意味着自调用(实际上,目标对象中的一个方法调用目标对象的另一个方法)不会在运行时执行事务,即使被调用的方法被标记为@Transactional。
源码分析
同Spring AOP一文的分析类似,开启事务的注解为@EnableTransactionManagement,从该注解开始分析。
如果是代理模式(默认)则导入AutoProxyRegistrar与ProxyTransactionManagementConfiguration俩个组件。
AutoProxyRegistrar类中最终注册了InfrastructureAdvisorAutoProxyCreator。
InfrastructureAdvisorAutoProxyCreator是一个后置处理器,我们找到后置处理器相关的接口,在对象创建以后,将对象包装成代理对象返回
ProxyTransactionManagementConfiguration类注册了BeanFactoryTransactionAttributeSourceAdvisor与AnnotationTransactionAttributeSource
AnnotationTransactionAttributeSource中的各种TransactionAnnotationParser负责解析事务相应的注解。
另一个bean为TransactionInterceptor事务拦截器,其中保存了事务的属性与事务管理器
找到动态代理相关的实现类,查看invoke方法
接上图如果是事务方法则会进入到createTransactionIfNecessary方法开始一个事务,invocation.proceedWithInvocation();执行方法中操作。
如果发生异常则调用completeTransactionAfterThrowing(txInfo, ex);
判断注解中是否指定了回滚的异常,根据异常做相应的回滚操作
最后调用commitTransactionAfterReturning(txInfo);进行事务的提交。
总结:找到被事务注解注释的相关bean,为bean生成代理对象,在对象方法执行时执行代理对象的invoke方法,做相应的事务操作。总体流程和AOP是一样的。
网友评论