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

250 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

## 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;
}
```