开发者如果要正确使用Spring事务,必须对其背后的实现机制有一个深入的理解,知其然,知其所以然。本文将从源码实现分析的角度来解读Spring事务的运行机制,行文以TransactionAttributeSourceAdvisor、TransactionManager、TransactionInterceptor这三个关键类为主线,一步步探索其源码实现。
-
@Transactional属性定义
声明式事务的在使用时通过@Transactional注解来定义事务属性,我们先看一下其属性:
- SpringTransactionAnnotationParser 属性解析
@Transactional 定义完要使用的事务属性后,应用通过SpringTransactionAnnotationParser方法对@Transactional 进行解析获取事务属性,封装到RuleBasedTransactionAttribute对象,方法源码如下:
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
ArrayList<RollbackRuleAttribute> rollBackRules = new ArrayList<RollbackRuleAttribute>();
Class<?>[] rbf = attributes.getClassArray("rollbackFor");
for (Class<?> rbRule : rbf) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] rbfc = attributes.getStringArray("rollbackForClassName");
for (String rbRule : rbfc) {
RollbackRuleAttribute rule = new RollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
Class<?>[] nrbf = attributes.getClassArray("noRollbackFor");
for (Class<?> rbRule : nrbf) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
String[] nrbfc = attributes.getStringArray("noRollbackForClassName");
for (String rbRule : nrbfc) {
NoRollbackRuleAttribute rule = new NoRollbackRuleAttribute(rbRule);
rollBackRules.add(rule);
}
rbta.getRollbackRules().addAll(rollBackRules);
return rbta;
}
RuleBasedTransactionAttribute 保存事务定义的各种属性,如超时时间、隔离级别、传播属性等,我们通过@Transactional定义的事务属性最终都是保存在这个对象中,继承关系如下
3.如何寻找@Transactional 的位置
通过1、2我们知道了属性如何定义和存放,可是应用是如何在目标类上寻找到对应的@Transactional 在哪里的呢?
AbstractFallbackTransactionAttributeSource#computeTransactionAttribute方法定义了寻找@Transactional的先后顺序
由这段代码可以看出,虽然@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上,但是其先后寻找Transactional的优先级是不一样的。
另外从开头这段代码(如下)我们可以明白一点:@Transactional 注解只能使用在public方法上
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
spring属性解析AnnotationTransactionAttributeSource方法中,该类通过ProxyTransactionManagementConfiguration 来完成初始化
注解解析容器中有spring事务注解解析类SpringTransactionAnnotationParser
解析@Transactional注解属性的入口