Spring代理默认实现查询:@Transactional对应方法包装调用逻辑源码
Spring @Transactional 代理方法包装核心源码
以下源码基于Spring 5.3.x/6.x 稳定版本,核心逻辑全版本通用。
事务拦截入口
Spring 声明式事务基于AOP实现,对原始方法的拦截入口为 org.springframework.transaction.interceptor.TransactionInterceptor 的 invoke 方法,是所有标注 @Transactional 方法的执行入口:
@Override @Nullable public Object invoke(MethodInvocation invocation) throws Throwable { // 获取被代理的目标类 Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // 传入原始方法执行回调,进入事务包装逻辑 return invokeWithinTransaction(invocation.getMethod(), targetClass, new CoroutinesInvocationCallback() { @Override @Nullable public Object proceedWithInvocation() throws Throwable { // 执行AOP调用链,最终会调用被代理的原始方法 return invocation.proceed(); } @Override public Object getTarget() { return invocation.getThis(); } @Override public Object[] getArguments() { return invocation.getArguments(); } }); }
事务包装核心逻辑
invokeWithinTransaction 是父类 TransactionAspectSupport 提供的核心方法,实现了事务开启、异常回滚、正常提交的全流程包装,核心片段如下:
@Nullable protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, final InvocationCallback invocation) throws Throwable { // 1. 读取方法上@Transactional注解的事务属性配置 TransactionAttributeSource tas = getTransactionAttributeSource(); final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null); // 2. 匹配对应的事务管理器 final TransactionManager tm = determineTransactionManager(txAttr); // 省略响应式事务、回调优先事务管理器的分支处理,核心通用逻辑如下 PlatformTransactionManager ptm = asPlatformTransactionManager(tm); final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) { // 3. 判断是否需要开启新事务,生成事务状态信息 TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification); Object retVal; try { // 4. 调用被代理的原始业务方法 retVal = invocation.proceedWithInvocation(); } catch (Throwable ex) { // 5. 业务方法抛出异常,判断是否符合回滚规则,符合则回滚事务 completeTransactionAfterThrowing(txInfo, ex); throw ex; } finally { // 6. 清理当前线程绑定的事务上下文 cleanupTransactionInfo(txInfo); } // 7. 业务方法正常返回,提交事务 commitTransactionAfterReturning(txInfo); return retVal; } // 省略回调优先事务管理器的分支,核心包装逻辑与上述一致 }
核心逻辑说明
- 原始方法的唯一调用入口为
invocation.proceedWithInvocation(),前后所有逻辑都是Spring附加的事务增强能力 - 如果使用JDK动态代理,
invocation.proceed()最终会调用JDK代理的目标方法;如果使用CGLIB代理,会调用CGLIB生成的代理子类的目标方法 - 事务上下文默认绑定在当前线程,存储在
TransactionSynchronizationManager的ThreadLocal变量中
内容的提问来源于stack exchange,提问作者Hynek Hrabík
相关产品推荐
相关产品推荐

