文章目录
- 1.Spring 事务工作流程
- 2.Spring 事务源码分析
- 2.1 创建代理对象
- 3.Spring 事务执行分析
- 3.1 事务执行源码分析
1.Spring 事务工作流程
- 获取到切面方法, 和所有切面匹配, 事务属性放入缓存attributeCache
- 创建Aop代理对象, 选择Jdk 和 Cglib
事务处理:
- 缓存拿到事务属性
- 创建并开启事务
- 执行业务逻辑
- 提交或者回滚事务
2.Spring 事务源码分析
refresh()
finishBeanFactoryInitialization()
preInstantiateSingletons()
doGetBean()
doCreateBean()
initializeBean()
applyBeanPostProcessorsAfterInitialization()
2.1 创建代理对象
获取切面列表
findCandidateAdvisors()
findEligibleAdvisors(): 开始匹配对应的切面
canApply(): 匹配对应的切面
如果匹配了, 会将事务的属性加入到attributeCache缓存中
getTransactionAttribute()
从 element 对象中获取到@Transactional 注解
getTransactionAttribute()
创建Aop对象
3.Spring 事务执行分析
Cglib 代理对象进行
3.1 事务执行源码分析
- 从缓存中获取事务相关属性
- 创建事务: 获取事务, 设置事务属性, 开启事务
- 执行业务逻辑
- 回滚事务: 判断异常类型判断是否回滚, 执行回滚
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//获取我们的事务属源对象
TransactionAttributeSource tas = getTransactionAttributeSource();
//通过事务属性源对象获取到我们的事务属性信息
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//获取我们配置的事务管理器对象
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//从tx属性对象中获取出标注了@Transactionl的方法描述符
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
//处理声明式事务
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
//有没有必要创建事务
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
//调用钩子函数进行回调目标方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
//抛出异常进行回滚处理
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清空我们的线程变量中transactionInfo的值
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
//编程式事务
else {
// 这里不是我们的重点,省略...
}
}
invokeWithinTransaction() 中获取事务的入口
从 attributeCache 获取事务的缓存数据
创建事务
获取事务状态
doGetTransaction(): 获取事务
protected void doBegin(Object transaction, TransactionDefinition definition) {
//强制转化事务对象
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
try {
//判断事务对象没有数据库连接持有器
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
//通过数据源获取一个数据库连接对象
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
//把我们的数据库连接包装成一个ConnectionHolder对象 然后设置到我们的txObject对象中去
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
//标记当前的连接是一个同步事务
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
//为当前的事务设置隔离级别
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
//关闭自动提交
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}
//判断事务为只读事务
prepareTransactionalConnection(con, definition);
//设置事务激活
txObject.getConnectionHolder().setTransactionActive(true);
//设置事务超时时间
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
// 绑定我们的数据源和连接到我们的同步管理器上 把数据源作为key,数据库连接作为value 设置到线程变量中
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
}
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
//释放数据库连接
DataSourceUtils.releaseConnection(con, obtainDataSource());
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
invokeWithinTransaction() 获取到txInfo 对象
执行逻辑
回滚事务
如果抛出的异常类型,和事务定义的异常类型匹配,证明该异常需要捕获。