Spring Transactional源码分析(二)
1.事务执行
代理对象创建完成之后,事务的执行的入口就是JdkDynamicAopProxy#invoke
或者CglibAopProxy.DynamicAdvisedInterceptor#interceptor
,然后调用ReflectiveMethodInvocation
执行到TransactionInterceptor#invoke
。
org.springframework.transaction.interceptor.TransactionInterceptor#invoke
:
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
//1.获取目标类class
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
//2.这里使用了一个匿名内部类进行回调,用于目标方法执行
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
org.springframework.transaction.interceptor.TransactionAspectSupport#invokeWithinTransaction
:
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
//1.获取@Transactional配置的属性,XML使用NameMatchTransactionAttributeSource,注解使用AnnotationTransactionAttributeSource
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
//2.获取事务管理器
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//3.得到连接点方法名
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//4.开启事务,包含了传播行为、隔离级别以及其他属性的处理,包括线程和数据源的绑定
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
//5.执行目标方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
//6.处理事务异常,可能回滚,也可能提交
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
//7.提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
} else {
// CallbackPreferringPlatformTransactionManager子类的执行,不关心
......
}
}
这是一个事务执行的模版方法,使用了环绕通知结构,具体方法的实现通过委派模式交给子类去实现。那也就是说事务是基于环绕通知实现的。
1.获取TransactionAttribute
xml
:
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (!ClassUtils.isUserLevelMethod(method)) {
return null;
}
// Look for direct name match.
//1.直接根据名称匹配从Map中获取
String methodName = method.getName();
TransactionAttribute attr = this.nameMap.get(methodName);
//2.上面可能获取不到,因为key可能是get*这种格式,所以需要遍历匹配获取
if (attr == null) {
String bestNameMatch = null;
for (String mappedName : this.nameMap.keySet()) {
if (isMatch(methodName, mappedName) &&
(bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
attr = this.nameMap.get(mappedName);
bestNameMatch = mappedName;
}
}
}
return attr;
}
从nameMap
缓存中获取,key
为<tx:method/>
的name
属性,value
为RuleBasedTransactionAttribute
,这个缓存是在解析<tx:method/>
标签的时候存入的。
注解:
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
//1.从缓存中获取,开始肯定为NULL
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
//2.获取@Transactional的属性值,并放入缓存
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isDebugEnabled()) {
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
注解方法获取TransactionAttribute
咋前面过滤Advisor
的时候,已经计算好了并且放入了attributeCache
缓存中,这里就是直接通过key
从缓存中获取即可。
2.获取事务管理器
org.springframework.transaction.interceptor.TransactionAspectSupport#determineTransactionManager
:
protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
//1.如果没有事务属性或容器为空,则获取默认的TransactionManager,可能找到,也可能返回null
if (txAttr == null || this.beanFactory == null) {
return getTransactionManager();
}
//2.别名是否存在,直接根据别名从缓存中获取
String qualifier = txAttr.getQualifier();
if (StringUtils.hasText(qualifier)) {
return determineQualifiedTransactionManager(qualifier);
}
//3.@Transactional指定了value或transactionManager属性,如果缓存中没有,则按照类型以及指定的事务管理器名称查找,放入缓存
else if (StringUtils.hasText(this.transactionManagerBeanName)) {
return determineQualifiedTransactionManager(this.transactionManagerBeanName);
}
else {
//4.先获取默认的TransactionManager,如果没找到,则按照类型从容器中查找,并放入缓存,XML
PlatformTransactionManager defaultTransactionManager = getTransactionManager();
if (defaultTransactionManager == null) {
defaultTransactionManager = this.transactionManagerCache.get(DEFAULT_TRANSACTION_MANAGER_KEY);
if (defaultTransactionManager == null) {
defaultTransactionManager = this.beanFactory.getBean(PlatformTransactionManager.class);
this.transactionManagerCache.putIfAbsent(
DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager);
}
}
return defaultTransactionManager;
}
}
这个方法是用来为当前的事务获取事务管理器(TransactionManager
),每个事务是和特定的事务管理器关联在一起的。
3.开启事务
org.springframework.transaction.interceptor.TransactionAspectSupport#createTransactionIfNecessary
:
protected TransactionInfo createTransactionIfNecessary(
PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) {
//1.如果没有指定事务名称,则是用当前方法名作为事务名称
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
//2.获取事务状态
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
//3.使用TransactionInfo类保存了这个线程事务的所有信息,如TransactionManager,TransactionAttributes、连接点方法名、TransactionStatus
//并且通过一个线程单例与当前线程绑定
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
首先把RuleBasedTransactionAttribute
转为DelegatingTransactionAttribute
,以执行的方法名作为本次事务的名称;然后就是最重要的一步,获取TransactionStatus
,这里面做了诸多工作;最后一步是把所有的信息封装到一个叫TransactionInfo
的类中,并作为线程单例缓存,以便获取堆栈信息。
1.获取事务状态(TransactionStatus
)
org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
:
@Override
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//1.获取当前事务,可能存在,可能不存在
Object transaction = doGetTransaction();
boolean debugEnabled = logger.isDebugEnabled();
//2.如果TransactionAttribute为空,则使用默认的
if (definition == null) {
definition = new DefaultTransactionDefinition();
}
//3.如果当前事务已经存在,则需要考虑事务传播行为
if (isExistingTransaction(transaction)) {
return handleExistingTransaction(definition, transaction, debugEnabled);
}
//4.没有已经存在的事务,创建新的事
//事务超时了
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
//运行在当前事务,如果当前事务不存在,则抛出异常
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);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
} catch (RuntimeException ex) {
resume(null, suspendedResources);
throw ex;
} catch (Error err) {
resume(null, suspendedResources);
throw err;
}
}
//都是非事务的执行
else {
//PROPAGATION.SUPPORTS、PROPAGATION_NOT_SUPPORTED、PROPAGATION_NEVER
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
该方法可以分为两部分,前面部分用于处理事务已经存在的情况,后面部分用于处理事务不存在的情况,这两种情况取决于doGetTransaction
能否拿到已经存在的事务。
1.获取当前事务
org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction
:
@Override
protected Object doGetTransaction() {
//1.TransactionObject是一个数据库事务对象,每个新的数据库连接都会有一个该对象,保存了数据库连接相关信息
DataSourceTransactionObject txObject = new DataSourceTransactionObject();
//2.是否允许嵌套事务
txObject.setSavepointAllowed(isNestedTransactionAllowed());
//3.从数据源获取连接持有器
// 是否存在事务指的是在当前线程、当前数据源(DataSource)中是否存在处于活动状态的事务
//也就是说事务是和数据源以及当前线程绑定在一起的
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);
//4.这时候获取的无论是否为空,肯定都不是newConnectionHolder
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
这里需要强调一下:是否存在事务是指在当前线程、当前数据源是否存在于活动状态的事务。
DataSourceTransactionObject
是DataSourceTransactionManager
的内部类,对于每个TransactionManager
都会有一个TransactionObject
,这个TransactionObject
事务对象保存了数据连接持有器(ConnectionHolder
)以及保存点等信息。
org.springframework.transaction.support.TransactionSynchronizationManager#getResource
:
public static Object getResource(Object key) {
//1.获取真实的resource
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
//2.获取ConnectionHolder
Object value = doGetResource(actualKey);
if (value != null && logger.isTraceEnabled()) {
logger.trace("Retrieved value [" + value + "] for key [" + actualKey + "] bound to thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
org.springframework.transaction.support.TransactionSynchronizationManager#doGetResource
:
private static Object doGetResource(Object actualKey) {
//1.从线程单例中获取当前数据源绑定的ConnectionHolder
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
//2.判断是否是无效的ResourceHolder
Object value = map.get(actualKey);
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
map.remove(actualKey);
if (map.isEmpty()) {
resources.remove();
}
value = null;
}
return value;
}
resources
是一个线程单例,这里的actualKey
一般就是DataSource
,而value
一般就是ConnectionHolder
,从这种获取事务的方式也可以得到事务是指当前线程、当前数据源所活动的数据库连接。
这里如果说已经存在事务了,就返回ConnectionHolder
实例,否则返回null
,但无论是否为null
,它的newConnectionHolder
肯定是false
。
org.springframework.jdbc.datasource.DataSourceTransactionManager#isExistingTransaction
:
@Override
protected boolean isExistingTransaction(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//如果连接持有器存在并且事务被激活了
return (txObject.hasConnectionHolder() && txObject.getConnectionHolder().isTransactionActive());
}
判断当前线程、当前数据源是否已经存在了事务。
无论当前事务是否存在,都要考虑Spring
支持的七种事务传播行为,传播行为是Spring
为了解决多线程运行时事务该如何处理所定义的一种概念,数据库本身并不存在这个概念。
2.存在当前事务
org.springframework.transaction.support.AbstractPlatformTransactionManager#handleExistingTransaction
:
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
//1.如果存在事务,则抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
//2.事务执行,如果存在当前事务,则挂起
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
//被挂起的线程的资源
Object suspendedResources = suspend(transaction);
//是否激活事务同步器
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
//适当的创建一个新的TransactionStatus
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources);
}
//3.总是新建事务,如果当前事务存在,则挂起
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
SuspendedResourcesHolder suspendedResources = suspend(transaction);
//是否是新的事务同步器
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
//创建新的TransactionStatus
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
//处理事务隔离级别,但是忽略了超时时间
doBegin(transaction, definition);
//适当的初始化事务同步器
prepareSynchronization(status, definition);
return status;
}
//4.如果存在事务,则创建一个事务作为当前事务的嵌套事务来执行,如果当前没有事务,则创建
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'");
}
//使用保存点创建嵌套事务,默认是true,
if (useSavepointForNestedTransaction()) {
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
status.createAndHoldSavepoint();
return status;
} else {
// 处理JtaTransactionManager支持的分布式事务
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, null);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
}
//5.处理
//PROPAGATION_SUPPORTS:如果存在事务,则加入该事务;如果当前没有事务,则非事务的运行
//PROPAGATION_REQUIRED:如果存在当前事务,则加入该事务;如果当前没有事务,则创建一个新事务。这是默认值
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null);
}
这个方法就是在事务已经存在的根据事务定义的传播行为做不同的处理,这里虽然不同的行为有不同的处理,但是核心都是使用的相同的方法,只是部分属性值不同。这里省略了部分不重要的代码。
挂起线程:
org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend
:
protected final SuspendedResourcesHolder suspend(Object transaction) throws TransactionException {
//1.如果当前的事务激活并处于同步活动状态,需要挂起事务同步器和事务
if (TransactionSynchronizationManager.isSynchronizationActive()) {
//挂起事务同步
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
//挂起事务,并重置相关状态
Object suspendedResources = null;
if (transaction != null) {
suspendedResources = doSuspend(transaction);
}
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
} catch (RuntimeException ex) {
doResumeSynchronization(suspendedSynchronizations);
throw ex;
} catch (Error err) {
doResumeSynchronization(suspendedSynchronizations);
throw err;
}
}
//2.当前事务被激活,但是未处于事务同步状态,只需挂起事务即可
else if (transaction != null) {
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
//3.当前事务不存在
else {
return null;
}
}
这里挂起主要分为三种情况:1.事务和同步器都被激活;2.只有事务激活;3.两者都未激活。
同步器挂起:
org.springframework.transaction.support.AbstractPlatformTransactionManager#doSuspendSynchronization
:
private List<TransactionSynchronization> doSuspendSynchronization() {
//1.获取当前线程所拥有的所有同步器
List<TransactionSynchronization> suspendedSynchronizations =
TransactionSynchronizationManager.getSynchronizations();
for (TransactionSynchronization synchronization : suspendedSynchronizations) {
//2.遍历挂起,移除当前线程所拥有的当前数据源的资源
synchronization.suspend();
}
//3.移除当前线程的所有同步器
TransactionSynchronizationManager.clearSynchronization();
return suspendedSynchronizations;
}
org.springframework.transaction.support.ResourceHolderSynchronization#suspend
:
@Override
public void suspend() {
if (this.holderActive) {
TransactionSynchronizationManager.unbindResource(this.resourceKey);
}
}
org.springframework.transaction.support.TransactionSynchronizationManager#doUnbindResource
:
private static Object doUnbindResource(Object actualKey) {
Map<Object, Object> map = resources.get();
if (map == null) {
return null;
}
Object value = map.remove(actualKey);
if (map.isEmpty()) {
resources.remove();
}
if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) {
value = null;
}
if (value != null && logger.isTraceEnabled()) {
logger.trace("Removed value [" + value + "] for key [" + actualKey + "] from thread [" +
Thread.currentThread().getName() + "]");
}
return value;
}
移除当前线程所拥有的当前数据源的资源。
org.springframework.transaction.support.TransactionSynchronizationManager#clearSynchronization
:
public static void clearSynchronization() throws IllegalStateException {
if (!isSynchronizationActive()) {
throw new IllegalStateException("Cannot deactivate transaction synchronization - not active");
}
logger.trace("Clearing transaction synchronization");
synchronizations.remove();
}
移除当前线程的所有同步器。
事务挂起:
org.springframework.jdbc.datasource.DataSourceTransactionManager#doSuspend
:
@Override
protected Object doSuspend(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
//一个ConnectionHolder对象就代表了一个数据库连接,将ConnectionHolder设为null就意味着我们下次使用连接时,将重新从连接池中获取,是一个新的连接
txObject.setConnectionHolder(null);
return TransactionSynchronizationManager.unbindResource(this.dataSource);
}
事务挂起这里把TransactionObject
所拥有的ConnectionHolder
置为null
是很重要的,如果这里不置为null
,后面就不会创建新的Connection
,也就不会是新的事务了。取消绑定资源和上面是一样的,就是移除了当前线程所拥有的当前数据源的ConnectionHolder
。
创建的TransactionStatus
:
org.springframework.transaction.support.AbstractPlatformTransactionManager#newTransactionStatus
:
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, Object suspendedResources) {
//1.是否激活事务同步器
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
//2.构造
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
这里唯一需要注意的就是是否需要立即激活事务同步器,后续都是调用DefaultTransacionStatus
进行构造。
创建新的Connection
并绑定:
org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin
:
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
//1.此时,txObject不为null,只是其核心的ConnectorHolder为null
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
//2.获得连接,可以看出ConnectionHolder是对Connection的封装
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
//3.设置是否只读和隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
//4.如果需要的情况下,置为手动提交,对于新连接,这里肯定是true
if (con.getAutoCommit()) {
//事务执行之后还原自动提交
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
//将数据库的事务自动提交置为false,这里就会开启事务
con.setAutoCommit(false);
}
//5.设置只读sql
prepareTransactionalConnection(con, definition);
//6.事务激活
txObject.getConnectionHolder().setTransactionActive(true);
//7.设置超时时间
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
//8.这里又将新的ConnectionHolder和数据源绑定在一起
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
这个方法创建了新的连接,并设置了相关的属性,如隔离级别、超时时间等,最后还是需要将当前线程的新的ConnectionHolder
和当前数据源绑定在一起。
org.springframework.jdbc.datasource.DataSourceUtils#prepareConnectionForTransaction
:
public static Integer prepareConnectionForTransaction(Connection con, TransactionDefinition definition)
throws SQLException {
//1.设置数据库连接是否只读
if (definition != null && definition.isReadOnly()) {
con.setReadOnly(true);
}
//2.指定事务隔离级别
Integer previousIsolationLevel = null;
if (definition != null && definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
int currentIsolation = con.getTransactionIsolation();
if (currentIsolation != definition.getIsolationLevel()) {
previousIsolationLevel = currentIsolation;
con.setTransactionIsolation(definition.getIsolationLevel());
}
}
return previousIsolationLevel;
}
设置数据库连接的只读和事务隔离级别。这里省略了部分代码。
org.springframework.jdbc.datasource.DataSourceTransactionManager#prepareTransactionalConnection
:
protected void prepareTransactionalConnection(Connection con, TransactionDefinition definition)
throws SQLException {
if (isEnforceReadOnly() && definition.isReadOnly()) {
Statement stmt = con.createStatement();
try {
stmt.executeUpdate("SET TRANSACTION READ ONLY");
}
finally {
stmt.close();
}
}
}
执行SQL
保证当前只读。
org.springframework.transaction.support.TransactionSynchronizationManager#bindResource
:
public static void bindResource(Object key, Object value) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Assert.notNull(value, "Value must not be null");
Map<Object, Object> map = resources.get();
if (map == null) {
map = new HashMap<Object, Object>();
resources.set(map);
}
Object oldValue = map.put(actualKey, value);
if (oldValue instanceof ResourceHolder && ((ResourceHolder) oldValue).isVoid()) {
oldValue = null;
}
if (oldValue != null) {
throw new IllegalStateException("Already value [" + oldValue + "] for key [" +
actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
if (logger.isTraceEnabled()) {
logger.trace("Bound value [" + value + "] for key [" + actualKey + "] to thread [" +
Thread.currentThread().getName() + "]");
}
}
这个方法和unbindResource
相反的,用于绑定当前线程拥有的当前数据源的资源,都是通过resources
这个线程单例。
适当的初始化线程同步器:
org.springframework.transaction.support.AbstractPlatformTransactionManager#prepareSynchronization
:
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
//1.如果是新的同步器,则设置事务同步管理器的内容
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
//2.设置线程单例
TransactionSynchronizationManager.initSynchronization();
}
}
TransactionSynchronization
是用于事务同步回调的接口,受AbstractPlatformTransactionManager
的支持。
TransactionSynchronizationManager
是一个核心委托,用于管理每个线程的资源和事务同步。
3.不存在当前事务
不存在当前事务的时候,也同样需要根据事务的传播行为创建不同的TransactionStatus
,主要可以分为三大类。
1.对于PROPAGATION_MANDATORY
,如果不存在当前事务,直接抛出异常。
2.对于PROPAGATION_REQUEIRED
、PROPAGATION_REQUIRE_NEW
、PROPAGATION_NESTED
,必须在事务中执行,总是会新建事务。
3.对于PROPAGATION_SUPPORTS
、PROPAGATION_NOT_SUPPORTED
、PROPAGATION_NERVER
,不需要在事务中执行的,则并不会创建真正的事务。
创建TransactionStatus
所调用的核心方法以及业务逻辑和存在当前事务时创建新事务基本是一样的,除了不需要挂起其他事务(suspend
),其他的可能略有状态上的不同。
2.封装(TransactionInfo
)
org.springframework.transaction.interceptor.TransactionAspectSupport#prepareTransactionInfo
:
protected TransactionInfo prepareTransactionInfo(PlatformTransactionManager tm,
TransactionAttribute txAttr, String joinpointIdentification, TransactionStatus status) {
//1.封装
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
txInfo.newTransactionStatus(status);
}
else {
if (logger.isTraceEnabled()) {
logger.trace("No need to create transaction for [" + joinpointIdentification +
"]: This method is not transactional.");
}
}
//2.始终绑定到线程,即使这里没有创建新的事物,保证正确的管理TransactionInfo堆栈
txInfo.bindToThread();
return txInfo;
}
org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#bindToThread
:
private void bindToThread() {
this.oldTransactionInfo = transactionInfoHolder.get();
transactionInfoHolder.set(this);
}
在拿到TransactionStatus
之后,使用一个TransactionInfo
类包装当前线程事务的所有相关信息,并且使用线程单例绑定到了当前线程,方便后面执行事务的打印堆栈信息。
4.执行目标方法
执行目标方法就很简单了。
protected interface InvocationCallback {
Object proceedWithInvocation() throws Throwable;
}
通过匿名内部类的回调,继续调用ReflectiveMethodInvocation#proceed
方法,如果还有其他的Interceptor
,则继续执行其他Interceptor
,最终执行目标方法。
前面也说过了,Spring
的事务执行是基于环绕通知的,当目标方法执行完成之后,就需要处理当前事务是commit
还是rollback
了。
5.提交或回滚
无论是事务执行发生异常进行事务回滚,还是正常执行进行事务提交,都要在finally
中回滚当前线程的TransactionInfo
。
org.springframework.transaction.interceptor.TransactionAspectSupport#cleanupTransactionInfo
:
protected void cleanupTransactionInfo(TransactionInfo txInfo) {
if (txInfo != null) {
txInfo.restoreThreadLocalStatus();
}
}
org.springframework.transaction.interceptor.TransactionAspectSupport.TransactionInfo#restoreThreadLocalStatus
:
private void restoreThreadLocalStatus() {
//如果当前线程只有一个TransactionInfo,那么这里回滚,值就是null
transactionInfoHolder.set(this.oldTransactionInfo);
}
1.事务提交
org.springframework.transaction.interceptor.TransactionAspectSupport#commitTransactionAfterReturning
:
protected void commitTransactionAfterReturning(TransactionInfo txInfo) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
//调用事务管理器进行提交
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
}
成功执行完成之后,并且没有异常处理,将会提交事务。
org.springframework.transaction.support.AbstractPlatformTransactionManager#commit
:
@Override
public final void commit(TransactionStatus status) throws TransactionException {
//1.事务已经完成了
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
//2.当前事务是否只支持回滚
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus);
return;
}
//3.是否提交全局回滚并只支持全局回滚
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus);
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
throw new UnexpectedRollbackException(
"Transaction rolled back because it has been marked as rollback-only");
}
return;
}
//4.事务提交
processCommit(defStatus);
}
这里在进行真正的事务提交之前,会判断当前的事务状态,如果事务已经完成了,则会抛出异常,如果事务只支持回滚,这里就会触发事务回滚,和后面的事务回滚是一样的,当这几个检测通过之后,rollback-only
标志也就被处理完了,然后就是真正的进行事务提交。
org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit
:
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
prepareForCommit(status);
triggerBeforeCommit(status);
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
boolean globalRollbackOnly = false;
if (status.isNewTransaction() || isFailEarlyOnGlobalRollbackOnly()) {
globalRollbackOnly = status.isGlobalRollbackOnly();
}
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
//1.如果有保存点,释放该事务的保存点
status.releaseHeldSavepoint();
} else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
//2.真正的提交
doCommit(status);
}
if (globalRollbackOnly) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
} catch (UnexpectedRollbackException ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
} catch (TransactionException ex) {
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
} else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
} catch (RuntimeException ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, ex);
throw ex;
} catch (Error err) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, err);
throw err;
}
try {
triggerAfterCommit(status);
} finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
} finally {
cleanupAfterCompletion(status);
}
}
这个方法是一个模板方法,在doCommit
之前和之后,调用了很多回调方法,这些回调方法的目的基本上都是释放当前线程占用的当前数据源的资源。这些回调基本上都是TransactionSynchronization
的实现类,集成的各个ORM
框架可以去通过实现这个接口,定义自己的前置和后置回调。
org.springframework.transaction.support.AbstractTransactionStatus#releaseHeldSavepoint
:
public void releaseHeldSavepoint() throws TransactionException {
if (!hasSavepoint()) {
throw new TransactionUsageException(
"Cannot release savepoint - no savepoint associated with current transaction");
}
//1.直接释放保存点即可
getSavepointManager().releaseSavepoint(getSavepoint());
setSavepoint(null);
}
org.springframework.jdbc.datasource.JdbcTransactionObjectSupport#releaseSavepoint
:
@Override
public void releaseSavepoint(Object savepoint) throws TransactionException {
ConnectionHolder conHolder = getConnectionHolderForSavepoint();
try {
//1.JDBC式释放保存点
conHolder.getConnection().releaseSavepoint((Savepoint) savepoint);
}
catch (Throwable ex) {
logger.debug("Could not explicitly release JDBC savepoint", ex);
}
}
如果当前事务有保存点,则释放当前事务的保存点即可,后续就是JDBC
的操作了。
org.springframework.jdbc.datasource.DataSourceTransactionManager#doCommit
:
@Override
protected void doCommit(DefaultTransactionStatus status) {
//1.事务对象,保存了连接持有器
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
//2.获取连接
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Committing JDBC transaction on Connection [" + con + "]");
}
try {
//3.JDBC式提交
con.commit();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
这里的代码就很熟悉了,就是数据库连接的commit
,与使用JDBC
的提交方式是一样的。
至此,事务的提交也就完成了。
2.事务回滚
org.springframework.transaction.interceptor.TransactionAspectSupport#completeTransactionAfterThrowing
:
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) {
if (txInfo != null && txInfo.hasTransaction()) {
if (logger.isTraceEnabled()) {
logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() +
"] after exception: " + ex);
}
if (txInfo.transactionAttribute.rollbackOn(ex)) {
try {
//1.回滚
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 {
//2.不会回滚,但如果是TransactionStatus.isRollbackOnly(),也会回滚
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by commit exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException ex2) {
logger.error("Application exception overridden by commit exception", ex);
throw ex2;
}
catch (Error err) {
logger.error("Application exception overridden by commit error", ex);
throw err;
}
}
}
}
会判断当前的异常是否在允许回滚的异常里面,可以通过rollback-for
属性设置仅哪些异常会被回滚。不允许被回滚的异常会被提交,但是如果TransactionStatus.isRollbackOnly()
,则在commit
里面依旧会被回滚。
org.springframework.transaction.support.AbstractPlatformTransactionManager#rollback
:
@Override
public final void rollback(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus);
}
如果事务已经完成了,直接抛出异常即可,否则强转为DefualtTransactionStatus
进行事务回滚。
org.springframework.transaction.support.AbstractPlatformTransactionManager#processRollback
:
private void processRollback(DefaultTransactionStatus status) {
try {
try {
triggerBeforeCompletion(status);
if (status.hasSavepoint()) {
if (status.isDebug()) {
logger.debug("Rolling back transaction to savepoint");
}
//1.回滚到该事务的保存点,并释放该保存点
status.rollbackToHeldSavepoint();
} else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction rollback");
}
//2.事务回滚
doRollback(status);
} else if (status.hasTransaction()) {
if (status.isLocalRollbackOnly() || isGlobalRollbackOnParticipationFailure()) {
if (status.isDebug()) {
logger.debug("Participating transaction failed - marking existing transaction as rollback-only");
}
doSetRollbackOnly(status);
} else {
if (status.isDebug()) {
logger.debug("Participating transaction failed - letting transaction originator decide on rollback");
}
}
} else {
logger.debug("Should roll back transaction but cannot - no transaction available");
}
} catch (RuntimeException ex) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
} catch (Error err) {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw err;
}
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
} finally {
cleanupAfterCompletion(status);
}
}
这个方法整体结构和processCommit
是一模一样的,也是在事务回滚前后调用了各种回调方法用于释放资源或者其他的处理。
org.springframework.transaction.support.AbstractTransactionStatus#rollbackToHeldSavepoint
:
public void rollbackToHeldSavepoint() throws TransactionException {
if (!hasSavepoint()) {
throw new TransactionUsageException(
"Cannot roll back to savepoint - no savepoint associated with current transaction");
}
//1.回滚保存点
getSavepointManager().rollbackToSavepoint(getSavepoint());
//2.释放保存点
getSavepointManager().releaseSavepoint(getSavepoint());
setSavepoint(null);
}
相对于commit
的时候释放事务保存点,这里多了一步回滚到事务的保存点,其他的都是一样的。
org.springframework.jdbc.datasource.DataSourceTransactionManager#doRollback
:
@Override
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
if (status.isDebug()) {
logger.debug("Rolling back JDBC transaction on Connection [" + con + "]");
}
try {
con.rollback();
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
这里的代码就很熟悉了,就是数据库连接的rollback
,与使用JDBC
的回滚方式是一样的。
至此,事务的回滚也就完成了。