`

Spring 事务简要说明

 
阅读更多
/**
对于 <tx:annotation-driven transaction-manager="txManager" />  配置的事务(在方法上标注@Transaction)
或 使用AOP配置的事件:
   <tx:advice id="txAdvice" transaction-manager="transactionManager">  
    <tx:attributes>  
        <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" />  
        <tx:method name="update*" propagation="REQUIRED" isolation="DEFAULT" read-only="true"/>  
    </tx:attributes>  
</tx:advice>  
<aop:config>  
        <aop:advisor pointcut="execution(* *..*Service*.*(..))" advice-ref="txAdvice" />  
</aop:config>  
 
spring 能过AOP方式(CGLIB) 在切面(需要启用事务的方法被调用时)上调用TransactionInterceptor。
 
  TransactionInterceptor  实现了方法拦截器: implements org.aopalliance.intercept.MethodInterceptor
  示意逻辑:
  
    TransactionStatus  transactionStatus = platformTransactionManager.getTransaction();
try{
//这里调用业务逻辑
}catch(Throwable ex){
platformTransactionManager.rollback(transactionStatus);
throw ex;
}
platformTransactionManager.commit(transactionStatus);
 
platformTransactionManager的子类 DataSourceTransactionManager 在启用事务时,从当前线程获取ConnectionHolder,如果不存在则创建一个,并绑定定到线程中。
(从线程中获取ConnectionHolder :TransactionSynchronizationManager.getResource(this.dataSource)
绑定ConnectionHolder到线程的对象为:TransactionSynchronizationManager.bindResource(this.dataSource,ConnectionHolder)
)
ConnectionHolder保存在TransactionStatus中(实际子类为:DefaultTransactionStatus),以便commit或rollback可以拿到同一个Connection。
 
 
在执行sql里,如JdbcTemplate 是如何拿到同一个Connection的?
   Connection con = DataSourceUtils.getConnection(getDataSource());
DataSourceUtils会从当前线程中获到ConnectionHolder,如果存在直接获取使用,
 如果不存在,则从DataSource中获取一个Connection,
 判断是否有事务(TransactionSynchronizationManager.isSynchronizationActive()),
    如果有则创建ConnectionHolder并存入当线程线(TransactionSynchronizationManager.bindResource(dataSource, ConnectionHolder);)以备下次用
如果没有,则直接返回Connnection.(无事务时每次用到Connection都会新建一个)
 
 
说明:当启用事务时,获取了 Connection(ConnctionHolder),就与当前线程绑定,JdbcTemplate 每次操作可以取得线程内的同一个Connection操作。
 **/

/** 
相关代码 :
 
TransactionInterceptor方法:
**/
  @Override
public Object invoke(final MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
 
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() {
@Override
public Object proceedWithInvocation() throws Throwable {
return invocation.proceed();//实际的业务逻辑
}
});
}
/**
*
*
*/
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
throws Throwable {
 
// If the transaction attribute is null, the method is non-transactional.
final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass);
 
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {//不是CallbackPreferringPlatformTransactionManager
// Standard transaction demarcation with getTransaction and commit/rollback calls.
 
//启用事务--调用PlatformTransactionManager(实际子类如DataSourceTransactionManager )的getTransaction方法启用事务
//创建TransactionInfo(内部持有PlatformTransactionManager) 并绑定到当前线程
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
retVal = invocation.proceedWithInvocation();调用实际的业务逻辑
}
catch (Throwable ex) {
// target invocation exception
//异常rollback
//txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus());
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
cleanupTransactionInfo(txInfo);//清除信息
}
//提交事务
//txInfo.getTransactionManager().commit(txInfo.getTransactionStatus());
commitTransactionAfterReturning(txInfo);//提交数据库
return retVal;
}
 
else {
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
//如果是CallbackPreferringPlatformTransactionManager。。。。
//忽略部分代码
}
}
 
 
 
DataSourceTransactionManager是PlatformTransactionManager的子类,提供了事务处理能力。
 
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager{
private DataSource dataSource;//内部持有数据源对象
 
/**
* 
*
*/
protected Object doGetTransaction() {
DataSourceTransactionObject txObject = new DataSourceTransactionObject();//创建DataSourceTransactionObject对象它持有ConnectionHolder
txObject.setSavepointAllowed(isNestedTransactionAllowed());
ConnectionHolder conHolder =
(ConnectionHolder) TransactionSynchronizationManager.getResource(this.dataSource);//当前线程中获取
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
@Override
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; 
Connection con = null;
 
try {
if (txObject.getConnectionHolder() == null ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = this.dataSource.getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);//获取Connection存入 ConnectionHolder 对象,内部持有Connection,
}
 
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
 
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
 
// Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
// so we don't want to do it unnecessarily (for example if we've explicitly
// configured the connection pool to set it already).
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);//设置自动提交为false
}
txObject.getConnectionHolder().setTransactionActive(true);//标记事务启动状态
 
// Bind the session holder to the thread.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder());//绑定ConnectionHolder到当前线程
}
}
 
catch (Throwable ex) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, this.dataSource);
txObject.setConnectionHolder(null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex);
}
}
 
 
//启用事务,内部调用
  public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
//非实际代码,忽略了部分代码
Object transaction = doGetTransaction();
 
 
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(//创建TransactionStatus对象内部持有DataSourceTransactionObject
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
 
}
 
 
    /**
*
*  DefaultTransactionStatus--持有-->DataSourceTransactionObject--持有-->ConnectionHolder--持有-》Connection-->commit()
*/
protected void doCommit(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
 
try {
con.commit();//提交
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not commit JDBC transaction", ex);
}
}
 
/**
*
*  DefaultTransactionStatus--持有-->DataSourceTransactionObject--持有-->ConnectionHolder--持有-》Connection-->rollback()
*/
protected void doRollback(DefaultTransactionStatus status) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction();
Connection con = txObject.getConnectionHolder().getConnection();
 
try {
con.rollback();//事务回滚
}
catch (SQLException ex) {
throw new TransactionSystemException("Could not roll back JDBC transaction", ex);
}
}
 
 
   JdbcTemplate 通过  DataSourceUtils 获得Connction:
   
  public static Connection doGetConnection(DataSource dataSource) throws SQLException {
Assert.notNull(dataSource, "No DataSource specified");
 
ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(dataSource);//当线
if (conHolder != null && (conHolder.hasConnection() || conHolder.isSynchronizedWithTransaction())) {
conHolder.requested();
if (!conHolder.hasConnection()) {
logger.debug("Fetching resumed JDBC Connection from DataSource");
conHolder.setConnection(dataSource.getConnection());
}
return conHolder.getConnection();
}
// Else we either got no holder or an empty thread-bound holder here.
 
logger.debug("Fetching JDBC Connection from DataSource");
Connection con = dataSource.getConnection();
 
if (TransactionSynchronizationManager.isSynchronizationActive()) {
logger.debug("Registering transaction synchronization for JDBC Connection");
// Use same Connection for further JDBC actions within the transaction.
// Thread-bound object will get removed by synchronization at transaction completion.
ConnectionHolder holderToUse = conHolder;
if (holderToUse == null) {
holderToUse = new ConnectionHolder(con);
}
else {
holderToUse.setConnection(con);
}
holderToUse.requested();
TransactionSynchronizationManager.registerSynchronization(
new ConnectionSynchronization(holderToUse, dataSource));
holderToUse.setSynchronizedWithTransaction(true);
if (holderToUse != conHolder) {
TransactionSynchronizationManager.bindResource(dataSource, holderToUse);
}
}
 
return con;
}
 

 

分享到:
评论

相关推荐

    spring 事务传播

    在深入探讨Spring框架中的事务传播属性之前,我们先来简要回顾一下Spring事务的基础概念。Spring框架提供了强大的事务管理功能,允许开发者通过声明式的方式管理业务逻辑中的事务边界。Spring的事务管理主要依赖于`...

    Spring 事务代理配置

    在深入探讨Spring事务代理配置之前,我们先简要回顾一下Spring框架的核心概念。Spring是一个开源的Java平台,它提供了一套全面的编程和配置模型,主要用于简化企业级应用的开发。其中,依赖注入(Dependency ...

    Spring事务管理配置

    在深入探讨Spring事务管理配置之前,我们先简要回顾一下Spring框架的核心概念。Spring是一个开源的Java平台,它提供了一套全面的编程和配置模型,旨在简化企业级应用的开发。其中,事务管理是Spring框架中的一个重要...

    Spring+Struts2+iBatis简要说明

    Spring通过`applicationContext.xml`配置文件来配置应用上下文,这里可以定义Bean、事务管理、连接池等。Spring还提供了与iBatis的集成,使得事务管理和DAO层的数据库操作得以统一管理。 Struts2是MVC模式的具体...

    Spring.net中文说明

    2. AOP(面向切面编程):Spring.NET提供了AOP支持,允许开发者定义横切关注点(如日志、事务管理等),并将其与业务逻辑分离,提高了代码的可重用性和可维护性。 3. 数据访问支持:Spring.NET集成了多种数据访问...

    Spring框架的简要分析.doc

    在没有使用Spring事务管理时,通常需要手动获取和释放数据库连接,以及处理事务开始、提交和回滚。Spring通过DataSourceTransactionManager简化了这一过程,自动处理连接和事务,确保事务的一致性。 总的来说,...

    spring3.1MVC+mybatis3.1框架集成及事务,分页使用

    在本文中,我们将深入探讨如何将Spring MVC 3.1与MyBatis 3.1框架集成,并讨论其中涉及的关键技术,如事务管理、分页和JSON数据交换。此外,我们还将简要提及开发环境中使用的工具,如Eclipse 4.3、Maven 3.0.5和...

    Spring 框架简介

    - **数据访问/集成(Data Access/Integration)**: Spring提供了丰富的数据访问抽象层,包括JDBC、ORM(如Hibernate、JPA等)、事务管理和异常处理等,大大简化了数据库操作。 - **Web支持**: Spring提供了强大的Web...

    spring最常用jar包

    以上只是Spring框架部分核心模块的简要介绍,每个模块都包含了大量的类和接口,它们共同构成了一个强大且灵活的开发平台,帮助开发者高效地构建复杂的企业级应用。通过理解并熟练掌握这些jar包中的知识点,开发者...

    spring4.2.0官方文档

    1. **简介**:这部分简要介绍了Spring框架的基本概念、设计理念和核心模块,帮助初学者快速理解Spring的核心价值。 2. **快速入门**:提供了快速上手的教程,指导如何创建第一个Spring项目,包括配置环境、编写代码...

    Beginning Spring(2015)

    最后一章简要展望了Spring 4.0版本的发展趋势和新特性。Spring框架一直在不断地发展和完善,以适应不断变化的技术需求。这一章为读者提供了关于未来版本的一些洞察,帮助他们了解Spring框架的演进方向。 通过上述...

    spring电子书大全

    以下是压缩包中各文件的简要说明: 1. "Struts+Spring+Hibernatewzzsgcdlz.rar" - 这个文件可能包含了一套教程,讲解如何将Spring与另外两个流行框架Struts和Hibernate集成。Struts是一个用于构建MVC架构的Java Web...

    spring-kafka 整合官方文档

    在介绍部分,文档首先提供了快速入门指南,这包括对Spring for Apache Kafka的简要介绍以及与Kafka的兼容性信息。对于想要快速上手的读者,文档提供了使用Java配置和Spring Boot两种快速入门方法。通过这些指南,...

    spring 入门示例代码

    4. **AOP(面向切面编程)**:Spring支持AOP,允许开发者定义“切面”,将关注点如日志、事务管理等与业务逻辑分离,提高代码的可复用性和可维护性。 5. **JDBC模板**:Spring JDBC模块提供了一种简化JDBC编码的...

    【BAT必备】spring面试题,spring MVC面试题,spring boot面试题,spring cloud面试题

    以上是对Spring框架及其相关技术栈的简要介绍。对于准备进入BAT等大厂的开发者来说,掌握Spring框架的核心知识是非常必要的。不仅需要了解基本的概念,还需要深入学习其实现原理,这样才能在实际项目中更加灵活地...

    spring2.5 -3.0 hibernate3.3 jar包说明

    在探讨Spring 2.5到3.0以及Hibernate 3.3的Jar包之前,我们先简要回顾一下这两个框架的基本概念。 #### Spring 框架简介 Spring是一个开源的应用框架,它提供了一个全面的编程模型,旨在简化Java应用程序的开发过程...

    spring libs.zip

    以上只是Spring框架部分组件的简要介绍,实际的"spring libs.zip"文件可能还包括其他扩展或特定场景的库,如Spring Data(用于数据访问)、Spring Security(安全框架)等。理解并熟练掌握这些库的使用,对于开发高...

    Wrox.Beginning.Spring.2015

    以上是对《Beginning Spring》各章节内容的简要介绍。本书不仅适合初学者入门,也适合有一定经验的开发者作为参考书阅读。希望通过对这些知识点的学习,能够帮助大家更好地掌握Spring框架,并应用于实际项目开发中。

    spring integration in action

    - **发送者和接收者:** 详细说明了消息发送者和接收者的角色,以及它们如何与通道交互。 - **端点配置:** 讲解了如何配置端点来发送或接收消息。 - **自定义端点:** 探讨了如何创建自定义的端点以满足特定的需求...

Global site tag (gtag.js) - Google Analytics