Spring事务模型

2018-12-02 10:56:37

Spring事务模型

一. 三个核心接口

Spring事务中有三个核心接口:PlatformTransactionManagerTransactionDefinitionTransactionStatusPlatformTransactionManager利用TransactionDefinition提供的事务属性配置信息创建事务,并用TransactionStatus来描述这个激活事务的状态。

  1. TransactionDefinition定义了Spring支持的事务属性:事务隔离级别,事务传播行为,事务超时,只读状态。可以通过xml或注解的方式为一个需要事务的类或方法配置事务属性,如:
  1. @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.REPEATABLE_READ, timeout = 1000, readOnly = true)
  1. TransactionStatus代表一个事务的具体运行状态,事务管理器可以通过该接口获取事务运行期状态,也可以通过该接口间接地回滚事务。该接口继承自SavepointManager接口,并拓展了该接口
  1. package org.springframework.transaction;
  2. import java.io.Flushable;
  3. public interface TransactionStatus extends SavepointManager, Flushable {
  4. // 判断当前事务是否是一个新的事务,如果返回false,则表示当前事务是一个已经存在的事务,或者当前操作未运行在事务环境中。
  5. boolean isNewTransaction();
  6. // 判断当前事务是否在内部创建了一个恢复点
  7. boolean hasSavepoint();
  8. // 将当前事务标记为rollbackOnly,从而通知事务管理器只能回滚该事务。
  9. void setRollbackOnly();
  10. boolean isRollbackOnly();
  11. void flush();
  12. // 判断当前事务是否已经结束(已经提交或回滚)
  13. boolean isCompleted();
  14. }

SavepointManager接口提供了创建恢复点,回滚到某个恢复点以及释放某个恢复点对象的方法

  1. package org.springframework.transaction;
  2. public interface SavepointManager {
  3. Object createSavepoint() throws TransactionException;
  4. void rollbackToSavepoint(Object var1) throws TransactionException;
  5. void releaseSavepoint(Object var1) throws TransactionException;
  6. }
  1. PlatformTransactionManager接口定义了事务管理的功能:提交或回滚事务。spring为不同的持久化框架提供了不同的该接口实现类,比如JpaTransactionManagerDataSourceTransactionManager
  1. package org.springframework.transaction;
  2. import org.springframework.lang.Nullable;
  3. public interface PlatformTransactionManager {
  4. // 该方法根据事务定义信息从事务环境返回一个已经存在的事务,或者创建一个事务,
  5. // 并返回一个描述该事务状态的TransactionStatus对象
  6. TransactionStatus getTransaction(@Nullable TransactionDefinition var1) throws TransactionException;
  7. // 根据事务状态提交事务,如果事务被标记为rollbackOnly,则该方法执行回滚操作
  8. void commit(TransactionStatus var1) throws TransactionException;
  9. // 回滚事务,当commit方法抛出异常时,该方法将会被隐式调用
  10. void rollback(TransactionStatus var1) throws TransactionException;
  11. }

一个实例:

  1. @Resource
  2. private PlatformTransactionManager transactionManager;
  3. @Override
  4. public void test() {
  5. // 配置事务属性
  6. DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
  7. definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  8. definition.setReadOnly(true);
  9. // 事务管理器用事务定义信息创建事务
  10. TransactionStatus status = transactionManager.getTransaction(definition);
  11. try {
  12. Thread.sleep(2000);
  13. // 完成业务,提交事务
  14. transactionManager.commit(status);
  15. } catch (Exception e) {
  16. // 出错,回滚事务
  17. transactionManager.rollback(status);
  18. }
  19. }

将spring jdbc的事务管理器的包日志级别设为debug后输出:

可以看到成功创建了一个事务并提交。
如果处理业务过程中抛出异常,则事务会回滚:

  1. @Override
  2. public void test() {
  3. DefaultTransactionDefinition definition = new DefaultTransactionDefinition();
  4. definition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
  5. definition.setReadOnly(true);
  6. TransactionStatus status = transactionManager.getTransaction(definition);
  7. try {
  8. throwM();
  9. transactionManager.commit(status);
  10. } catch (Exception e) {
  11. transactionManager.rollback(status);
  12. }
  13. }
  14. private void throwM() {
  15. throw new RuntimeException();
  16. }

二. 事务同步管理器

事务是和线程紧密相关的,spring的事务同步管理器TransactionSynchronizationManager使用ThreadLocal为每个线程绑定一个数据库连接。比如在一个线程中,当一个Service的方法被执行时,如果这个方法需要一个事务,spring会在开启事务时,利用事务同步管理器为该线程绑定一个数据库连接,之后在当前线程的这个事务内,只要需要用到数据库连接,都是从ThreadLocal获取这个之前被绑定的连接,这也是为什么像JdbcTemplate这种单例的Bean能够正常工作在多线程环境中,因为JdbcTemplate在执行sql时也是从事务同步管理器中拿数据库连接的。

DataSourceUtils是spring jdbc从事务同步管理器中获取数据库连接的工具类,spring为不同的持久化框架提供了一套从事务同步管理器中获取对应线程绑定资源的工具类,比如Jpa的EntityManagerFactoryUtils
所以,当我们使用这些持久化框架时,如果需要自己手动操作底层的连接,应该从这些工具类中获取,而不是直接从DataSource中获取,因为从数据源直接获取的连接不是和当前事务绑定的,从而无法参与到当前线程的事务。
事务同步管理器同时也维护了当前事务配置的属性和运行状态信息:

  1. public abstract class TransactionSynchronizationManager {
  2. // 当前线程对应的connection或session等类型的资源
  3. private static final ThreadLocal<Map<Object, Object>> resources = new NamedThreadLocal("Transactional resources");
  4. // 存放当前线程的事务执行过程中的回调操作
  5. private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations = new NamedThreadLocal("Transaction synchronizations");
  6. // 当前线程的事务名称
  7. private static final ThreadLocal<String> currentTransactionName = new NamedThreadLocal("Current transaction name");
  8. // 当前线程的事务是否为只读
  9. private static final ThreadLocal<Boolean> currentTransactionReadOnly = new NamedThreadLocal("Current transaction read-only status");
  10. // 当前线程的事务隔离级别
  11. private static final ThreadLocal<Integer> currentTransactionIsolationLevel = new NamedThreadLocal("Current transaction isolation level");
  12. // 当前线程的事务是否被激活
  13. private static final ThreadLocal<Boolean> actualTransactionActive = new NamedThreadLocal("Actual transaction active");
  14. ...
  15. }

1
2
0

添加评论

正在回复:
取消
1
1
2
0