事务
什么是事务?
事务通常针对数据的操作而言,一般说的都是指数据库的事务。
什么是ACID?
ACID是指事务的特性,只有满足了这四个条件系统才能称之为支持事务
Automicity 原子性, 指一个事务内的操作要么全部成功,要么全部失败。
Consistence 一致性,是指事务内的数据需要处于一种有意义的状态。针对一个另一个事务而言不会看到其他事务正处于运行时的状态。比如A向B转账100元,其他事务只能看到A减去100元和B加上100元的状态,不会看到中间状态。
通俗的理解就是对于一个操作影响的一个或多个数据结果必须是一致且符合操作预期结果的
针对原子性和一致性的区别可以这么理解, 原子性指的是数据操作状态要么全部成功,要么全部失败不存在部分成功部分失败的情况。 而一致性是针对数据的状态只有最开始的数据和最终的数据是对于其他事务可见的
Isolation 隔离性, 隔离性是指不同事务之间的操作是相互隔离互相不干扰的,对于事务A而言要么只能看到事务B开始前的数据,要么看到事务B执行之后的数据
Durability 持久性,是指事务一但提交,在数据库中便会得到持久的保存
什么是事务的隔离级别?
理解事务的隔离级别之前先理解一下,什么是脏读、幻读和不可重复读。
脏读 就是A用户对数据进行了修改但未提交到数据库,这时候B用户读取到了未提交的数据并对数据进行了操作。这些操作的数据可能是错误的,称之为脏读
幻读 就是A用户删除了一条数据,这时B用户又插入了一条数据。A用户查询数据的时感觉没有做删除操作,产生了幻觉。幻读一般针对批量操作情况下
不可重复读 是指用户A读取了用户B修改的数据,造成了每次读取的数据不一只
事务的隔离级别(Mysql为例)
隔离级别 | 脏读 | 不可重复读 | 幻读 | 解释 |
---|---|---|---|---|
读未提交 read-uncommitted | 是 | 是 | 是 | 事务A开始写数据则不允许事务B同时也写这条数据,但是可以读已可能会出现脏读现象 |
读提交 read-committed | 否 | 是 | 是 | 事务A读数据时,事务B可以对数据进行读写。如果写数据则进制其他事务访问这条数据,会出现不可重复读,事务A第一次读取数据后事务B更新了数据事务A再次读取两条数据不一致(其实是正常情况) |
可重复读 repeatable-read | 否 | 否 | 是 | 事务A在读取数据后,对数据进行加锁使得事务B无法读到未提交和修改数据,但是不能排除insert语句,所以还是存在幻读的情况 |
串行化 serializable | 否 | 否 | 否 | 已锁表方式,其他线程无法操作。效率低 |
什么是Spring中的事务支持?
先来看一下Spring中对事务的管理接口
这里引用一张图:原文地址Spring事务管理
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface PlatformTransactionManager {
// 这里传递一个事务的定义接口
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
// 提交事务
void commit(TransactionStatus var1) throws TransactionException;
// 回滚事务
void rollback(TransactionStatus var1) throws TransactionException;
}
再开来一下TransactionDefinition接口
package org.springframework.transaction;
import org.springframework.lang.Nullable;
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;
int ISOLATION_READ_UNCOMMITTED = 1;
int ISOLATION_READ_COMMITTED = 2;
int ISOLATION_REPEATABLE_READ = 4;
int ISOLATION_SERIALIZABLE = 8;
// 定义了默认的超时时间-1表示不超时
int TIMEOUT_DEFAULT = -1;
// 获取用户定义的传播行为
int getPropagationBehavior();
// 获取用户定义的隔离级别
int getIsolationLevel();
// 获取用户定义的超时时间
int getTimeout();
// 是否只读,设为只读则该事务不能进行数据的修改
boolean isReadOnly();
@Nullable
String getName();
在Srping中一般使用声明式@Transaction注解标识,当前方法块中的事务配置。同样可以使用编程式事务只针对某一数据块的操作进行事务设置
传播行为 | 含义 |
---|---|
PROPAGATION_REQUIRED | 当前操作的数据,必须在事务中。如果不存在事务则启动一个新的事务 |
PROPAGATION_SUPPORTS | 当前方法不需要事务上下文,如果存在事务的话则在事务中运行 |
PROPAGATION_MANDATORY | 表示该方法必须在事务中运行,如果没有事务则会抛出异常 |
PROPAGATION_REQUIRES_NEW | 表示方法必须运行在事务中,运行期间会启动一个新的事务,如果已经存在事务,则该事务会被挂起 |
PROPAGATION_NOT_SUPPORTED | 表示方法不运行在事务中,运行期间如果有事务则事务会被挂起 |
PROPAGATION_NEVER | 不支持事务,如果存在事务则会抛出异常 |
PROPAGATION_NESTED | 如果已经存在事务,则会作为嵌套事务进行。嵌套的事务可单独运行提交不影响外层,但是外层事务如果失败会把嵌套的事务一起回滚 |
如何更好的理解事务的理解spring事务的传播属性,这里可以模拟两个方法,通过声明式配置该方法事务的传播属性
// 方法A
@Transactional(propagation=propagation.xxx)
void methodA(){
doA();
methodB();
doB();
}
// 方法B
@Transactional(propagation=propagation.xxx)
void methodB();
当methodA中调用了methodB时,才会有已经存事务的情况
接下来我们来看下PlatformTransactionManager中的另一个方法返回
TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
public interface TransactionStatus extends SavepointManager, Flushable {
...
}
先看下继承的两个类是什么东东?
/**
* 可以看出这个接口主要用于对保存记录的操作
**/
public interface SavepointManager {
// 保存记录点
Object createSavepoint() throws TransactionException;
// 回滚到记录点
void rollbackToSavepoint(Object savepoint) throws TransactionException;
// 释放记录的点
void releaseSavepoint(Object savepoint) throws TransactionException;
}
public interface Flushable {
/**
* Flushes this stream by writing any buffered output to the underlying
* stream.
*
* @throws IOException If an I/O error occurs
*/
void flush() throws IOException;
}
在回过来看下,TransactionStatus
public interface TransactionStatus extends SavepointManager, Flushable{
boolean isNewTransaction(); // 判断当前事务是否是新事务,否在则已存在事务中
boolean hasSavepoint(); // 判断是否有记录点
void setRollbackOnly(); // 设为只回滚
boolean isRollbackOnly(); // 判断是否设置了只回滚
@Override
void flush(); // 将缓存数据写入持久化
boolean isCompleted(); // 判断当前事务是否完成,被committed或者rollback
}
大致了解了PlatformTransactionManager接口所要实现的方法,现在来具体看一下具体实现了事务接口的类
已DataSourceTransactionManager为例:
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
...
}
照例我们来看下它继承的是个什么东东?
/**
*集成了PlatformTrasactionManager
**/
public interface ResourceTransactionManager extends PlatformTransactionManager {
/**
* 定义了一个获取资源工厂的方法
* 实际就是返回与数据库关联的资源对象,可以是 JDBC DataSource 或者JMS的ConnectionFactory
**/
Object getResourceFactory();
}
/**
* 这里与spring结合
**/
public interface InitializingBean {
// 这个方法会被BeanFactory调用在设置完对象的属性之后
void afterPropertiesSet() throws Exception;
}
最主要的是继承了Spring提供的抽象事务管理类,来看下AbstractPlatformTransactionManager里面都有些什么东西?
/**
* 这里也继承了主接口并且标识了可序列化
**/
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
// 标识事务任何时候是加锁的(即线程安全)
// PROPAGATION_SUPPORTS,PROPAGATION_NOT_SUPPORTED,PROPAGATION_NEVER三种行为支持
public static final int SYNCHRONIZATION_ALWAYS = 0;
// 当存在真是的事务时才进行加锁
// PROPAGATION_REQUIRED,PROPAGATION_MANDATORY,PROPAGATION_REQUIRES_NEW支持
public static final int SYNCHRONIZATION_ON_ACTUAL_TRANSACTION = 1;
public static final int SYNCHRONIZATION_NEVER = 2;//任何时候不加锁
// 获取类中反射的属性包含类名称,字段等放在Constans类中
private static final Constants constants = new Constants(AbstractPlatformTransactionManager.class);
protected transient Log logger = LogFactory.getLog(getClass()); // 日志
private int transactionSynchronization = SYNCHRONIZATION_ALWAYS;
private int defaultTimeout = TransactionDefinition.TIMEOUT_DEFAULT; // 默认的超时时间,从配置中取
private boolean nestedTransactionAllowed = false; // 是否允许NESTED行为的事务
private boolean validateExistingTransaction = false; // 是否验证已经存在事务
private boolean globalRollbackOnParticipationFailure = true; // 当传播事务失败后是否执行全局的回滚
private boolean failEarlyOnGlobalRollbackOnly = false; // 暂时还不知道什么意思后面看看
private boolean rollbackOnCommitFailure = false; // 当提交失败后是否回滚
public final void setTransactionSynchronizationName(String constantName) { // 这里通过转换将传播行为的类型转为具体的加锁属性
setTransactionSynchronization(constants.asNumber(constantName).intValue());
}
// ....属性的get set方法大致省略
// 继承获取事务方法的实现
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
Object transaction = doGetTransaction(); // 获取一个TransactionStatus实例,后续doCommit,doBegin,doRollback传的都是这个对象
boolean debugEnabled = logger.isDebugEnabled(); // 获取日志级别用于日志打印
if (definition == null) { // 如果没有传入定义则使用默认定义
// propagationBehavior = PROPAGATION_REQUIRED;
// isolationLevel = ISOLATION_DEFAULT;
// readOnly = false
definition = new DefaultTransactionDefinition();
}
if(isExistingTransaction(transaction)){
// 如果存在事务则根据定义的事务传播行为处理事务(后面再具体看一下这个方法)
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// 检查设置的超时时间是否准确
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// 如果设定为Mandatory则一定要在事务中运行,因为前面如果有事务则调用了handleExistingTransaction方法,所以这里没有事务抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
// 用来存在被挂起的事务对象(后面具体再看下这里面是什么)
SuspendedResourcesHolder suspendedResources = suspend(null);
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
// 是否支持锁
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 生成一个默认的TransactionStatus
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
// 开始事务(有具体提供的类实现)
doBegin(transaction, definition);
// 为当前线程启动一个线程的初始化一个TransactionSynchronizationManager可以预想是为了多线程下的事务使用的
// 用于记录当前线程下事务的状态
prepareSynchronization(status, definition);
return status;
}catch (RuntimeException | Error ex) {
// 恢复事务
resume(null, suspendedResources);
throw ex;
}
} else{
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
// 记录状态
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
// 后面大致看一下方法的作用,具体的方法内容可以看源码
// 处理已经存在的事务
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
// 如果是never则直接抛出异常
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// ...其他对应具体传播行为的处理方法
}
/**
* 通过给定的参数生成TransactionStatus
* 同时初始化transaction synchronization
**/
protected final DefaultTransactionStatus prepareTransactionStatus(){...}
/**
* 通过参数创建一个新的TransactionStatus
* */
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {...}
/**
* 初始化transaction synchronization
**/
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {...}
/**
* 确定超时时间
**/
protected int determineTimeout(TransactionDefinition definition) {...}
/**
* 用于记录挂起的事务
**/
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {...}
// 恢复指定的事务
protected final void resume(@Nullable Object transaction, @Nullable SuspendedResourcesHolder resourcesHolder){...}
// 当内层事务异常后恢复外层事务
private void resumeAfterBeginException(
Object transaction, @Nullable SuspendedResourcesHolder suspendedResources, Throwable beginEx) {...}
// 挂起当前所有事务
private List<TransactionSynchronization> doSuspendSynchronization() {...}
// 恢复给定同步的事务
private void doResumeSynchronization(List<TransactionSynchronization> suspendedSynchronizations) {}
@Override
// 提交事务
public final void commit(TransactionStatus status) throws TransactionException {
if (status.isCompleted()) {
throw new IllegalTransactionStateException(
"Transaction is already completed - do not call commit or rollback more than once per transaction");
}
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
if (defStatus.isLocalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Transactional code has requested rollback");
}
processRollback(defStatus, false);
return;
}
if (!shouldCommitOnGlobalRollbackOnly() && defStatus.isGlobalRollbackOnly()) {
if (defStatus.isDebug()) {
logger.debug("Global transaction is marked as rollback-only but transactional code requested commit");
}
processRollback(defStatus, true);
return;
}
processCommit(defStatus);
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status); // 提交前准备
triggerBeforeCommit(status); // 触发提交前
triggerBeforeCompletion(status); // 触发提交后
beforeCompletionInvoked = true;
if (status.hasSavepoint()) { // 如果有保存的节点
if (status.isDebug()) {
logger.debug("Releasing transaction savepoint");
}
unexpectedRollback = status.isGlobalRollbackOnly(); // 是否期望回滚
status.releaseHeldSavepoint(); // 释放保存点
} else if (status.isNewTransaction()) {
if (status.isDebug()) {
logger.debug("Initiating transaction commit");
}
unexpectedRollback = status.isGlobalRollbackOnly();
doCommit(status);
}
else if (isFailEarlyOnGlobalRollbackOnly()) {
unexpectedRollback = status.isGlobalRollbackOnly();
}
if (unexpectedRollback) {
throw new UnexpectedRollbackException(
"Transaction silently rolled back because it has been marked as rollback-only");
}
}
catch (UnexpectedRollbackException ex) {
// can only be caused by doCommit
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
throw ex;
}
catch (TransactionException ex) {
// can only be caused by doCommit
if (isRollbackOnCommitFailure()) {
doRollbackOnCommitException(status, ex);
}
else {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
}
throw ex;
}
catch (RuntimeException | Error ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, ex);
throw ex;
}
try {
triggerAfterCommit(status);
}
finally {
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
cleanupAfterCompletion(status);
}
}
// 回滚
public final void rollback(TransactionStatus status) throws TransactionException {}
// 具体回滚的实现
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {}
// 一些触发的方法
protected final void triggerBeforeCommit(DefaultTransactionStatus status) {}
protected final void triggerBeforeCompletion(DefaultTransactionStatus status) {}
private void triggerAfterCommit(DefaultTransactionStatus status) {}
private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {}
protected final void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus){}
private void cleanupAfterCompletion(DefaultTransactionStatus status) {}
// 下面的部分是继承的类需要实现的方法
protected abstract Object doGetTransaction() throws TransactionException; // 获取一个Transaction对象
protected boolean isExistingTransaction(Object transaction) throws TransactionException; //是否存在事务
protected boolean useSavepointForNestedTransaction() {
return true;
}
protected abstract void doBegin(Object transaction, TransactionDefinition definition)
throws TransactionException;
protected Object doSuspend(Object transaction) throws TransactionException {
throw new TransactionSuspensionNotSupportedException(
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
}
protected void doResume(@Nullable Object transaction, Object suspendedResources) throws TransactionException {
throw new TransactionSuspensionNotSupportedException(
"Transaction manager [" + getClass().getName() + "] does not support transaction suspension");
}
protected boolean shouldCommitOnGlobalRollbackOnly() {
return false;
}
protected void prepareForCommit(DefaultTransactionStatus status) {}
protected abstract void doCommit(DefaultTransactionStatus status) throws TransactionException;
protected abstract void doRollback(DefaultTransactionStatus status) throws TransactionException;
// 设置事务rollback-only
protected void doSetRollbackOnly(DefaultTransactionStatus status) throws TransactionException {
throw new IllegalTransactionStateException(
"Participating in existing transactions is not supported - when 'isExistingTransaction' " +
"returns true, appropriate 'doSetRollbackOnly' behavior must be provided");
}
// 设置同步的事务
protected void registerAfterCompletionWithExistingTransaction(
Object transaction, List<TransactionSynchronization> synchronizations) throws TransactionException {
logger.debug("Cannot register Spring after-completion synchronization with existing transaction - " +
"processing Spring after-completion callbacks immediately, with outcome status 'unknown'");
invokeAfterCompletion(synchronizations, TransactionSynchronization.STATUS_UNKNOWN);
}
protected void doCleanupAfterCompletion(Object transaction) {
}
}
代码看到这里基本AbstractPlatformTransactionManager抽象类就结束了,可以看出。该类中定义了实际对事务的操作方法,具体的继承类需要实现方法 。我们可以拿DataSourceTransactionManager稍微看一下里面的内容:
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
// 具体与数据库的连接资源
private DataSource dataSource;
// 其它的一些方法即实现了抽象类方法,需要可以再去深入看一下
}
到这里从代码层面上,大致了解了一遍事务的运行机制。当然要想深入了解代码实现,则好要花时间看。
什么情况下会导致spring中事务的传播行为失效?
什么是事务的失效,可以简单的理解为开启了事务,但遇到问题了并没有回滚事务。
基本有下列几种情况:
- 已mysql为例,当数据库本身不支持事务时不会生效。innodb支持,MyISAM不支持
- 当采用声明式的方法所在对象没有被spring管理时
//@Service
public class Test{
@Transaction
public void A(){}
}
Test类并没有标识@Service或者注入到ioc中
3. 声明式的事务方法只能用在public方法中才会生效
4. 当声明了事务,当没有被其他外部类调用,事务也不会生效
5. 没有正确配置支持事务的事务管理器,比如DataSourceTransactionManager
6. 默认事务的异常处理类是RuntimeException。当抛出的异常不是这个时不会生效。要手动配置
@Transactional(rollbackFor = Exception.class)
接下来我们再来看下声明式的事务是怎么实现的?
首先看下声明式:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default ""; // 事务管理器的别名
@AliasFor("value")
String transactionManager() default ""; // 通过事务管理器名字查找可用的管理器
Propagation propagation() default Propagation.REQUIRED; // 事务传播级别
Isolation isolation() default Isolation.DEFAULT; // 隔离级别
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; // 超时时间
boolean readOnly() default false; // 是否只读
Class<? extends Throwable>[] rollbackFor() default {}; // 指定回滚能捕获的异常Class
String[] rollbackForClassName() default {};// 异常名
Class<? extends Throwable>[] noRollbackFor() default {}; // 不需要回滚异常类
String[] noRollbackForClassName() default {}; // 不需要回滚异常名
}
了解了注解里的东西之后,那标识上这个注解的方法是怎么实现事务管理的呢?接着来看一下
先来看下@EnableTransactionManagement 要让项目支持注解需要加上这个注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
/**
* 标识是否创建CGLIB代理模式,默认为否这个配置会关系到所有需要代理的事务
*/
boolean proxyTargetClass() default false;
/**
* 默认使用JDK Proxy模式进行动态代理
*/
AdviceMode mode() default AdviceMode.PROXY;
/**
* 标识事务的顺序,当一个切点中包含多个事务切面时.
*/
int order() default Ordered.LOWEST_PRECEDENCE;
}
可以看到注解自动注入了一个TransactionManagementConfigurationSelector类
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {
// 通过配置的代理模式返回代理配置
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
}
我们通过默认的模式PROXY看一下这个配置类都启动了哪些东西。
@Configuration
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
}
稍微看下它的抽象类
@Configuration
public abstract class AbstractTransactionManagementConfiguration implements ImportAware {
@Nullable
protected AnnotationAttributes enableTx; // 用于存放注解的信息(解析到的Transaction注解)
@Nullable
protected PlatformTransactionManager txManager; // 需要有事务管理器
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableTx = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableTransactionManagement.class.getName(), false)); // 从标识了EnableTransactionManagement的类中获取注解信息
if (this.enableTx == null) {
throw new IllegalArgumentException(
"@EnableTransactionManagement is not present on importing class " + importMetadata.getClassName());
}
}
@Autowired(required = false)
void setConfigurers(Collection<TransactionManagementConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one TransactionManagementConfigurer may exist");
}
TransactionManagementConfigurer configurer = configurers.iterator().next();
this.txManager = configurer.annotationDrivenTransactionManager(); // 主要是事务配置中获取到事务管理器
}
@Bean(name = TransactionManagementConfigUtils.TRANSACTIONAL_EVENT_LISTENER_FACTORY_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionalEventListenerFactory transactionalEventListenerFactory() {
return new TransactionalEventListenerFactory(); // 获取事务事件监听工厂,可以通过事务监听工厂在beforCommit,afterCompletion等监听事务执行步骤
}
}
回过头来看下ProxyTransactionManagementConfiguration 配置类
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
// 这里生成BeanFactoryTransactionAttributeSourceAdvisor 用于存放标识了Transaction的切点信息
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
// 生成Interceptor类和使用proxy代理的原理一致
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
从 TransactionInterceptor中看出,其中主要的方法为invoke,这里就是代理了事务的方法
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// 获取标识了注解的资源信息
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr); // 获取事务管理器
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr); // 获取切点
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// 创建事务信息
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal;
try {
// 围绕增强设置
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 如果失败了则处理失败
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);
}
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 这里回滚
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
} else {
throw new ThrowableHolderException(ex);
}
}
else {
throwableHolder.throwable = ex;
return null;
}
}
finally {
cleanupTransactionInfo(txInfo);
}
});
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
到这里@Transaction注解相关的代码稍微看了一下。
最后来看下编程式事务是怎么个工作原理:
@Autowired
private TransactionTemplate transactionTemplate;
public void testTransaction() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
try {
// .... 业务代码
} catch (Exception e){
//回滚
transactionStatus.setRollbackOnly();
}
}
});
}
Template的代码相对比较直观一点
public class TransactionTemplate extends DefaultTransactionDefinition
implements TransactionOperations, InitializingBean {
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
@Nullable
private PlatformTransactionManager transactionManager;
/**
* Construct a new TransactionTemplate for bean usage.
* <p>Note: The PlatformTransactionManager needs to be set before
* any {@code execute} calls.
* @see #setTransactionManager
*/
public TransactionTemplate() {
}
/**
* Construct a new TransactionTemplate using the given transaction manager.
* @param transactionManager the transaction management strategy to be used
*/
public TransactionTemplate(PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
/**
* Construct a new TransactionTemplate using the given transaction manager,
* taking its default settings from the given transaction definition.
* @param transactionManager the transaction management strategy to be used
* @param transactionDefinition the transaction definition to copy the
* default settings from. Local properties can still be set to change values.
*/
public TransactionTemplate(PlatformTransactionManager transactionManager, TransactionDefinition transactionDefinition) {
super(transactionDefinition);
this.transactionManager = transactionManager;
}
public void setTransactionManager(@Nullable PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
@Nullable
public PlatformTransactionManager getTransactionManager() {
return this.transactionManager;
}
@Override
public void afterPropertiesSet() {
if (this.transactionManager == null) {
throw new IllegalArgumentException("Property 'transactionManager' is required");
}
}
@Override
@Nullable
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
}
else {
// 直接使用事务管理器进行操作
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
result = action.doInTransaction(status);
}
catch (RuntimeException | Error ex) {
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
}
catch (Throwable ex) {
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
this.transactionManager.commit(status);
return result;
}
}
/**
* 处理回滚操作
*/
private void rollbackOnException(TransactionStatus status, Throwable ex) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");
logger.debug("Initiating transaction rollback on application exception", ex);
try {
this.transactionManager.rollback(status);
}
catch (TransactionSystemException ex2) {
logger.error("Application exception overridden by rollback exception", ex);
ex2.initApplicationException(ex);
throw ex2;
}
catch (RuntimeException | Error ex2) {
logger.error("Application exception overridden by rollback exception", ex);
throw ex2;
}
}
@Override
public boolean equals(Object other) {
return (this == other || (super.equals(other) && (!(other instanceof TransactionTemplate) ||
getTransactionManager() == ((TransactionTemplate) other).getTransactionManager())));
}
}
总结一下spring下的事务:
针对spring的事务,首先是需要数据库的事务支持。同时spring设置了事务的不同传播行为,用于满足不同业务场景的事务需求。
调用方式主要有两种,注解及编程式事务。编程式事务相对比较灵活。