文章目录
Spring事物源码分析-TransactionDefinition
一、TransactionDefinition接口
-
Spring事务中,通过TransactionDefinition接口定义了事物的属性,比如隔离级别、事务传播行为、事务超时时间、事务是否只读等。
-
TransactionDefinition中定义了事物传播级中的7个传播行为、4个事物隔离级别
public interface TransactionDefinition {
//事物传播行为
int PROPAGATION_REQUIRED = 0;
int PROPAGATION_SUPPORTS = 1;
int PROPAGATION_MANDATORY = 2;
int PROPAGATION_REQUIRES_NEW = 3;
int PROPAGATION_NOT_SUPPORTED = 4;
int PROPAGATION_NEVER = 5;
int PROPAGATION_NESTED = 6;
int ISOLATION_DEFAULT = -1;
//读未提交--1
int ISOLATION_READ_UNCOMMITTED = Connection.TRANSACTION_READ_UNCOMMITTED;
//读提交--2
int ISOLATION_READ_COMMITTED = Connection.TRANSACTION_READ_COMMITTED;
//可重复读--4
int ISOLATION_REPEATABLE_READ = Connection.TRANSACTION_REPEATABLE_READ;
//序列化--8
int ISOLATION_SERIALIZABLE = Connection.TRANSACTION_SERIALIZABLE;
//默认超时时间
int TIMEOUT_DEFAULT = -1;
//获取事物传播行为、隔离级别
int getPropagationBehavior();
int getIsolationLevel();
//获取超时时间
int getTimeout();
//获取是否制只读
boolean isReadOnly();
//获取事物名称
String getName();
}
二、子接口TransactionAttribute
- TransactionAttribute是TransactionDefinition的子接口,该接口又添加了两个属性;
public interface TransactionAttribute extends TransactionDefinition {
//事务的目标方法的完整方法名称
@Nullable
String getQualifier();
//对于给定的异常信息,是否回滚
boolean rollbackOn(Throwable ex);
}
- 在事物调用之前,会通过事物属性源获取事物属性,在前面的《Spring事物03-源码分析TransactionInterceptor》中的invoke调用的invokeWithinTransaction方法中可以看到
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
//1.获取事物属性源,(如果为空则表示不存在事物)
TransactionAttributeSource tas = getTransactionAttributeSource();
//2.属性源得到目标类和方法有关的属性
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
//省略其他......
}
三、实现类
3.1 DefaultTransactionDefinition
- DefaultTransactionDefinition是TransactionDefinition的一个实现类,实现了一些比较基础的方法
public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
//省略一些属性字段
//很多重载的构造方法
public DefaultTransactionDefinition() {
}
public DefaultTransactionDefinition(TransactionDefinition other) {
this.propagationBehavior = other.getPropagationBehavior();
this.isolationLevel = other.getIsolationLevel();
this.timeout = other.getTimeout();
this.readOnly = other.isReadOnly();
this.name = other.getName();
}
//传播行为属性get set方法
public final void setPropagationBehaviorName(String constantName) throws IllegalArgumentException {
if (!constantName.startsWith(PREFIX_PROPAGATION)) {
throw new IllegalArgumentException("Only propagation constants allowed");
}
setPropagationBehavior(constants.asNumber(constantName).intValue());
}
public final void setPropagationBehavior(int propagationBehavior) {
if (!constants.getValues(PREFIX_PROPAGATION).contains(propagationBehavior)) {
throw new IllegalArgumentException("Only values of propagation constants allowed");
}
this.propagationBehavior = propagationBehavior;
}
public final int getPropagationBehavior() {
return this.propagationBehavior;
}
//隔离级别get set方法
public final void setIsolationLevelName(String constantName) throws IllegalArgumentException {
if (!constantName.startsWith(PREFIX_ISOLATION)) {
throw new IllegalArgumentException("Only isolation constants allowed");
}
setIsolationLevel(constants.asNumber(constantName).intValue());
}
public final void setIsolationLevel(int isolationLevel) {
if (!constants.getValues(PREFIX_ISOLATION).contains(isolationLevel)) {
throw new IllegalArgumentException("Only values of isolation constants allowed");
}
this.isolationLevel = isolationLevel;
}
@Override
public final int getIsolationLevel() {
return this.isolationLevel;
}
//超时get set方法
public final void setTimeout(int timeout) {
if (timeout < TIMEOUT_DEFAULT) {
throw new IllegalArgumentException("Timeout must be a positive integer or TIMEOUT_DEFAULT");
}
this.timeout = timeout;
}
@Override
public final int getTimeout() {
return this.timeout;
}
//只读get set方法
public final void setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
}
public final boolean isReadOnly() {
return this.readOnly;
}
//name get set方法
public final void setName(String name) {
this.name = name;
}
public final String getName() {
return this.name;
}
//省略equals和hashCode
//输出事物属性基本信息
@Override
public String toString() {
return getDefinitionDescription().toString();
}
//输出事物属性基本信息
protected final StringBuilder getDefinitionDescription() {
//忽略..就是字符串输出...
}
}
3.2 DefaultTransactionAttribute
- DefaultTransactionAttribute实现了TransactionAttribute,并且继承了DefaultTransactionDefinition,几个类和接口的关系如下:
- 实际上TransactionDefinition和TransactionAttribute接口是父子关系,而且前面也有描述,差异不大,两个实现类也是继承的关系,差异不大。
四、属性描述
4.1 事物传播
属性 | 简化 | 功能描述 | 代码对应值 | 备注 |
---|---|---|---|---|
PROPAGATION_REQUIRED | require | 有就加入,没有就创建 | 0 | 保证在同一个事务中 |
PROPAGATION_SUPPORTS | supports | 有就加入,没有就算了 | 1 | 保证在同一个事务中 |
PROPAGATION_MANDATORY | mandatory | 有就加入,没有就抛异常 | 2 | 保证在同一个事务中 |
PROPAGATION_REQUIRES_NEW | requires_new | 前面有就挂起,自己一定要启动新的事物 | 3 | 保证不在一个事务中 |
PROPAGATION_NOT_SUPPORTED | not_support | 前面有就挂起、自己不用事物 | 4 | 保证不在一个事务中 |
PROPAGATION_NEVER | never | 前面有要抛异常,以非事物方式运行 | 5 | 保证不在一个事务中 |
PROPAGATION_NESTED | nested | 当前存在事物则进行事物嵌套,事物可单独回滚或者提交,如果没有事物则和require行为一致 | 6 | 保证不在一个事务中 |
4.2 隔离级别
- 事物隔离级别有四种
属性 | 简化 | 代码对应值 |
---|---|---|
ISOLATION_DEFAULT | 默认,采用数据库的默认隔离级别 | -1 |
ISOLATION_READ_UNCOMMITTED | 读未提交 | 1 |
ISOLATION_READ_COMMITTED | 读提交(Oracle默认) | 2 |
ISOLATION_REPEATABLE_READ | 可重复读(MySql默认) | 4 |
ISOLATION_SERIALIZABLE | 序列化 | 8 |
五、小结
- TransactionDefinition和TransactionAttribute接口是父子关系,而且差异不大;
- DefaultTransactionDefinition和DefaultTransactionAttribute分别实现了前面的两个接口,而且差异也很小。
- 两个接口或者实现类的作用都是用于描述一个事物的相关属性,也如文章开通所描述的,比如隔离级别、事务传播行为、事务超时时间、事务是否只读等。