事务的同步管理器
Spring 将 JDBC 的 Connection、Hibernate 的 Session 等访问数据库的连接或者会话对象统称为资源,这些资源在同一时刻是不能多线程共享的 。为了让 DAO 或 Service 类可以实现单例模式,Spring 的事务同步管理类 org.springframework.transaction.support.TransactionSynchronizationManager 利用 ThreadLocal 为不同的事务线程提供了独立的资源副本,并同时维护这些事务的配置属性和运行状态信息 。
TransactionSynchronizationManager
部分源码
public abstract class TransactionSynchronizationManager {
private static final Log logger = LogFactory.getLog(TransactionSynchronizationManager.class);
// 用于保存每个事务对应的Connection和Session等类型的资源
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<Map<Object, Object>>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");
// 用于保存每个事务线程对应事务的名称
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<String>("Current transaction name");
//用于保存每个事务线程对应的事务的read-only的状态
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<Boolean>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<Integer>("Current transaction isolation level");
// 保存每个事务线程对应的事务的激活态
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<Boolean>("Actual transaction active");
// ...
}
Spring 框架为不同的持久化技术提供了一套从 TransactionSynchronizationManager 中获取对应线程绑定资源的工具类,这些工具类都提供了可以获取绑定当前线程资源的静态方法:
持久化技术 | 线程绑定资源获取工具 | 方法 |
---|---|---|
Spring JDBC 或 MyBatis | org.springframework.jdbc.datasource.DataSourceUtils | public static Connection getConnection(DataSource dataSource) |
HibernateX.0 | org.springframework.orm.hibernateC.SessionFactoryUtils | public static Session getSession(SessionFactory sessionFactory, boolean allowCreate) |
JPA | org.springframework.orm.jpa.EntityManagerFactoryUtils | public static EntityManager getTransactionalEntityManager(EntityManagerFactory emf) |
JTO | org.springframework.orm.jdo.PersistenceManagerFactoryUtils | … |
某些场景下,可能无法使用 Spring 提供的模板类。这时,就必须通过操作底层持久化技术所提供的原生 API ,而这就需要通过这些工具类来获取线程绑定的资源。如果直接从 DataSource 或 SessionFactory 中获取资源,那么就无法让数据操作参与到与本线程相关的事务环境,因为这些对象不能获取和当前线程相关的资源。
事务传播行为
事务传播在Spring中事务管理的重要概念。
事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。
- PROPAGATION_REQUIRED支持当前事务,如果不存在,就新建一个(默认)
- PROPAGATION_SUPPORTS支持当前事务,如果不存在,就不适用事务
- PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常保证没有在同一个事务中
- PROPAGATION_REQUIRES_NEW如果有事务存在,挂起当前事务,创建一个新的事务
- PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
- PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
- PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行