SpringBoot中事务执行原理分析补充篇

72 篇文章 18 订阅
52 篇文章 3 订阅

关联博文:
SpringBoot中事务执行原理分析(一)
SpringBoot中事务执行原理分析(二)
SpringBoot中事务执行原理分析(三)
SpringBoot中事务执行原理分析(四)
SpringBoot中事务执行原理分析(五)
SpringBoot中事务执行原理分析(六)
SpringBoot中事务执行原理分析补充篇
你认真研究过Spring中的@EnableTransactionManagement注解吗?

本文是对SpringBoot中事务执行原理分析(一)的补充说明,我们详细分析一下如何判断Advisor与我们的service是否匹配。

【1】几个核心类

在前文中我们提到了BeanFactoryTransactionAttributeSourceAdvisor,其包含了Advice用于对我们的service进行增强实现事务效果。

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
	private TransactionAttributeSource transactionAttributeSource;

	private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
		@Override
		@Nullable
		protected TransactionAttributeSource getTransactionAttributeSource() {
			return transactionAttributeSource;
		}
	};
	//...
}	


//ProxyTransactionManagementConfiguration中定义了advicetransactionInterceptor

@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
		TransactionAttributeSource transactionAttributeSource,
		TransactionInterceptor transactionInterceptor) {
	BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
	advisor.setTransactionAttributeSource(transactionAttributeSource);
	advisor.setAdvice(transactionInterceptor);
	if (this.enableTx != null) {
		advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
	}
	return advisor;
}

TransactionAttributeSourcePointcut 就是我们AOP概念中的pointcut,用于判断类/方法是否匹配。如下所示其还设置了ClassFilter为TransactionAttributeSourceClassFilter用于类级别的判断。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
		setClassFilter(new TransactionAttributeSourceClassFilter());
	}
//...
}	

TransactionAttributeSource其是一个策略接口被TransactionInterceptor使用来检测元数据信息。在本文这里其实际是AnnotationTransactionAttributeSource,这个在ProxyTransactionManagementConfiguration这个配置类中有定义。

@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
//空参构造,publicMethodsOnly默认为true
	return new AnnotationTransactionAttributeSource();
}

这里要特别注意publicMethodsOnly 属性与annotationParsers 属性。前者标明是否只允许public方法,后者则是注解解析器。

public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
// 默认为true,表示只允许public方法
	this.publicMethodsOnly = publicMethodsOnly;
	if (jta12Present || ejb3Present) {
		this.annotationParsers = new LinkedHashSet<>(4);
		this.annotationParsers.add(new SpringTransactionAnnotationParser());
		if (jta12Present) {
			this.annotationParsers.add(new JtaTransactionAnnotationParser());
		}
		if (ejb3Present) {
			this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
		}
	}
	else {
	//指定注解解析器
		this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
	}
}

SpringTransactionAnnotationParser主要作用就是用来解析事务注解信息(@Transactional)。


【2】Advisor是如何匹配我们的service呢?

在AopUtils的findAdvisorsThatCanApply会对找到的Advisor进行逐一判断,鉴定其是否适用于我们的service。
在这里插入图片描述

如下所示在AopUtils的canApply方法中首先使用ClassFilter进行判断,然后获取到MethodMatcher 对class和method进行遍历循环判断。

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
	Assert.notNull(pc, "Pointcut must not be null");
	// 首先使用classFilter进行判断
	if (!pc.getClassFilter().matches(targetClass)) {
		return false;
	}

//获取到MethodMatcher 
	MethodMatcher methodMatcher = pc.getMethodMatcher();
	if (methodMatcher == MethodMatcher.TRUE) {
		// No need to iterate the methods if we're matching any method anyway...
		return true;
	}

//判断是否为引入方法匹配器
	IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
	if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
		introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
	}

//获取到目标类、超类
	Set<Class<?>> classes = new LinkedHashSet<>();
	if (!Proxy.isProxyClass(targetClass)) {
		classes.add(ClassUtils.getUserClass(targetClass));
	}
	classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));


//对目标类与超类的所有方法进行遍历、判断
	for (Class<?> clazz : classes) {
		Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
		for (Method method : methods) {
			if (introductionAwareMethodMatcher != null ?
					introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
					methodMatcher.matches(method, targetClass)) {
				return true;
			}
		}
	}

	return false;
}

① 类级别的判断

也就是下面这句代码, 前面我们提到过TransactionAttributeSourcePointcut中的classFilter是TransactionAttributeSourceClassFilter

pc.getClassFilter().matches(targetClass)

其是TransactionAttributeSourcePointcut的成员内部类(非静态内部类),我们看下其matches方法:

@Override
public boolean matches(Class<?> clazz) {
	if (TransactionalProxy.class.isAssignableFrom(clazz) ||
			PlatformTransactionManager.class.isAssignableFrom(clazz) ||
			PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
		return false;
	}
	TransactionAttributeSource tas = getTransactionAttributeSource();
	return (tas == null || tas.isCandidateClass(clazz));
}

也就是说如果是TransactionalProxyPlatformTransactionManager或者PersistenceExceptionTranslator,直接返回false。否则判断TransactionAttributeSource 是否为null或者TransactionAttributeSourceisCandidateClass方法是否为true。

如下所示,其将会遍历持有的TransactionAnnotationParser ,触发其isCandidateClass方法。

//AnnotationTransactionAttributeSource#isCandidateClass
@Override
public boolean isCandidateClass(Class<?> targetClass) {
	for (TransactionAnnotationParser parser : this.annotationParsers) {
		if (parser.isCandidateClass(targetClass)) {
			return true;
		}
	}
	return false;
}

本文我们只有一个SpringTransactionAnnotationParser,我们继续看SpringTransactionAnnotationParser解析器的isCandidateClass方法。

@Override
public boolean isCandidateClass(Class<?> targetClass) {
	return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
}

其只是触发了AnnotationUtils的isCandidateClass方法,如下所示可以说基本对我们的service来说都返回true。

public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
//如果注解名称以java.开头,直接返回true
	if (annotationName.startsWith("java.")) {
		return true;
	}
	//如果clazz.getName以java.开头或者是Ordered类型
	if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
		return false;
	}
	//直接返回true
	return true;
}

② 方法级别的判断

OK,我们往下再看方法级别如何判断。这里触发的是TransactionAttributeSourcePointcut的matches方法。其获取到TransactionAttributeSource ,如果tas为null或者使用tas获取到的事务属性信息不为null,则返回true。

@Override
public boolean matches(Method method, Class<?> targetClass) {
	TransactionAttributeSource tas = getTransactionAttributeSource();
	return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}

如下图所示,AbstractFallbackTransactionAttributeSourcecomputeTransactionAttribute
方法中首先会根据publicMethodsOnly属性和方法的修饰符进行判断,如果非public则直接返回null(默认情况下publicMethodsOnly=true)。

然后将会从当前类进行级联查找方法上的事务注解信息,也就是说你的service如果实现了接口,那么在接口的方法上添加@Transactional(rollbackFor = Exception.class)也是OK的。
在这里插入图片描述
如何获取方法上的注解信息呢,这里就用到了SpringTransactionAnnotationParser,其将会级联检索方法上的事务注解。获取到的事务注解信息如下所示:
在这里插入图片描述

确定了Advisor与我们的service匹配后,就可以为我们的service创建代理进行实现事务增强了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Spring Boot是一个用于构建Java应用程序的开源框架,它简化了Spring应用程序的开发过程。事务Spring Boot非常重要的一个特性,它可以确保数据库操作的一致性和完整性。下面是Spring Boot事务底层原理的介绍: Spring Boot使用了Spring框架事务管理器来实现事务功能。事务管理器是一个接口,它定义了一些方法来管理事务的开始、提交和回滚等操作。在Spring Boot,常用的事务管理器有两种:JpaTransactionManager和DataSourceTransactionManager。 JpaTransactionManager是用于管理JPA(Java Persistence API)事务事务管理器。它通过与JPA提供商(如Hibernate)进行交互,来实现对数据库的事务管理。 DataSourceTransactionManager是用于管理传统的关系型数据库(如MySQL、Oracle等)事务事务管理器。它通过与数据源进行交互,来实现对数据库的事务管理。 在Spring Boot,我们可以通过在方法上添加@Transactional注解来启用事务。当方法被调用时,Spring会自动创建一个事务,并在方法执行结束后根据方法的执行结果来决定是提交事务还是回滚事务事务的隔离级别、传播行为等属性可以通过@Transactional注解的属性来进行配置。例如,可以设置隔离级别为READ_COMMITTED,传播行为为REQUIRED等。 总结一下,Spring Boot事务底层原理是通过事务管理器来管理事务的开始、提交和回滚等操作。我们可以通过@Transactional注解来启用事务,并通过注解的属性来配置事务的属性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

流烟默

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值