1. 事务
指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。 事务由事务开始(begin transaction)和事务结束(end transaction)之间执行的全体操作组成。
特性:
- 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的操作要么都做,要么都不做。
- 一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
- 隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
- 持久性(durability):或永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
2.Spring编程式事务
2.1 概念
即通过编码方式实现事务,即类似于JDBC编程实现事务管理。管理使用TransactionTemplate(Spring推荐)或者直接使用底层的PlatformTransactionManager。
2.2 重要接口
- TransactionDefinition:定义了Spring兼容的事务属性(比如事务隔离级别、事务传播、事务超时、是否只读状态)。
- TransactionStatus:代表了事务的具体运行状态(获取事务运行状态的信息,也可以通过该接口间接回滚事务等操作)。
- PlatformTransactionManager:事务管理器接口(定义了一组行为,具体实现交由不同的持久化框架来完成—类比JDBC)
3. Spring声明式事务
3.1 概念
本质是AOP思想的实现,即对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。
3.2 实现方式
- @Transactional注解实现
- xml配置
3.3 @Transactional注解属性配置
- readOnly:设置当前事务是否为只读事务,设置为true表示只读,false则表示可读写,默认值为false。
@Transactional(readOnly=true)
- rollbackFor: 设置需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,则进行事务回滚。
指定单一异常类:@Transactional(rollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(rollbackFor={RuntimeException.class, Exception.class})
- rollbackForClassName:该属性用于设置需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,则进行事务回滚。
指定单一异常类名称:@Transactional(rollbackForClassName="RuntimeException")
指定多个异常类名称:@Transactional(rollbackForClassName={"RuntimeException","Exception"})
- noRollbackFor: 设置不需要进行回滚的异常类数组,当方法中抛出指定异常数组中的异常时,不进行事务回滚。
指定单一异常类:@Transactional(noRollbackFor=RuntimeException.class)
指定多个异常类:@Transactional(noRollbackFor={RuntimeException.class, Exception.class})
- noRollbackForClassName: 设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。
指定单一异常类名称:@Transactional(noRollbackForClassName="RuntimeException")
指定多个异常类名称:@Transactional(noRollbackForClassName={"RuntimeException","Exception"})
- propagation:设置事务的传播行为。
@Transactional(propagation=Propagation.NOT_SUPPORTED)
- isolation:设置底层数据库的事务隔离级别,事务隔离级别用于处理多事务并发的情况,通常使用数据库的默认隔离级别即可,基本不需要进行设置。
- timeout:设置事务的超时秒数,默认值为 -1 表示永不超时
3.4 @Transactional注意事项
- @Transactional 只能被应用到public方法上, 对于其它非public的方法,如果标记了@Transactional不会报错,但方法没有事务功能。
4. Spring 事务传播行为
Spring 事务传播行为:用来解决业务层之间调用的事务的关系。
类型 | 外部不存在事务 | 外部存在事务 | 范例 |
---|---|---|---|
REQUIRED(默认) | 开启新的事务 | 融合到外部事务中 | @Transactional(propagation = Propagation.REQUIRED)适用增删改查 |
SUPPORTS | 不开启新的事务 | 融合到外部事务中 | @Transactional(propagation = Propagation.SUPPORTS)适用查询 |
REQUIRES_NEW | 开启新的事务 | 不用外部事务,创建新的事务 | @Transactional(propagation = Propagation.REQUIRES_NEW)适用内部事务和外部事务不存在业务关联情况,如日志 |
NOT_SUPPORTED | 不开启新的事务 | 不用外部事务 | @Transactional(propagation = Propagation.NOT_SUPPORTED) 不常用 |
NEVER | 开启新的事务 | 抛出异常 | @Transactional(propagation = Propagation.NEVER )不常用 |
MANDATORY | 抛出异常 | 融合到外部事务中 | @Transactional(propagation = Propagation.MANDATORY)不常用 |
NESTED | 开启新的事务 | 融合到外部事务中,SavePoint机制,外层影响内层, 内层不会影响外层 | @Transactional(propagation = Propagation.NESTED)不常用 |
5. @Transactional原理大致解析
基于注解的声明式事务,必不可少的一步是在容器配置类上加@EnableTransactionManagement注解。
5.1 源码解析
@EnableTransactionManagement源码:
TransactionManagementConfigurationSelector类源码:
- AutoProxyRegistrar:相当于一个自定义组件注册器,在容器中注册了一个后置处理器。
- ProxyTransactionManagementConfiguration:是一个容器配置类,在其中注册了事务增强器。
registerAutoProxyCreatorIfNecessary方法:
最终在容器中注册了一个InfrastructureAdvisorAutoProxyCreator类
InfrastructureAdvisorAutoProxyCreator类:
这个类实现了SmartInstantiationAwareBeanPostProcessor,即这是一个后置处理器。所以,声明式事务是springAOP思想的一种应用。
ProxyTransactionManagementConfiguration类源码:
这个类注册了一个组件transactionAdvisor(事务增强器),然后又在这个事务增强器中又注入了两个属性:
- transactionAttributeSource:属性解析器
- transactionInterceptor:事务拦截器
属性解析器AnnotationTransactionAttributeSource类:
方法中主要添加了多种注解解析器(TransactionAnnotationParser),例如spring的、jta的、ejb的。下面只看spring的注解解析器源码。
spring的注解解析器SpringTransactionAnnotationParser类:
方法主要用来解析@Transactional注解的属性
事务拦截器TransactionInterceptor类:
最终返回:
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
invokeWithinTransaction方法:
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass, TransactionAspectSupport.InvocationCallback invocation) throws Throwable {
// 获取属性解析器,即在ProxyTransactionManagementConfiguration容器配置类中注册事务拦截器时注入的
TransactionAttributeSource tas = this.getTransactionAttributeSource();
TransactionAttribute txAttr = tas != null ? tas.getTransactionAttribute(method, targetClass) : null;
// 获取事务管理器(spring会先根据qualifier,即@Transactional注解的value属性去获取,一般都不配置。只要在容器中有注册过PlatformTransactionManager类型的事务管理器,就可以直接通过类型来获取;)
TransactionManager tm = this.determineTransactionManager(txAttr);
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
TransactionAspectSupport.ReactiveTransactionSupport txSupport = (TransactionAspectSupport.ReactiveTransactionSupport)this.transactionSupportCache.computeIfAbsent(method, (key) -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && TransactionAspectSupport.KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException("Unsupported annotated transaction on suspending function detected: " + method + ". Use TransactionalOperator.transactional extensions instead.");
} else {
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " + method.getReturnType());
} else {
return new TransactionAspectSupport.ReactiveTransactionSupport(adapter);
}
}
});
return txSupport.invokeWithinTransaction(method, targetClass, invocation, txAttr, (ReactiveTransactionManager)tm);
} else {
PlatformTransactionManager ptm = this.asPlatformTransactionManager(tm);
String joinpointIdentification = this.methodIdentification(method, targetClass, txAttr);
if (txAttr != null && ptm instanceof CallbackPreferringPlatformTransactionManager) {
TransactionAspectSupport.ThrowableHolder throwableHolder = new TransactionAspectSupport.ThrowableHolder();
Object result;
try {
result = ((CallbackPreferringPlatformTransactionManager)ptm).execute(txAttr, (statusx) -> {
TransactionAspectSupport.TransactionInfo txInfo = this.prepareTransactionInfo(ptm, txAttr, joinpointIdentification, statusx);
Object var9;
try {
Object retVal = invocation.proceedWithInvocation();
if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, statusx);
}
var9 = retVal;
return var9;
} catch (Throwable var13) {
if (txAttr.rollbackOn(var13)) {
if (var13 instanceof RuntimeException) {
throw (RuntimeException)var13;
}
throw new TransactionAspectSupport.ThrowableHolderException(var13);
}
throwableHolder.throwable = var13;
var9 = null;
} finally {
this.cleanupTransactionInfo(txInfo);
}
return var9;
});
} catch (TransactionAspectSupport.ThrowableHolderException var20) {
throw var20.getCause();
} catch (TransactionSystemException var21) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
var21.initApplicationException(throwableHolder.throwable);
}
throw var21;
} catch (Throwable var22) {
if (throwableHolder.throwable != null) {
this.logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw var22;
}
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
} else {
return result;
}
} else {
TransactionAspectSupport.TransactionInfo txInfo = this.createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
retVal = invocation.proceedWithInvocation();
} catch (Throwable var18) {
// 如果目标方法抛异常,会执行completeTransactionAfterThrowing,即回滚
this.completeTransactionAfterThrowing(txInfo, var18);
throw var18;
} finally {
this.cleanupTransactionInfo(txInfo);
}
if (retVal != null && vavrPresent && TransactionAspectSupport.VavrDelegate.isVavrTry(retVal)) {
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = TransactionAspectSupport.VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
// 进行事务提交
this.commitTransactionAfterReturning(txInfo);
return retVal;
}
}
}
5.2 原理小结
- 在容器配置类上使用@EnableTransactionManagement注解,该注解在容器中注册了两大组件——AutoProxyRegistrar、ProxyTransactionManagementConfiguration。
- AutoProxyRegistrar通过导入方式在容器中注册了InfrastructureAdvisorAutoProxyCreator,即后置处理器。
- ProxyTransactionManagementConfiguration本身就是一个容器配置类,它注册了transactionAdvisor(事务增强器),然后又在这个事务增强器中注入了两个属性transactionAttributeSource、transactionInterceptor。
- transactionAttributeSource用于解析@Transactional注解的各种属性。
- transactionInterceptor实现了MethodInterceptor,是一个拦截器链,这个拦截器链会从容器中获取事务管理器,利用事务管理器,在目标方法发生异常时执行回滚,在目标发生正常完成后提交事务。
- 第2步的InfrastructureAdvisorAutoProxyCreator后置处理器,会在目标对象创建完成之后将其包装为代理对象,代理对象在执行目标方法时会首先获取拦截器链,这个拦截器链就是第5步的transactionInterceptor。