Spring实现@Transactional的核心原理还是AOP的动态代理:
加了@Transactional注解之后,就对这个动态代理插入了一堆事务管理的增强逻辑,开始执行方法之前先开启事务,方法中有报错就回滚事务,如果没有报错就提提交事务。
依赖了Spring Boot1.5.9之后,会自动依赖引入Spring-tx-4.3.13.RELEASE.jar
org.springframework.transaction.interceptor
这个包下的TransactionInterceptor 是AOP 实现事务的核心源码
@Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();
}
});
}
invokeWithinTransaction 这个方法的实现是在父类TransactionAspectSupport里
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
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 {
// 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();
//这行代码,其实相当于是去调用你的那个RefillDataCenterService.finishRefillData()方法
}
catch (Throwable ex) {
// target invocation exception
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)) {
// 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.
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
}
});
// Check result state: It might indicate a Throwable to rethrow.
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;
}
}
}
TransactionIntercepor其实就是如果我们给我们的service组件加了@Transactional注解之后,就会对我们的这个service组件里的方法在调用的时候,就会先走这个TransactionoIntercepor的拦截
事务拦截器,拦截我们对@Transactional注解标注的类中的方法的调用,finishRfillData()方法之前,就会先走这个拦截器
中
@Transactional(rollbackFor = Exception.class)
public void finishRefillData(RefillRequest refillRequest) {
在这个拦截器里,就可以给我们先打开事务,然后再执行我么你的finishRefillData()方法,接着根据方法的执行结果,报错就回滚事务,没报错就提交事务
TransactionIntercepor.invoke()方法,这个里面调用了invokeWithinTransaction()方法,核心的事务控制的逻辑都在invokeWithinTransaction()方法中,invokeWithinTransaction()方法其实是父类TransactionAspectSupport(Aspect这个名词就可以看出来了,这个东西一定是跟Spring AOP机制是有关系的,Aspect切面的意思,就是spring AOP的核心概念)
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
上面那行代码其实是核心中的核心,这行代码顾名思义,其实就是如果你使用了@Transactional注解之后,意思就是要给这个方法开启事务,此时就会给你开启一个事务,创建事务
retVal = invocation.proceedWithInvocation();
这行代码,其实相当于是去调用你的那个RefillDataCenterService.finishRefillData()方法
completeTransactionAfterThrowing(txInfo, ex);
这行代码是什么意思呢,如果你的RefillDataCenterService.finishRefillData()方法报错了,抛了个异常出来,此时就会回滚事务
commitTransactionAfterReturning(txInfo);
如果没有报错的话,就会提交你的事务,完成全部逻辑的执行