警告
本文最后更新于 2020-12-07,文中内容可能已过时。
spring源码系列文章,示例代码的中文注释,均是 copy 自 https://gitee.com/wlizhi/spring-framework 。
链接中源码是作者从 github 下载,并以自身理解对核心流程及主要节点做了详细的中文注释。
[17 声明式事务执行流程源码分析] 中已经列举,通过 getTransactionAttribute() 获取到了方法上事务注解的一些信息。
来到其源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 获取事务注解属性
if (method.getDeclaringClass() == Object.class) {
return null;
}
// 先从缓存中拿。如果一个方法的事务注解信息被获取过,就会将其缓存到一个并发安全的map中。后面再获取就从这个缓存中获取。
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// 省略...
}else {
// TODO 获取事务注解属性,放入缓存。
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {// 放入缓存
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
// 省略...
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
}
|
先从缓存中获取,如果可以获取到直接返回。否则调用 computeTransactionAttribute() 从方法上进行事务注解信息的获取。
来到 computeTransactionAttribute() 源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// Don't allow no-public methods as required.
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
// TODO 重点:查找事务属性,首先从目标方法上查找
// First try is the method in the target class.
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// 如果目标方法上查找不到,从目标类上查找。
// Second try is the transaction attribute on the target class.
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
// 如果方法上找不到,到接口方法、接口上找对应注解。
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
}
|
查找注解信息的顺序:
- 从缓存中获取,如果获取得到,就返回。
- 从目标对象的方法上找,如果能查找到注解信息,就返回。
- 从目标对象类上查找注解信息,如果查找到,就返回。
- 从目标接口、父类方法上查找注解信息,如果查找到,就返回。
- 从目标接口、父类上查找注解信息,如果查找到,就返回。
- 如果没有查找到注解信息,就返回null。
继续向下追踪源码就能看到,无论是从方法上获取、还是从类上获取注解信息,最终都是调用到 determineTransactionAttribute()。
源码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
// TODO 循环所有的解析器,如果有解析器解析出的结果不为空,则直接返回事务属性,解析器列表是在当前对象构造函数时,加载的
// 如果是注解方式,用到的注解解析器是:SpringTransactionAnnotationParser
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
return null;
}
}
|
遍历 annotationParsers,并调用 preTransactionAnnotation(),在 [14 声明式事务中XML配置及注解方式的注册入口]
中已经说明,在事务注解支持的入口,注册了 AnnotationTransactionAttributeSource,其中封装了一个解析类 SpringTransactionAnnotationParser,这个类就负责事务注解的解析。
SpringTransactionAnnotationParser 是 TransactionAnnotationParser 的其中一个实现。
以下是 SpringTransactionAnnotationParser.parseTransactionAnnotation() 源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// TODO 重点:从方法上查找@Transactional注解,AnnotatedElement是Method、Field的超类
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
// TODO 重点:如果从方法上查找到了@Transactional注解,则解析注解中的各个属性值
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
}
|
AnnotatedElement是 Method、Class的共同父类,是一个接口。
上面源码中,首先从方法、或者类上查找 @Transactional 注解,如果查找到,调用 parseTransactionAnnotation(),进行解析封装。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
// TODO 此方法主要做对象类型转换,将AnnotationAttributes中的属性赋值到RuleBasedTransactionAttribute中,返回。
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
// 解析 @Transactional 中的属性:propagation、isolation、timeout、readOnly、value。
// 解析后将其封装到 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"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
}
|
创建一个 RuleBasedTransactionAttribute,依次解析注解中 propagation、isolation、timeout、readOnly、value 等属性,将其封装到 RuleBasedTransactionAttribute 中返回。
最终返回后,会放入到 attributeCache 中,后面在获取,就会从缓存中获取。