- 前言
- 第一部分 核心实现
- 第 1 章 Spring 整体架构和环境搭建
- 第 2 章 容器的基本实现
- 第 3 章 默认标签的解析
- 第 4 章 自定义标签的解析
- 第 5 章 bean 的加载
- 第 6 章 容器的功能扩展
- 第 7 章 AOP
- 第二部分 企业应用
- 第 8 章 数据库连接 JDBC
- 第 9 章 整合 MyBatis
- 第 10 章 事务
- 第 11 章 SpringMVC
- 第 12 章 远程服务
- 第 13 章 Spring 消息
10.3 事务增强器
TransactionInterceptor 支撑着整个事务功能的架构,逻辑还是相对复杂的,那么现在我们切入正题来分析此拦截器是如何实现事务特性的。TransactionInterceptor 类继承自 MethodInterceptor,所以调用该类是从其 invoke 方法开始的,首先预览下这个方法:
public Object invoke(final MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass
(invocation.getThis()) : null);
//获取对应事务属性
final TransactionAttribute txAttr =
getTransactionAttributeSource().getTransactionAttribute (invocation.
getMethod(), targetClass);
//获取 beanFactory 中的 transactionManager
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
//构造方法唯一标识(类.方法,如 service.UserServiceImpl.save)
final String joinpointIdentification = methodIdentification (invocation.
getMethod(), targetClass);
//声明式事务处理
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransaction
Manager)) {
//创建 TransactionInfo
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpoint
Identification);
Object retVal = null;
try {
//执行被增强方法
retVal = invocation.proceed();
}
catch (Throwable ex) {
//异常回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
//清除信息
cleanupTransactionInfo(txInfo);
}
//提交事务
commitTransactionAfterReturning(txInfo);
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();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
return new ThrowableHolder(ex);
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result: It might indicate a Throwable to rethrow.
if (result instanceof ThrowableHolder) {
throw ((ThrowableHolder) result).getThrowable();
}
else {
return result;
}
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
}
}
从上面的函数中,我们尝试整理下事务处理的脉络,在 Spring 中支持两种事务处理的方式,分别是声明式事务处理与编程式事务处理,两者相对于开发人员来讲差别很大,但是对于 Spring 中的实现来讲,大同小异。在 invoke 中我们也可以看到这两种方式的实现。考虑到对事务的应用比声明式的事务处理使用起来方便,也相对流行些,我们就以此种方式进行分析。对于声明式的事务处理主要有以下几个步骤。
(1)获取事务的属性。
对于事务处理来说,最基础或者说最首要的工作便是获取事务属性了,这是支撑整个事务功能的基石,如果没有事务属性,其他功能也无从谈起,在分析事务准备阶段时我们已经分析了事务属性提取的功能,大家应该有所了解。
(2)加载配置中配置的 TransactionManager。
(3)不同的事务处理方式使用不同的逻辑。
对于声明式事务的处理与编程式事务的处理,第一点区别在于事务属性上,因为编程式的事务处理是不需要有事务属性的,第二点区别就是在 TransactionManager 上,CallbackPreferring PlatformTransactionManager 实现 PlatformTransactionManager 接口,暴露出一个方法用于执行事务处理中的回调。所以,这两种方式都可以用作事务处理方式的判断。
(4)在目标方法执行前获取事务并收集事务信息。
事务信息与事务属性并不相同,也就是 TransactionInfo 与 TransactionAttribute 并不相同, TransactionInfo 中包含 TransactionAttribute 信息,但是,除了 TransactionAttribute 外还有其他事务信息,例如 PlatformTransactionManager 以及 TransactionStatus 相关信息。
(5)执行目标方法。
(6)一旦出现异常,尝试异常处理。
并不是所有异常,Spring 都会将其回滚,默认只对 RuntimeException 回滚。
(7)提交事务前的事务信息清除。
(8)提交事务。
上面的步骤分析旨在让大家对事务功能与步骤有个大致的了解,具体的功能还需要详细地分析。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论