Spring源码解读:@Transactional原理(2)

本文深入分析了Spring框架中@Transactional注解的执行逻辑,包括类图、类间关系、核心方法TransactionInterceptor#invoke的具体实现等,揭示了如何通过AOP实现事务管理。


前言

在上一篇Spring源码解读:@Transactional注解是如何生效的里面,我们讲解了咱们这个AOP 的advisor(BeanFactoryTransactionAttributeSourceAdvisor)中的pointCut(TransactionAttributeSourcePointcut)的逻辑,主要靠matches方法来判断advisor是否需要生效。那么今天就来分析下BeanFactoryTransactionAttributeSourceAdvisor中的advice(TransactionInterceptor)的具体执行逻辑。

一、类图

TransactionalInterceptor的类结构图

可以看到TransactionInterceptor确实是一个Advice,但是其实Advice和Interceptor这两个接口类,并没有方法需要实现,更像是标志类,或者说是为了实现动态而设计的类。

二、类关系

1. TransactionStatus

public class DefaultTransactionStatus extends AbstractTransactionStatus {
   
   

	@Nullable
	private final Object transaction;

	private final boolean newTransaction;

	private final boolean newSynchronization;

	private final boolean readOnly;

	private final boolean debug;

	@Nullable
	private final Object suspendedResources;
}

其中最重要的就是newTransaction和newSynchronization。分别表示是否是新事务和是否是是否是第一次同步操作。
具体作用:newTransaction的作用比较简单,就是标志当前使用的事务是否是新的事务,具体用在判断是否需要commit;而newSynchronization是用来控制TransactionSynchronizationManager类的init和clear的,只有为true才会进行,同时用来控制钩子函数是否执行。具体有如下的几个钩子函数(AbstractPlatformTransactionManager):

钩子函数1:triggerBeforeCommit
钩子函数2:triggerBeforeCompletion
钩子函数3:triggerAfterCommit
钩子函数4:triggerAfterCompletion

其实正常能够commit的时候执行的时候,钩子函数1和钩子函数2执行只有先后顺序,钩子函数3和钩子函数4执行也只有先后顺序,中间没有插入其他关于事务的逻辑。

newTransaction取值为true或者false的时机好理解
newSynchronization在同一线程内只有第一次调用newTransaction为true的时候,才为true,其余时候都是false

也就是每个加了@Transactional注解的方法,都会对应生成TransactionStatus对象,但是在同一个线程内只有第一个TransactionStatus对象的newSynchronization才为true

三、MethodInterceptor#invoke

1.方法拦截器?

public interface MethodInterceptor extends Interceptor {
   
   

	/**
	 * Implement this method to perform extra treatments before and
	 * after the invocation. Polite implementations would certainly
	 * like to invoke {@link Joinpoint#proceed()}.
	 * @param invocation the method invocation joinpoint
	 * @return the result of the call to {@link Joinpoint#proceed()};
	 * might be intercepted by the interceptor
	 * @throws Throwable if the interceptors or the target object
	 * throws an exception
	 */
	Object invoke(MethodInvocation invocation) throws Throwable;
}

按照invoke上面这方法的说明,就是该实现应该写成Joinpoint#proceed()的invoke的方法,也就是在joinpoint.proceed()逻辑的前后加上自己的逻辑。例如在基于AOP+Redis实现一个简单的频控拦截器中的拦截方法实现逻辑。

2.TransactionInterceptor#invoke

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);
	}

可以看到主要实现的是invokeWithTransaction方法

3. TransactionAspectSupport#invokeWithinTransaction

结合上面的类图结构可以看到TransactionInterceptor继承了TransactionAspectSupport,所以TransactionInterceptor#invoke的实际逻辑走的是TransactionAspectSupport#invokeWithinTransaction
咱们只挑重点代码分析。

			// 创建事务/获取事务;事务信息txInfo可能为空
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			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.
				
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值