什么是事务传播?
假设这样一个场景:方法A上面添加了一个@Transactional注解,在该方法中去调用另一个Service的方法B,但方法B并不需要事务,但是由于A开启了事务,导致B方法的执行也处于事务范围,那么这种情况该如何处理呢?
简单来说事务传播其实就是当一个事务方法调用其它方法时,被调用的方法可以通过@Transactional注解来决定如何应对调用方的事务,是抛出异常(Propagation.NEVER)?还是挂起调用方的事务(Propagation.NOT_SUPPORTED)?还是被调用方法自己再开启一个事务(Propagation#REQUIRES_NEW)?这点也和Spring官方文档中关于事务传播行为的解释不谋而合。
另外需要说明的是数据库没有事务传播这个概念。
底层实现
我们在使用Spring的声明式事务时需要配置一个TransactionManager,字面翻译就是事务管理器。事务传播行为就是在该接口的抽象实现-AbstractPlatformTransactionManager的getTransaction方法中实现的。
@Bean public TransactionManager transactionManager(){ return new DataSourceTransactionManager(dataSource()); }
在getTransaction方法中,首先通过doGetTransaction方法来获取事务,接下来通过isExistingTransaction方法来判断是否存在事务,如果存在事务则执行handleExistingTransaction方法来处理已存在的事务。
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException { // Use defaults if no transaction definition given. TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults()); Object transaction = doGetTransaction(); boolean debugEnabled = logger.isDebugEnabled(); if (isExistingTransaction(transaction)) { // Existing transaction found -> check propagation behavior to find out how to behave. return handleExistingTransaction(def, transaction, debugEnabled); } // 删除与本次分析无关代码... } }
doGetTransaction方法由AbstractPlatformTransactionManager类定义,由DataSourceTransactionManager类实现,典型的模板方法设计模式。
在该方法中,首先创建一个事务对象-DataSourceTransactionObject ,重点是接下来的设置数据库链接持有器(封装了数据库链接-Connection),通过TransactionSynchronizationManager的getResource方法来获取数据库链接持有器-ConnectionHolder,然后将获取到的数据库链接持有器设置到DataSourceTransactionObject中。因为数据库事务是和数据库链接-Connection有关(通过Connection的rollback或commit方法来回滚事务或提交事务),因此我们只需要关注一个数据库链接如何在不同方法之间传递。
标签:事务,transaction,Spring,数据库,调用,原理,方法,链接 From: https://www.cnblogs.com/jelly12345/p/16725581.html