在Service层的方法上加上@Transactional注解,在发生错误时,方法会抛出运行时异常,随即Spring会自动回滚事务。
Spring实现事务回滚的流程如下:
1、通过cglib,将方法上加了@Transactional注解的类创建生成代理对象
2、Controller在调用Service方法时,由于Service是代理对象,便会进入到DynamicAdvisedInterceptor类的intercept方法中,源码如下
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class> targetClass = (target != null ? target.getClass() : null);
List
这段代码注意这一行,chain里只有一个对象,即TransactionInterceptor,下面会用到这个对象
List
3、继续一层层方法进入,我们就会来到TransactionInterceptor的invoke方法,先获取被代理的对象类targetClass,随后进入核心类TransactionAspectSupport的invokeWithinTransaction方法中
public Object invoke(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, invocation::proceed);
}
4、TransactionAspectSupport的invokeWithinTransaction方法中,实现回滚的就是这几行,try catch包住要执行的事务方法,如果发生报错,就在catch中回滚事务
Object retVal;
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;
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)