spring-reading./spring-transaction/spring-transaction-springTr.../README.md

250 lines
11 KiB
Markdown
Raw Permalink Normal View History

2024-05-28 07:22:28 +00:00
## TransactionAnnotationParser
- [TransactionAnnotationParser](#transactionannotationparser)
- [一、基本信息](#一基本信息)
- [二、基本描述](#二基本描述)
- [三、主要功能](#三主要功能)
- [四、接口源码](#四接口源码)
- [五、主要实现](#五主要实现)
- [六、类关系图](#六类关系图)
- [七、最佳实践](#七最佳实践)
- [八、源码分析](#八源码分析)
### 一、基本信息
✒️ **作者** - Lex 📝 **博客** - [掘金](https://juejin.cn/user/4251135018533068/posts) 📚 **源码地址
** - [github](https://github.com/xuchengsheng/spring-reading)
### 二、基本描述
`TransactionAnnotationParser` 接口是 Spring Framework 中的一个接口,用于定义解析事务相关注解的标准方式,我们可以通过实现该接口来自定义解析特定事务注解的逻辑,并将其转换为
Spring 内部的事务配置对象,以实现更灵活的事务管理。
### 三、主要功能
1. **解析事务注解**
+ 该接口定义了解析事务相关注解的方法,我们可以通过实现该方法来提取注解中的属性信息。
2. **支持多种注解**
+ 允许实现类支持多种事务相关的注解,不仅限于 `@Transactional`,这使得接口更加灵活和通用。
3. **自定义扩展**
+ 根据自己的需求实现该接口,并自定义解析逻辑,以满足特定场景下的事务管理需求,从而扩展 Spring Framework 的事务管理功能。
### 四、接口源码
用于解析已知的事务注解类型。它包括一个默认方法用于确定给定类是否是事务注解的候选类,以及一个方法用于解析给定方法或类上的事务注解并将其转换为
Spring 框架的事务属性对象。该接口的实现类可用于支持特定的事务注解类型,如 Spring 的 `@Transactional`、JTA 1.2
`javax.transaction.Transactional` 或 EJB3 的 `javax.ejb.TransactionAttribute`
```java
/**
* 已知事务注解类型解析的策略接口。
* {@link AnnotationTransactionAttributeSource} 委托给此类解析器,以支持特定的注解类型,例如 Spring 的 {@link Transactional}、JTA 1.2 的 {@link javax.transaction.Transactional} 或 EJB3 的 {@link javax.ejb.TransactionAttribute}。
*
* @author Juergen Hoeller
* @since 2.5
* @see AnnotationTransactionAttributeSource
* @see SpringTransactionAnnotationParser
* @see Ejb3TransactionAnnotationParser
* @see JtaTransactionAnnotationParser
*/
public interface TransactionAnnotationParser {
/**
* 确定给定类是否是此 {@code TransactionAnnotationParser} 的注解格式中的事务属性候选类。
* <p>如果此方法返回 {@code false},则给定类上的方法将不会被遍历用于 {@code #parseTransactionAnnotation} 内省。
* 返回 {@code false} 是针对未受影响的类的优化,而 {@code true} 意味着类需要对给定类上的每个方法进行完整的内省。
* @param targetClass 要内省的类
* @return 如果已知该类在类或方法级别上没有事务注解,则返回 {@code false};否则返回 {@code true}。默认实现返回 {@code true},导致常规内省。
* @since 5.2
*/
default boolean isCandidateClass(Class<?> targetClass) {
return true;
}
/**
* 根据此解析器理解的注解类型,解析给定方法或类的事务属性。
* <p>本质上,这将已知的事务注解解析为 Spring 的元数据属性类。如果方法/类不是事务性的,则返回 {@code null}。
* @param element 被注解的方法或类
* @return 配置的事务属性,如果没有找到则返回 {@code null}
* @see AnnotationTransactionAttributeSource#determineTransactionAttribute
*/
@Nullable
TransactionAttribute parseTransactionAnnotation(AnnotatedElement element);
}
```
### 五、主要实现
1. **SpringTransactionAnnotationParser**
+ 用于解析 Spring Framework 中的 `@Transactional` 注解,它能够将 `@Transactional` 注解中的属性信息提取出来,并转换为
Spring 内部的事务配置对象。在 Spring 应用中,通常使用 `@Transactional` 注解声明事务,因此这个解析器是非常常用的,它使得事务管理更加便捷和灵活。
2. **Ejb3TransactionAnnotationParser**
+ 用于解析 EJB3 规范中的 `javax.ejb.TransactionAttribute` 注解。EJB3 是 Java EE
规范中的一部分,用于开发企业级应用程序。`Ejb3TransactionAnnotationParser` 负责解析 `javax.ejb.TransactionAttribute`
注解,并将其转换为 Spring 内部的事务配置对象,这使得 Spring 能够与 EJB3 技术集成,实现统一的事务管理。
3. **JtaTransactionAnnotationParser**
+ 用于解析 JTAJava Transaction API规范中定义的 `javax.transaction.Transactional` 注解。JTA 是 Java 平台的一部分,提供了一套
API 用于管理分布式事务。`JtaTransactionAnnotationParser` 负责解析 `javax.transaction.Transactional` 注解,并将其转换为
Spring 内部的事务配置对象,这使得 Spring 能够与分布式事务相关的技术集成,实现全面的事务管理支持。
### 六、类关系图
~~~mermaid
classDiagram
direction BT
class Ejb3TransactionAnnotationParser
class JtaTransactionAnnotationParser
class SpringTransactionAnnotationParser
class TransactionAnnotationParser {
<<Interface>>
}
Ejb3TransactionAnnotationParser ..> TransactionAnnotationParser
JtaTransactionAnnotationParser ..> TransactionAnnotationParser
SpringTransactionAnnotationParser ..> TransactionAnnotationParser
~~~
### 七、最佳实践
使用 `SpringTransactionAnnotationParser`
类来解析方法上的事务注解,并将其转换为事务属性对象。在这个示例中,通过反射获取了 `ScoresServiceImpl` 类中的 `insertScore`
方法,然后通过 `SpringTransactionAnnotationParser` 解析该方法上的事务注解,最后将解析结果输出到控制台。
```java
public class SpringTransactionAnnotationParserDemo {
public static void main(String[] args) throws NoSuchMethodException {
// 获取 ScoresServiceImpl 类中的 insertScore 方法
Method insertScoreMethod = ScoresServiceImpl.class.getMethod("insertScore");
// 创建 SpringTransactionAnnotationParser 实例
SpringTransactionAnnotationParser parser = new SpringTransactionAnnotationParser();
// 解析 insertScore 方法上的事务注解,并转换为事务属性对象
TransactionAttribute transactionAttribute = parser.parseTransactionAnnotation(insertScoreMethod);
// 输出事务属性对象
System.out.println(transactionAttribute);
}
}
```
`ScoresServiceImpl` 类实现了 `ScoresService` 接口,其中的 `insertScore` 方法被 `@Transactional`
注解修饰声明了一个事务。该事务的特性包括只读readOnly = true遇到任何异常都会回滚rollbackFor =
Exception.class事务隔离级别为可重复读isolation = Isolation.REPEATABLE_READ超时时间为 30 秒timeout =
30以及标签为 "tx1" 和 "tx2"。
```java
public class ScoresServiceImpl implements ScoresService {
@Override
@Transactional(
readOnly = true,
rollbackFor = Exception.class,
isolation = Isolation.REPEATABLE_READ,
timeout = 30,
label = {"tx1", "tx2"}
)
public void insertScore() {
// TODO
}
}
```
运行结果,事务的传播行为为 `PROPAGATION_REQUIRED`,隔离级别为 `ISOLATION_REPEATABLE_READ`,超时时间为 30
秒,只读模式开启,标签为 "tx1" 和 "tx2",同时,事务会回滚遇到 `java.lang.Exception` 及其子类的异常。
```java
PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ,timeout_30,readOnly; [tx1,tx2],-java.lang.Exception
```
### 八、源码分析
在`org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(java.lang.reflect.AnnotatedElement)`
方法中,首先通过 `AnnotatedElementUtils` 查找并获取元素上合并的 `@Transactional`
注解的属性信息,如果找到了注解,则调用另一个方法解析事务注解并返回事务属性对象,如果未找到注解,则返回 null。
```java
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
// 查找并获取元素上合并的 @Transactional 注解的属性信息
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
// 如果属性信息不为空,则解析事务注解并返回事务属性对象
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
// 如果属性信息为空,则返回 null
else {
return null;
}
}
```
在`org.springframework.transaction.annotation.SpringTransactionAnnotationParser#parseTransactionAnnotation(org.springframework.core.annotation.AnnotationAttributes)`
方法中,用于解析给定的注解属性并将其转换为事务属性对象。它根据注解属性中的信息设置事务的传播行为、隔离级别、超时时间、只读属性、限定符、标签和回滚规则等。最后,它返回一个基于规则的事务属性对象。
```java
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());
// 设置事务超时时间字符串
String timeoutString = attributes.getString("timeoutString");
// 校验是否同时设置了超时时间和超时时间字符串
Assert.isTrue(!StringUtils.hasText(timeoutString) || rbta.getTimeout() < 0,
"Specify 'timeout' or 'timeoutString', not both");
rbta.setTimeoutString(timeoutString);
// 设置事务是否为只读模式
rbta.setReadOnly(attributes.getBoolean("readOnly"));
// 设置事务限定符
rbta.setQualifier(attributes.getString("value"));
// 设置事务标签
rbta.setLabels(Arrays.asList(attributes.getStringArray("label")));
// 解析回滚规则
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;
}
```