spring事务源码分析
1、事务如何生效?
@EnableTransactionManagement 事务是如何起作用的,通过代理对象执行方法。 ProxyTransactionManagementConfiguration 该类相当于给系统注入了一个事务的拦截器,通过拦截器来拦截是否需要支持事务。该类非常重要,对于事务的分析很有帮助。
2、事务执行的代码
import org.springframework.transaction.TransactionSystemException;
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// 如果transaction attribute为空,该方法就是非事务(非编程式事务)
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
// 标准声明式事务:如果事务属性为空 或者 非回调偏向的事务管理器
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// 这里就是一个环绕增强,在这个proceed前后可以自己定义增强实现
// 方法执行
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 根据事务定义的,该异常需要回滚就回滚,否则提交事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {//清空当前事务信息,重置为老的
cleanupTransactionInfo(txInfo);
}//返回结果之前提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
// 编程式事务:(回调偏向)
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr,
new TransactionCallback<Object>() {
@Override
public Object doInTransaction(TransactionStatus status) {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {// 如果该异常需要回滚
if (txAttr.rollbackOn(ex)) {
// 如果是运行时异常返回
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}// 如果是其它异常都抛ThrowableHolderException
else {
throw new ThrowableHolderException(ex);
}
}// 如果不需要回滚
else {
// 定义异常,最终就直接提交事务了
throwableHolder.throwable = ex;
return null;
}
}
finally {//清空当前事务信息,重置为老的
cleanupTransactionInfo(txInfo);
}
}
});
// 上抛异常
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
3、事务失效的几种原因
- 数据库引擎不支持事务
- 对象没有被Spring管理
- 方法不是public的
- 类内部自身调用问题
- 数据源没有配置事务管理器
- 主动声明不支持事务
- 捕获了异常
- 抛出的异常不适合
- 切面引起的事务不生效
总结:
最有可能发生事务不生效的场景是: 类内部自身调用问题,捕获了异常