Spring-transaction
Spring 事务
- Author: HuiFer
- 源码阅读仓库: SourceHot-Spring
声明式事务
Propagation
- 事务传播
|
|
Isolation
- 事务级别
|
|
EnableTransactionManagement
- 下面代码是一个注解方式的事务配置使用
EnableTransactionManagement
来开启事务支持
|
|
- 注解源码如下,关注于
@Import(TransactionManagementConfigurationSelector.class)
|
|
|
|
ProxyTransactionManagementConfiguration
|
|
TransactionInterceptor
- 实现了
org.aopalliance.intercept.MethodInterceptor
接口的方法
|
|
- 这段代码会在具有
Transactional
的注解方法上生效
|
|
断点开始进行查阅. 再断点后执行一步会直接进入 cglib 代理对象
org.springframework.aop.framework.CglibAopProxy.DynamicAdvisedInterceptor#intercept
具体不展开,继续往下执行
走到invoke
方法了
入参对象查看
-
获取事务属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
@Override @Nullable public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { if (method.getDeclaringClass() == Object.class) { return null; } // First, see if we have a cached value. // 尝试缓存中获取 Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { // Value will either be canonical value indicating there is no transaction attribute, // or an actual transaction attribute. if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } else { // We need to work it out. // 自行构建一个事务属性 TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); // Put it in the cache. 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.isTraceEnabled()) { logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr); } this.attributeCache.put(cacheKey, txAttr); } return txAttr; } } protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) { return new MethodClassKey(method, targetClass); }
-
此处方法已经获取到了这个方法就是后面的一个切面
-
确定事务管理器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
@Nullable protected TransactionManager determineTransactionManager( @Nullable TransactionAttribute txAttr) { // Do not attempt to lookup tx manager if no tx attributes are set // 空判断返回一个事务管理器 if (txAttr == null || this.beanFactory == null) { return getTransactionManager(); } // 属性是否有别名 String qualifier = txAttr.getQualifier(); // 如果有 if (StringUtils.hasText(qualifier)) { // 从 ioc 容器中根据类型和名称获取事务管理器 return determineQualifiedTransactionManager(this.beanFactory, qualifier); } else if (StringUtils.hasText(this.transactionManagerBeanName)) { // 从 ioc 容器中根据类型和名称获取事务管理器 return determineQualifiedTransactionManager(this.beanFactory, this.transactionManagerBeanName); } else { // 通过get方法获取 TransactionManager defaultTransactionManager = getTransactionManager(); // 如果没有 if (defaultTransactionManager == null) { // 尝试从缓存中获取 defaultTransactionManager = this.transactionManagerCache .get(DEFAULT_TRANSACTION_MANAGER_KEY); // 缓存里面没有从 ioc 容器中获取并且设置缓存 if (defaultTransactionManager == null) { defaultTransactionManager = this.beanFactory.getBean(TransactionManager.class); this.transactionManagerCache.putIfAbsent( DEFAULT_TRANSACTION_MANAGER_KEY, defaultTransactionManager); } } return defaultTransactionManager; } }
-
类型转换
1 2 3 4 5 6 7 8 9 10 11 12
@Nullable private PlatformTransactionManager asPlatformTransactionManager( @Nullable Object transactionManager) { if (transactionManager == null || transactionManager instanceof PlatformTransactionManager) { return (PlatformTransactionManager) transactionManager; } else { throw new IllegalStateException( "Specified transaction manager is not a PlatformTransactionManager: " + transactionManager); } }
-
获取方法切面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
private String methodIdentification(Method method, @Nullable Class<?> targetClass, @Nullable TransactionAttribute txAttr) { String methodIdentification = methodIdentification(method, targetClass); if (methodIdentification == null) { if (txAttr instanceof DefaultTransactionAttribute) { // 直接就获取了.方法签名. methodIdentification = ((DefaultTransactionAttribute) txAttr).getDescriptor(); } if (methodIdentification == null) { methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); } } return methodIdentification; }
-
创建一个新的事务根据事务传播性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
@SuppressWarnings("serial") protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, final String joinpointIdentification) { // If no name specified, apply method identification as transaction name. // 把切面的地址放进去 if (txAttr != null && txAttr.getName() == null) { txAttr = new DelegatingTransactionAttribute(txAttr) { @Override public String getName() { return joinpointIdentification; } }; } 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"); } } } // 处理出一个 TransactionInfo return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
-
tm.getTransaction
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
@Override public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { // Use defaults if no transaction definition given. // 获取事务的定义 TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); // 获取事务 Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); // 是否存在事务 if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. // 存在事务后处理什么操作 return handleExistingTransaction(def, transaction, debugEnabled); } // Check definition settings for new transaction. // 超时的校验. 小于默认值抛出异常 if (def.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) { throw new InvalidTimeoutException("Invalid transaction timeout", def.getTimeout()); } // No existing transaction found -> check propagation behavior to find out how to proceed. // 没有事务抛出异常 if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) { throw new IllegalTransactionStateException( "No existing transaction found for transaction marked with propagation 'mandatory'"); } else if (def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW || def.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) { SuspendedResourcesHolder suspendedResources = suspend(null); if (debugEnabled) { logger.debug("Creating new transaction with name [" + def.getName() + "]: " + def); } try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus( def, transaction, true, newSynchronization, debugEnabled, suspendedResources); doBegin(transaction, def); prepareSynchronization(status, def); return status; } catch (RuntimeException | Error ex) { resume(null, suspendedResources); throw ex; } } else { // Create "empty" transaction: no actual transaction, but potentially synchronization. if (def.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger .isWarnEnabled()) { logger.warn( "Custom isolation level specified but no actual transaction initiated; " + "isolation level will effectively be ignored: " + def); } boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS); return prepareTransactionStatus(def, null, true, newSynchronization, debugEnabled, null); } }
-
org.springframework.transaction.support.AbstractPlatformTransactionManager#getTransaction
-
org.springframework.jdbc.datasource.DataSourceTransactionManager#doGetTransaction
1 2 3 4 5 6 7 8 9 10 11 12
@Override protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); // 数据库链接对象 // 从事务管理器中获取数据库链接对象 ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager .getResource(obtainDataSource()); txObject.setConnectionHolder(conHolder, false); return txObject; }
-
org.springframework.transaction.support.AbstractPlatformTransactionManager#suspend
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
@Nullable protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException { 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 | Error ex) { // doSuspend failed - original transaction is still active... doResumeSynchronization(suspendedSynchronizations); throw ex; } } else if (transaction != null) { // Transaction active but no synchronization active. Object suspendedResources = doSuspend(transaction); return new SuspendedResourcesHolder(suspendedResources); } else { // Neither transaction nor synchronization active. return null; } }
-
-
prepareTransactionInfo
简单的new
对象并且绑定线程1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm, @Nullable TransactionAttribute txAttr, String joinpointIdentification, @Nullable TransactionStatus status) { // 初始化 TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification); if (txAttr != null) { // We need a transaction for this method... if (logger.isTraceEnabled()) { logger.trace( "Getting transaction for [" + txInfo.getJoinpointIdentification() + "]"); } // The transaction manager will flag an error if an incompatible tx already exists. txInfo.newTransactionStatus(status); } else { // The TransactionInfo.hasTransaction() method will return false. We created it only // to preserve the integrity of the ThreadLocal stack maintained in this class. if (logger.isTraceEnabled()) { logger.trace("No need to create transaction for [" + joinpointIdentification + "]: This method is not transactional."); } } // We always bind the TransactionInfo to the thread, even if we didn't create // a new transaction here. This guarantees that the TransactionInfo stack // will be managed correctly even if no transaction was created by this aspect. // 和线程绑定 txInfo.bindToThread(); return txInfo; }
-
retVal = invocation.proceedWithInvocation();
-
这里走的是 CGLIB 的方法直接会执行结果将结果返回具体方法在
org.springframework.aop.framework.CglibAopProxy.CglibMethodInvocation#proceed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
@Override @Nullable public Object proceed() throws Throwable { try { return super.proceed(); } catch (RuntimeException ex) { throw ex; } catch (Exception ex) { if (ReflectionUtils.declaresException(getMethod(), ex.getClass())) { throw ex; } else { throw new UndeclaredThrowableException(ex); } } }
-
-
如果没有异常就直接处理完成返回了
-
我们现在是有异常的
1 2 3 4 5 6 7 8 9 10 11 12 13 14
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); }
-
completeTransactionAfterThrowing
回滚异常的处理方法1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
protected void completeTransactionAfterThrowing(@Nullable TransactionInfo txInfo, Throwable ex) { if (txInfo != null && txInfo.getTransactionStatus() != null) { if (logger.isTraceEnabled()) { logger.trace("Completing transaction for [" + txInfo.getJoinpointIdentification() + "] after exception: " + ex); } if (txInfo.transactionAttribute != null && txInfo.transactionAttribute.rollbackOn(ex)) { 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 | Error ex2) { logger.error("Application exception overridden by rollback exception", ex); throw ex2; } } else { // We don't roll back on this exception. // Will still roll back if TransactionStatus.isRollbackOnly() is true. try { // org.springframework.transaction.support.AbstractPlatformTransactionManager.commit 的方法 txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } catch (TransactionSystemException ex2) { logger.error("Application exception overridden by commit exception", ex); ex2.initApplicationException(ex); throw ex2; } catch (RuntimeException | Error ex2) { logger.error("Application exception overridden by commit exception", ex); throw ex2; } } } }
-
整理一下这里的流程
-
有异常走回滚
txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus())
-
没有异常直接提交
txInfo.getTransactionManager().commit(txInfo.getTransactionStatus())
-
-
注意: 这里的异常如果是 exception 不会走回滚
-
-
判断是否需要回滚
txInfo.transactionAttribute.rollbackOn
-
链路
-
org.springframework.transaction.interceptor.DelegatingTransactionAttribute#rollbackOn
-
org.springframework.transaction.interceptor.RuleBasedTransactionAttribute#rollbackOn
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
@Override public boolean rollbackOn(Throwable ex) { if (logger.isTraceEnabled()) { logger.trace( "Applying rules to determine whether transaction should rollback on " + ex); } RollbackRuleAttribute winner = null; int deepest = Integer.MAX_VALUE; if (this.rollbackRules != null) { for (RollbackRuleAttribute rule : this.rollbackRules) { int depth = rule.getDepth(ex); if (depth >= 0 && depth < deepest) { deepest = depth; winner = rule; } } } if (logger.isTraceEnabled()) { logger.trace("Winning rollback rule is: " + winner); } // User superclass behavior (rollback on unchecked) if no rule matches. if (winner == null) { logger.trace("No relevant rollback rule found: applying default rules"); return super.rollbackOn(ex); } return !(winner instanceof NoRollbackRuleAttribute); }
-
org.springframework.transaction.interceptor.DefaultTransactionAttribute#rollbackOn
1 2 3 4
@Override public boolean rollbackOn(Throwable ex) { return (ex instanceof RuntimeException || ex instanceof Error); }
- 这就是我们的异常判断是否需要回滚
-
-
-
-
-
cleanupTransactionInfo
数据清理
1 2 3 4 5
protected void cleanupTransactionInfo(@Nullable TransactionInfo txInfo) { if (txInfo != null) { txInfo.restoreThreadLocalStatus(); } }
1 2 3 4 5
private void restoreThreadLocalStatus() { // Use stack to restore old transaction TransactionInfo. // Will be null if none was set. transactionInfoHolder.set(this.oldTransactionInfo); }
编程式事务
DefaultTransactionDefinition
- 默认的事务定义
- 常见属性
- timeout
- readOnly
- ….
- 常见属性
PlatformTransactionManager
|
|
- 贴出一部分
- AbstractPlatformTransactionManager 定义了一些基础属性 以及一些需要子类实现的方法
|
|
DataSourceTransactionManager
- xml 配置如下
|
|
-
两个属性,通常我们会配置 datasource
1 2 3 4
@Nullable private DataSource dataSource; private boolean enforceReadOnly = false;
- bean 的属性注入就不具体描述了
-
InitializingBean
-
1 2 3 4 5 6
@Override public void afterPropertiesSet() { if (getDataSource() == null) { throw new IllegalArgumentException("Property 'dataSource' is required"); } }
- 如果
dataSource
为空会抛出异常 - 默认单例会注册到 ioc 容器中.后续注册流程不具体描述
- 如果
-
-
方法注释
|
|
内部类 DataSourceTransactionObject
|
|
AbstractPlatformTransactionManager
- abstract 修饰具体定义的方法不具体展开。主要关注实现
org.springframework.transaction.PlatformTransactionManager
的几个方法
commit 方法
|
|
|
|
rollback 方法
|
|
|
|
TransactionSynchronizationManager
-
事务同步管理器
-
一些基本属性
|
|
资源方法
获取资源
|
|
判断是否存在资源
|
|
-
unwrapResourceIfNecessary
方法会将资源具体化到接口,从接口中调用方法获取具体的资源1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
static Object unwrapResourceIfNecessary(Object resource) { Assert.notNull(resource, "Resource must not be null"); Object resourceRef = resource; // unwrap infrastructure proxy if (resourceRef instanceof InfrastructureProxy) { resourceRef = ((InfrastructureProxy) resourceRef).getWrappedObject(); } if (aopAvailable) { // now unwrap scoped proxy resourceRef = ScopedProxyUnwrapper.unwrapIfNecessary(resourceRef); } return resourceRef; } private static class ScopedProxyUnwrapper { public static Object unwrapIfNecessary(Object resource) { if (resource instanceof ScopedObject) { return ((ScopedObject) resource).getTargetObject(); } else { return resource; } } }
-
doGetResource
方法去获取资源1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@Nullable private static Object doGetResource(Object actualKey) { Map<Object, Object> map = resources.get(); if (map == null) { return null; } Object value = map.get(actualKey); // Transparently remove ResourceHolder that was marked as void... // 如果资源是下面两种的其中一个就删除这个资源 if (value instanceof ResourceHolder && ((ResourceHolder) value).isVoid()) { map.remove(actualKey); // Remove entire ThreadLocal if empty... if (map.isEmpty()) { resources.remove(); } value = null; } return value; }
资源绑定
|
|
- debug 使用的是 druid 的数据源
unwrapResourceIfNecessary
方法
|
|
显然com.alibaba.druid.pool.DruidDataSource
不是InfrastructureProxy
-
aopAvailable
1 2 3
private static final boolean aopAvailable = ClassUtils.isPresent( "org.springframework.aop.scope.ScopedObject", TransactionSynchronizationUtils.class.getClassLoader());
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public static boolean isPresent(String className, @Nullable ClassLoader classLoader) { try { forName(className, classLoader); return true; } catch (IllegalAccessError err) { throw new IllegalStateException("Readability mismatch in inheritance hierarchy of class [" + className + "]: " + err.getMessage(), err); } catch (Throwable ex) { // Typically ClassNotFoundException or NoClassDefFoundError... return false; } }
看是否可以解析如果解析成功返回
true
解析失败返回false
-
ScopedProxyUnwrapper.unwrapIfNecessary
1 2 3 4 5 6 7 8 9 10
private static class ScopedProxyUnwrapper { public static Object unwrapIfNecessary(Object resource) { if (resource instanceof ScopedObject) { return ((ScopedObject) resource).getTargetObject(); } else { return resource; } } }
com.alibaba.druid.pool.DruidDataSource
不是ScopedObject
直接返回
后续就是一个map
的put
方法不具体展开
解除资源绑定
|
|
map 对象的 remove 操作
其他
- 其他几个都是使用
ThreadLocal
进行数据设置操作即可.
TransactionTemplate
-
属性
1 2
@Nullable private PlatformTransactionManager transactionManager;
前文说到
DataSourceTransactionManager
实现了PlatformTransactionManager
因此配置的时候我们有如下片段1 2 3 4
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager"/> </bean>
-
事务操作模板类图
-
org.springframework.beans.factory.InitializingBean
接口的实现1 2 3 4 5 6
@Override public void afterPropertiesSet() { if (this.transactionManager == null) { throw new IllegalArgumentException("Property 'transactionManager' is required"); } }
execute
|
|
- 原文作者:知识铺
- 原文链接:https://geek.zshipu.com/post/code/docs/Spring/TX/Spring-transaction/
- 版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可,非商业转载请注明出处(作者,原文链接),商业转载请联系作者获得授权。
- 免责声明:本页面内容均来源于站内编辑发布,部分信息来源互联网,并不意味着本站赞同其观点或者证实其内容的真实性,如涉及版权等问题,请立即联系客服进行更改或删除,保证您的合法权益。转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。也可以邮件至 sblig@126.com