细节知多少 - spring boot transaction解析之阶段二 访问service类的@Transactional方法实现事务的阶段

本文深入解析Spring Boot中访问带@Transactional注解的Service类方法时的事务处理过程,包括代理类方法、事务入口点和事务管理的核心逻辑。通过分析TransactionInterceptor和TransactionAspectSupport类,理解事务的开启、提交、回滚机制。
摘要由CSDN通过智能技术生成

概述

原文地址:细节知多少 - spring boot transaction解析之阶段二 访问service类的@Transactional方法实现事务的阶段

spring boot transaction我们平时用着非常简单,只需要在service方法上声明@Transactional就可以了。但是要知道,简单的背后是不简单,只是很多东西spring框架帮我们做好了。如果想进阶,想进步,想弄懂,想学习,需要接近它,了解它,弄懂它,最好的方法莫过于debug它的源码了。

笔者把spring boot transaction的整个过程分为两个阶段

  1. 带有@Transactional方法的service类生成代理类的阶段
  2. 访问service类的@Transactional方法实现事务的阶段
    本文我们产出第二阶段:访问service类的@Transactional方法实现事务的阶段

技术栈

spring boot 1.5.10
spring framework 4.3.14

带着问题学习

带着问题学习往往起到更好的效果

问题:

1. 平时总是spring默认的事务只有运行时异常才回滚,为什么
2. 事务的savepoint是什么
3. 如何做到多个数据操作的事务提交和回滚的

http 访问

http://localhost:2372/user/updateSchoolName?schoolName=vl&studentId=3

当从controller访问service的方法时,因为controller引用的service指向的代理类,所以进去代理类的方法,如下

代理类的方法

这里我们以UserService的updateSchoolName为例,下面代码为UserService的updateSchoolName方法生成的代理类的方法,var10000即是DynamicAdvisedInterceptor类

final void CGLIB$updateSchoolName$4(String var1, long var2) {
	super.updateSchoolName(var1, var2);
}

public final void updateSchoolName(String var1, long var2) {
	try {
		MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
		if (var10000 == null) {
			CGLIB$BIND_CALLBACKS(this);
			var10000 = this.CGLIB$CALLBACK_0;
		}

		if (var10000 != null) {
			var10000.intercept(this, CGLIB$updateSchoolName$4$Method, new Object[]{var1, new Long(var2)}, CGLIB$updateSchoolName$4$Proxy);
		} else {
			super.updateSchoolName(var1, var2);
		}
	} catch (Error | RuntimeException var4) {
		throw var4;
	} catch (Throwable var5) {
		throw new UndeclaredThrowableException(var5);
	}
}

从这个方法我们知道,程序会进去var10000.intercept,即DynamicAdvisedInterceptor.intercept方法,我们看看这个方法内部代码

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
	Object oldProxy = null;
	Class<?> targetClass = null;
	Object target = null;
	try {
		if (this.advised.exposeProxy) {
			oldProxy = AopContext.setCurrentProxy(proxy);
		}
		
		List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
		Object retVal;
		
		if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
			······
		}
		else {
			retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); // (1)
		}
		retVal = processReturnType(proxy, target, method, retVal);
		return retVal;
	}
	finally {
		······
	}
}

在这个方法中,会创建CglibMethodInvocation实例,proxy, target,chain等参数传给它,然后调动proceed()方法。这里运用了一个设计模式:责任链模式的变种,CglibMethodInvocation拥有一个MethodInterceptor集合,通过proceed()方法执行interceptor chain。proceed()会遍历interceptorsAndDynamicMethodMatchers(其实就是interceptor集合)从而执行每个interceptor.invoke(MethodInvocation)自身的逻辑,因为这个时候MethodInvocation会传递给invoke方法,所以每一个invoke方法内部都会执行MethodInvocation.proceed(),从而这样形成了一个链式的调用关系。我们看下链式代码结构

MethodInvocation类
public Object proceed() throws Throwable {
    // 链式调用终结点
    if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
        return invokeJoinpoint();
    }
    // 从interceptor集合中获取一个interceptor
    Object interceptorOrInterceptionAdvice =
            this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
    // 调用这个interceptor.invoke方法,开始走链了
    return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
MethodInterceptor类
public interface MethodInterceptor extends Interceptor {
    
    Object invoke(MethodInvocation invocation) throws Throwable;
}

MethodInterceptor实现类
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值