对大多数Java开发者来讲,Spring事务管理是Spring应用中最经常使用的功能,使用也比较简单。本文主要从三个方面(基本概述、基于源码的原理分析以及须要注意的细节)来逐步介绍Spring事务管理的相关知识点及原理,做为Spring事务管理的学习总结。html
ANSI/ISO SQL92标准定义了4个隔离级别:READ UNCOMMITED、READ COMMITED、REPEATABLE READ和SERIALIZABLE,隔离程度由弱到强。不一样的事务隔离级别可以解决数据并发问题的能力不一样,它与数据库并发性是对立的,二者此消彼长。java
事务传播主要是为了描述两个服务接口方法嵌套调用时,被调用者在调用者有无事务时所采起的事务行为。Spring框架在TransactionDefinition接口中固定了7种事务传播行为:PROPAGATION_REQUIRED、 PROPAGATION_SUPPORTS、 PROPAGATION_MANDATORY、 PROPAGATION_REQUIRES_NEW、 PROPAGATION_NOT_SUPPORTED、 PROPAGATION_NEVER、 PROPAGATION_NESTED。前面的6种是从EJB中引入的,而PROPAGATION_NESTED是Spring特有的。具体可参见深刻浅出事务(4):Spring事务的传播行为,该文结合具体代码示例,通俗易懂。spring
TransactionSynchronizationManager——事务管理的基石,主要是为了解决事务管理在多线程环境下资源(如Connection、Session等)的并发访问问题:使用ThreadLocal为不一样事务线程维护独立的资源副本,以及事务配置属性和运行状态信息,使各个事务线程互不影响。数据库
SPI(Service Provider Interface)是一个框架开放给第三方的可扩展服务接口,供其具体实现,以支持框架的扩展性和插件式组件。Spring事务管理SPI主要包括3个接口:PlatformTransactionManager(进行事务的建立、提交或回滚)、TransactionDefinition(定义事务属性,如隔离级别)和TransactionStatus(事务运行时状态,如是否已完成)。这三者经过PlatformTransactionManager的以下接口进行关联:express
// 根据事务定义建立事务,并由TransactionStatus表示它 TransactionStatus getTransaction(TransactionDefinition definition); // 根据事务运行时状态提交或回滚事务 void commit(TransactionStatus status); void rollback(TransactionStatus status);
三种方式:编程、XML配置和注解。第一方式对应用代码侵入性较大,现已较少使用。后面两种则都属于声明式事务管理的方式,二者的共同点是都提供事务管理信息的元数据,只不过方式不一样。前者对代码的侵入性最小,也最为经常使用,后者则属于较为折衷的方案,有一点侵入性,但相对也较少了配置,各有优劣,依场景需求而定。声明式事务管理是Spring的一大亮点,利用AOP技术将事务管理做为切面动态织入到目标业务方法中,让事务管理简单易行。编程
而不论是使用哪一种方式,数据源、事务管理器都是必须的,通常经过XML的Bean配置:api
... <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destory-method="close"> <property name="driverClass"><value>${jdbc.driverClass}</value></property> <property name="jdbcUrl"><value>${jdbc.jdbcUrl}</value></property> <property name="user"><value>${jdbc.username}</value></property> <property name="password"><value>${jdbc.password}</value></property> <property name="maxPoolSize"><value>${jdbc.maxPoolSize}</value></property> <property name="minPoolSize"><value>${jdbc.minPoolSize}</value></property> <property name="initialPoolSize"><value>${initialPoolSize}</value></property> </bean> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource"> <ref local="dataSource" /> </property> <!-- 指定事务管理器标识,可被@Transactional注解引用 --> <qualifier value="txManagerA" /> </bean> ...
采用与DAO模板类同样的开闭思想,Spring提供了线程安全的TransactionTemplate模板类来处理不变的事务管理逻辑,将变化的部分抽象为回调接口TransactionCallback供用户自定义数据访问逻辑。使用示例:安全
public class ServiceAImpl { private DaoA daoA; @autowried private TransactionTemplate template; public void addElement(final Element ele) { template.execute(new TransactionCallbackWithoutResult() { protected void doInTransactionWithoutResult(TransactionStatus status){ daoA.addElement(ele); } }); } }
TransactionTemplate的配置信息:多线程
... <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager"> <ref local="txManager" /> </property> <property name="isolationLevelName" value="ISOLATION_DEFAULT" /> <property name="propagationBehaviorName" value="PROPAGATION_REQUIRED" /> </bean> ...
固然,用户也能够不使用TransactionTemplate,而是直接基于原始的Spring事务管理SPI进行编程式事务管理,只不过这种方式对代码侵入性最大,不推荐使用,这里也就很少作介绍了。并发
Spring早期版本,是经过TransactionProxyFactoryBean代理类实施声明式事务配置,因为这种方式的种种弊端,后来引入AOP切面描述语言后,提出一种更简洁的基于Schema的配置方式:tx/aop命名空间,使声明式事务配置更简洁便利。
... <bean id="serviceATarget" class="org.sherlocky.book.spring3x.service.ServiceAImpl" /> <bean id="serviceA" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" p:transactionManager-ref="txManager" p:target-ref="serviceATarget"> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="*">PROPAGATION_REQUIRED</prop> </props> </property> </bean> ...
... <tx:advice id="txAdvice" transaction-manager="txManager"> <tx:attributes> <tx:method name="create*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" /> <tx:method name="delete*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" /> <tx:method name="update*" propagation="REQUIRED" timeout="300" rollback-for="java.lang.Exception" /> <tx:method name="get*" propagation="REQUIRED" read-only="true" timeout="300" /> <tx:method name="*" propagation="REQUIRED" read-only="true" timeout="300" /> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* org.sherlocky.book.spring3x.service.*ServiceA.*(..))" /> <aop:advisor pointcut-ref="txPointcut" advice-ref="txAdvice" /> </aop:config>
经过**@Transactional对须要事务加强的Bean接口、实现类或方法进行标注,在容器中配置tx:annotation-driven**以启用基于注解的声明式事务。注解所提供的事务属性信息与XML配置中的事务信息基本一致,只不过是另外一种形式的元数据而已。使用示例:
@Transactional("txManagerA") public class ServiceAImpl { private DaoA daoA; public void addElement(final Element ele) { ... } }
源码分析必定要有目的性,至少有一条清晰的主线,好比要搞清楚框架的某一个功能点背后的代码组织,来龙去脉,而不是一头扎进源码里,无的放矢。本文就从Spring事务管理的三种使用方式入手,逐个分析Spring在背后都为咱们作了些什么。
TransactionTemplate是编程式事务管理的入口,源码以下:
public class TransactionTemplate extends DefaultTransactionDefinition implements TransactionOperations, InitializingBean { private PlatformTransactionManager transactionManager; ... public <T> T execute(TransactionCallback<T> action) throws TransactionException { if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) { return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);【1】 } else { TransactionStatus status = this.transactionManager.getTransaction(this);【2】 T result; try { result = action.doInTransaction(status); } catch (RuntimeException ex) {【3】 // Transactional code threw application exception -> rollback rollbackOnException(status, ex); throw ex; } catch (Error err) {【4】 // Transactional code threw error -> rollback rollbackOnException(status, err); throw err; } catch (Exception ex) {【5】 // Transactional code threw unexpected exception -> rollback rollbackOnException(status, ex); throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception"); } this.transactionManager.commit(status); return result; } } }
TransactionTemplate提供了惟一的编程入口execute,它接受用于封装业务逻辑的TransactionCallback接口的实例,返回用户自定义的事务操做结果T。具体逻辑:先是判断transactionManager是不是接口CallbackPreferringPlatformTransactionManager的实例,如果则直接委托给该接口的execute方法进行事务管理;不然交给它的核心成员PlatformTransactionManager进行事务的建立、提交或回滚操做。
CallbackPreferringPlatformTransactionManger接口扩展自PlatformTransactionManger,根据如下的官方源码注释可知,该接口至关因而把事务的建立、提交和回滚操做都封装起来了,用户只须要传入TransactionCallback接口实例便可,而不是像使用PlatformTransactionManger接口那样,还须要用户本身显示调用getTransaction、rollback或commit进行事务管理。
// Implementors of this interface automatically express a preference for // callbacks over programmatic getTransaction, commit and rollback calls. interface CallbackPreferringPlatformTransactionManager extends PlatformTransactionManager{...}
能够看到transactionTemplate直接扩展自DefaultTransactionDefinition,让自身具备默认事务定义功能,【1】和【2】处将this做为execute或getTransaction的实参传入,说明该事务管理是采用默认的事务配置,能够看下DefaultTransactionDefinition中定义的默认配置:
... private int propagationBehavior = PROPAGATION_REQUIRED; //经常使用选择:当前没有事务,则新建;不然加入到该事务中 private int isolationLevel = ISOLATION_DEFAULT; //使用数据库默认的隔离级别 private int timeout = TIMEOUT_DEFAULT; //-1,使用数据库的超时设置 private boolean readOnly = false; //非只读事务
而TransactionOperations和InitializingBean接口分别定义了以下单个方法。InitializingBean是Spring在初始化所管理的Bean时经常使用的接口,以确保某些属性被正确的设置或作一些初始化时的后处理操做,可参考InitializingBean的做用。
<T> T execute(TransactionCallback<T> action); //TransactionTemplate的编程接口 void afterPropertiesSet(); //Bean初始化时调用:在成员变量装配以后
TransactionTemplate实现InitializingBean接口,主要是确保其核心成员transactionManager是否已初始化:
public void afterPropertiesSet() { if (this.transactionManager == null) { throw new IllegalArgumentException("Property 'transactionManager' is required"); } }
从【3】【4】【5】可看出,基于TransactionTemplate的事务管理,在发生RuntimeException、Error或Exception时都会回滚,正常时才提交事务。
该接口在Spring事务管理中扮演着重要角色。看下getTransaction的源码注释:
// Return a currently active transaction or create a new one, according to // the specified propagation behavior.
该方法的主要做用就是根据TransactionDefinition返回当前有效事务或新建事务,其中就包含了事务传播行为的控制逻辑。其惟一实现就是该接口对应的抽象类AbstractPlatformTransactionManager,这是典型的接口->抽象类->具体实现类三层结构,以提升代码复用性。其中抽象类是负责实现一些共有逻辑,而具体子类则是各自实现差别化功能:
// 声明为final,确保不能再被子类重写 public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); ... if (isExistingTransaction(transaction)) {【1】 return handleExistingTransaction(definition, transaction, debugEnabled); } ... if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY){ throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null);【2】 ... try { ... } catch (RuntimeException ex) { resume(null, suspendedResources);【3】 throw ex; } catch (Error err) { resume(null, suspendedResources); throw err; } } else { boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null); } }
能够看到它会根据【1】处的isExistingTransaction方法判断当前是否有事务而分别做出不一样的处理,包括挂起和恢复当前事务等,有兴趣的童鞋能够深刻【2】处的supend和【3】处的resume方法,会发现对事务的挂起和恢复操做实际是委托于TransactionSynchronizationManager来作的,而该类在前面也提过到,是Spring管理事务资源的,这几个重要接口和类的关系渐渐清晰了,因为篇幅有限,后面打算单独另起一篇细讲。
基于XML和注解的方式都是属于声明式事务管理,只是提供元数据的形式不用,索性就一块儿讲了。声明式事务的核心实现就是利用AOP技术,将事务逻辑做为环绕加强MethodInterceptor动态织入目标业务方法中。其中的核心类为TransactionInterceptor。从如下代码注释可知,TransactionInterceptor是专用于声明式事务管理的。
// AOP Alliance MethodInterceptor for declarative transaction // management using the common Spring transaction infrastructure {PlatformTransactionManager} public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {...}
// AOP Alliance MethodInterceptor for declarative transaction // management using the common Spring transaction infrastructure public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {...}
从上述注释中可知该类是专用于声明式事务管理的,它的核心方法以下invoke:
public Object invoke(final MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // If the transaction attribute is null, the method is non-transactional. final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(invocation.getMethod(), targetClass);【1】 final PlatformTransactionManager tm = determineTransactionManager(txAttr);【2】 final String joinpointIdentification = methodIdentification(invocation.getMethod(), targetClass); if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { // Standard transaction demarcation with getTransaction and commit/rollback calls. TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);【3】 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.proceed(); } catch (Throwable ex) { // target invocation exception completeTransactionAfterThrowing(txInfo, ex);【4】 throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo);【5】 return retVal; } else { try { Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, new TransactionCallback<Object>() { public Object doInTransaction(TransactionStatus status) { TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); try { return invocation.proceed(); } ... } }); ... } ... } }
TransactionInterceptor实现了MethodInterceptor接口,将事务管理的逻辑封装在环绕加强的实现中,而目标业务代码则抽象为MethodInvocation(该接口扩展自Joinpoint,故实际是AOP中的链接点),使得事务管理代码与业务逻辑代码彻底分离,能够对任意目标类进行无侵入性的事务织入。具体逻辑:先根据MethodInvocation获取事务属性TransactionAttribute,根据TransactionAttribute获得对应的PlatformTransactionManager,再根据其是不是CallbackPreferringPlatformTransactionManager的实例分别作不一样的处理,总体上跟TransactionTemplate中截然不同,后面主要是介绍几点不一样的地方。
MethodInterceptor是AOP中的环绕加强接口,同一个链接点能够有多个加强,而TransactionInterceptor扩展自该接口,说明事务管理只是众多横切逻辑中的一种,还有不少其余的,好比像日志记录、性能监控等,对于AOP而言并没有区别,它会按照加强的顺序统一处理。关于AOP,后期会单独一篇详细介绍。
在代码【1】处,委托给TransactionAttributeSource根据MethodInvocation获取对应的事务属性TransactionAttribute,先来看下TransactionAttribute:
public interface TransactionAttribute extends TransactionDefinition { /** * Return a qualifier value associated with this transaction attribute. * <p>This may be used for choosing a corresponding transaction manager * to process this specific transaction. */ String getQualifier(); /** * Should we roll back on the given exception? * @param ex the exception to evaluate * @return whether to perform a rollback or not */ boolean rollbackOn(Throwable ex); }
就是在TransactionDefinition的基础上增长了两个可定制属性,使用过XML配置和注解方式的童鞋应该都对qualifier和rollback-for再熟悉不过了,那两个新增属性就是为了支持这两个配置项的。再来看下TransactionAttributeSource:
/** * Interface used by TransactionInterceptor. Implementations know * how to source transaction attributes, whether from configuration, * metadata attributes at source level, or anywhere else. * @see TransactionInterceptor#setTransactionAttributeSource * @see TransactionProxyFactoryBean#setTransactionAttributeSource */ public interface TransactionAttributeSource { TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass); }
之因此有这个接口,是由于Spring提供了XML配置、注解等不一样的事务元数据形式,即事务属性的来源多样,该接口正是将事务配置的来源进行抽象,不一样的来源有对应不一样的实现类,接口单一职责,巧妙精简的设计!类图以下,AnnotationTransactionAttributeSource是注解相关,而NameMatchTransactionAttributeSource、MatchAlwaysTransactionAttributeSource等是XML配置相关。
该抽象父类是事务切面的基本处理类,实现了一些共有方法,如代码【2】处determineTransactionManager(..)根据TransactionAttribute获得对应的PlatformTransactionManager,以及【3】处createTransactionIfNecessary建立事务,【4】处completeTransactionAfterThrowing回滚事务,【5】处commitTransactionAfterReturning提交事务等基本操做,底层一样是委托PlatformTransactionManager进行处理的。这里主要看下事务的回滚操做,跟TransactionTemplate是有区别的:
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.hasTransaction()) { ... if (txInfo.transactionAttribute.rollbackOn(ex)) {【1】 try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by rollback exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } catch (Error err) { logger.error("Application exception overridden by rollback error", ex); throw err; } } else { try { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } ... } } }
从【1】处的transactionAttribute.rollbackon(ex)可看出,事务属性中的rollbackOn是在这里生效的,在发生指定异常时选择回滚或提交,是用户可配置的,而不像TransactionTemplate是固定的所有回滚。
该类是早期基于Bean的XML配置方式实现声明式事务的核心类,之因此放在后面讲,是由于该方式已不被推荐使用,先来看下定义:
/** * Proxy factory bean for simplified declarative transaction handling. * This is a convenient alternative to a standard AOP * {@link org.springframework.aop.framework.ProxyFactoryBean} * with a separate {@link TransactionInterceptor} definition. * * <p><strong>HISTORICAL NOTE:</strong> This class was originally designed to cover the * typical case of declarative transaction demarcation: namely, wrapping a singleton * target object with a transactional proxy, proxying all the interfaces that the target * implements. However, in Spring versions 2.0 and beyond, the functionality provided here * is superseded by the more convenient {@code tx:} XML namespace. See the <a * href="http://bit.ly/qUwvwz">declarative transaction management</a> section of the * Spring reference documentation to understand the modern options for managing * transactions in Spring applications. * ... */ public class TransactionProxyFactoryBean extends AbstractSingletonProxyFactoryBean implements BeanFactoryAware { private final TransactionInterceptor transactionInterceptor = new TransactionInterceptor(); private Pointcut pointcut; ... protected Object createMainInterceptor() { this.transactionInterceptor.afterPropertiesSet(); if (this.pointcut != null) { return new DefaultPointcutAdvisor(this.pointcut, this.transactionInterceptor); } else { // Rely on default pointcut. return new TransactionAttributeSourceAdvisor(this.transactionInterceptor); } } }
源码的声明已经至关清晰,大体说明了该类的前因后果,忍不住直接贴上来了,感兴趣可自行阅读。这里主要是看下其实现思路:事务处理逻辑是委托给其成员TransactionInterceptor,而将事务逻辑织入目标类的工做则交由AbstractSingletonProxyFactoryBean来处理。FactoryBean是Spring中普遍使用的用来定制一些较复杂Bean的实例化逻辑,所以从类名上就可看出,AbstractSingletonProxyFactoryBean的主要工做则是实例化并返回一个单例的Proxy对象。有了Proxy对象,织入的工做就垂手可得了,此时TransactionInterceptor只是Proxy的众多Advisor中的一个,最后由Proxy建立拥有了事务加强的代理对象便可。
如下是AbstractSingletonProxyFactoryBean中Proxy的实例化过程,所有在afterPropertiesSet中完成。其中的createMainInterceptor()是在其子类TransactionProxyFactoryBean中实现的,对应事务加强逻辑。
public abstract class AbstractSingletonProxyFactoryBean extends ProxyConfig implements FactoryBean<Object>, BeanClassLoaderAware, InitializingBean { ... public void afterPropertiesSet() { if (this.target == null) { throw new IllegalArgumentException("Property 'target' is required"); } if (this.target instanceof String) { throw new IllegalArgumentException("'target' needs to be a bean reference, not a bean name as value"); } if (this.proxyClassLoader == null) { this.proxyClassLoader = ClassUtils.getDefaultClassLoader(); } ProxyFactory proxyFactory = new ProxyFactory();【1】 if (this.preInterceptors != null) { for (Object interceptor : this.preInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } // Add the main interceptor (typically an Advisor). proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(createMainInterceptor())); if (this.postInterceptors != null) { for (Object interceptor : this.postInterceptors) { proxyFactory.addAdvisor(this.advisorAdapterRegistry.wrap(interceptor)); } } proxyFactory.copyFrom(this); TargetSource targetSource = createTargetSource(this.target); proxyFactory.setTargetSource(targetSource); if (this.proxyInterfaces != null) { proxyFactory.setInterfaces(this.proxyInterfaces); } else if (!isProxyTargetClass()) { // Rely on AOP infrastructure to tell us what interfaces to proxy. proxyFactory.setInterfaces( ClassUtils.getAllInterfacesForClass(targetSource.getTargetClass(), this.proxyClassLoader)); } this.proxy = proxyFactory.getProxy(this.proxyClassLoader); } }
从代码【1】处能够看到,ProxyFactory是建立Proxy对象的关键类,感兴趣的童鞋能够跟进ProxyFactory的代码,可发现最终建立Proxy对象的是DefaultAopProxyFactory,细节以下:根据config配置,选择建立咱们所熟知的两种AopProxy:JDK的JdkDynamicAopProxy和Cglib的Cglib2AopProxy。
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { ... public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface()) { return new JdkDynamicAopProxy(config); } if (!cglibAvailable) { throw new AopConfigException( "Cannot proxy target class because CGLIB2 is not available. " + "Add CGLIB to the class path or specify proxy interfaces."); } return CglibProxyFactory.createCglibProxy(config); } else { return new JdkDynamicAopProxy(config); } } }
当使用PROPAGATION_NESTED时,底层的数据源必须基于JDBC3.0。由于Spring所支持的嵌套事务,是基于事务保存点实现的(JTA除外),而保存点机制是从JDBC3.0才开始出现的。直接看AbstractPlatformTransactionManager中的处理代码。对于一般的嵌套事务,会在当前所处父事务中建立保存点,而后进行子事务处理;对于JTA事务环境,则是采用嵌套的begin和commit/rollback调用来处理。
private TransactionStatus handleExistingTransaction( TransactionDefinition definition, Object transaction, boolean debugEnabled) throws TransactionException { ... 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 = prepareTransactionStatus(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. boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( definition, transaction, true, newSynchronization, debugEnabled, null); doBegin(transaction, definition); prepareSynchronization(status, definition); return status; } } ... }
当脱离模板类,直接操做底层持久技术的原生API时,就须要经过Spring提供的资源工具类获取线程绑定的资源,而不该该直接从DataSource或SessionFactory中获取,不然容易形成数据链接泄露的问题。Spring为不一样的持久化技术提供了一套从TransactionSynchronizationManager中获取对应线程绑定资源的工具类:DataSourceUtils(Spring JDBC或iBatis)、SessionFactoryUtils(Hibernate 3.0)等。
虽然@Transactional注解可被应用于接口、接口方法、类及类的public方法,但建议在具体实现类上使用@Transactional注解,由于接口上的注解不能被继承,这样会有隐患(关于注解的继承,可参考这里)。当事务配置按以下方式,使用的是子类代理(CGLib)而非接口代理(JDK)时,对应目标类不会添加事务加强!
<tx:annotation-driven transaction-manager="txManager" proxy-target-class="true" />