Spring 与 MyBatis 事务管理源码解析

时间:2020-07-28 17:26:30   收藏:0   阅读:95
<bean id="comboPooledDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ssm"/>
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
    </bean>

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="comboPooledDataSource"/>
</bean>

<bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="cn.itcast.dao"/>
</bean>
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware {

	//接口包
	
    private String basePackage;
    private boolean addToConfig = true;
    private SqlSessionFactory sqlSessionFactory;
    private SqlSessionTemplate sqlSessionTemplate;
    private String sqlSessionFactoryBeanName;
    private String sqlSessionTemplateBeanName;
    private Class<? extends Annotation> annotationClass;
    private Class<?> markerInterface;
    private ApplicationContext applicationContext;
    private String beanName;
    private boolean processPropertyPlaceHolders;
    private BeanNameGenerator nameGenerator;
     ···
     get/set方法用以注入
     ···
}

技术图片

public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {

public final TransactionzhuangtStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {

//在DataSourceTransactionManager中重写了的类,查询当前线程中是否有传入的datasource对应的ConnectionHolder,有则依据他创建transaction

 Object transaction = this.doGetTransaction();
 boolean debugEnabled = this.logger.isDebugEnabled();
 if (definition == null) {
     definition = new DefaultTransactionDefinition();
 }

 if (this.isExistingTransaction(transaction)) {
     return this.handleExistingTransaction((TransactionDefinition)definition, transaction, debugEnabled);
 }
···
各种条件判断
···
     try {
         boolean newSynchronization = this.getTransactionSynchronization() != 2;
         
         //被创建的事务状态对象类型是DefaultTransactionStatus,它持有上述创建的事务对象。事务状态对象主要用于获取当前事务对象的状态,比如事务是否被标记了回滚,是否是一个新事务等等。
         DefaultTransactionStatus status = this.newTransactionStatus((TransactionDefinition)definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
         
         //事务开始处理,进行促使化,连接获取
         this.doBegin(transaction, (TransactionDefinition)definition);
         
         //对象都交由TransactionSynchronizationManager管理,TransactionSynchronizationManager把这些对象都保存在ThreadLocal中。在该transaction未commit/关闭前,该线程就会与该connection一直绑定在一起,通过只能同时绑定一个connection的原理,实现事务管理。
         
         this.prepareSynchronization(status, (TransactionDefinition)definition);
         
         返回事务状态对象:(主要进行:查询事务状态、通过setRollbackOnly()方法标记当前事务使其回滚,根据事务参数创建内嵌事务),statu的意思是方便先对事务进行判断再获取transaction进行操作。
         return status;
     } catch (Error | RuntimeException var7) {
         this.resume((Object)null, suspendedResources);
         throw var7;
     }
 }
}
}
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
		implements ResourceTransactionManager, InitializingBean {

@Override//主要增加了对TransactionSynchronizationManager中当前线程是否有connectionHolder
	protected Object doGetTransaction() {
	
		// 创建事务对象
		
		DataSourceTransactionObject txObject = new DataSourceTransactionObject();
		txObject.setSavepointAllowed(isNestedTransactionAllowed());
		ConnectionHolder conHolder =
				(ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource());
		//ConnectionHolder赋值给事务对象txObject
		txObject.setConnectionHolder(conHolder, false);
		return txObject;		
		}
}

//处理事务开始的方法 ?
? ? protected void doBegin(Object transaction, TransactionDefinition definition) { ?
? ? ? ? DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; ?
? ? ? ? Connection con = null; ?
? ? ? ? try { ?
? ? ? ? ? ? //如果数据源事务对象的ConnectionHolder为null或者是事务同步的 ?
? ? ? ? ? ? if (txObject.getConnectionHolder() == null || ?
? ? ? ? txObject.getConnectionHolder().isSynchronizedWithTransaction()) { ?
? ? ? ? ? ? ? ? //获取当前数据源的数据库连接 ?
? ? ? ? ? ? ? ? Connection newCon = this.dataSource.getConnection(); ?
? ? ? ? ? ? ? ? if (logger.isDebugEnabled()) { ?
? ? ? ? ? ? ? ? ? ? logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction"); ?
? ? ? ? ? ? ? ? } ?
? ? ? ? ? ? ? ? //为数据源事务对象设置ConnectionHolder ?
? ? ? ? ? ? ? ? txObject.setConnectionHolder(new ConnectionHolder(newCon), true); ?
? ? ? ? ? ? } ?
? ? //设置数据源事务对象的事务同步 ? ?txObject.getConnectionHolder().setSynchronizedWithTransaction(true); ?
? ? ? ? ? ? //获取数据源事务对象的数据库连接 ?
? ? ? ? ? ? con = txObject.getConnectionHolder().getConnection(); ?
? ? ? ? ? ? //根据数据连接和事务属性,获取数据库连接的事务隔离级别 ?
? ? ? ? ? ? Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); ?
? ? //为数据源事务对象设置事务隔离级别 ?
? ? txObject.setPreviousIsolationLevel(previousIsolationLevel); ?
? ? ? ? ? ? //如果数据库连接设置了自动事务提交属性,则关闭自动提交 ?
? ? ? ? ? ? if (con.getAutoCommit()) { ?
? ? ? ? ? ? ? ? //保存数据库连接设置的自动连接到数据源事务对象中 ?
? ? ? ? ? ? ? ? txObject.setMustRestoreAutoCommit(true); ?
? ? ? ? ? ? ? ? if (logger.isDebugEnabled()) { ?
? ? ? ? ? ? ? ? ? ? logger.debug("Switching JDBC Connection [" + con + "] to manual commit"); ?
? ? ? ? ? ? ? ? } ?
? ? ? ? ? ? ? ? //设置数据库连接自动事务提交属性为false,即禁止自动事务提交 ?
? ? ? ? ? ? ? ? con.setAutoCommit(false); ?
? ? ? ? ? ? } ?
? ? ? ? ? ? //激活当前数据源事务对象的事务配置 ?
? ? ? ? ? ? txObject.getConnectionHolder().setTransactionActive(true); ?
? ? ? ? ? ? //获取事务配置的超时时长 ?
int timeout = determineTimeout(definition); ?
//如果事务配置的超时时长不等于事务的默认超时时长 ?
? ? ? ? ? ? if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { ?
? ? ? ? //数据源事务对象设置超时时长 ?
? ? ? ? txObject.getConnectionHolder().setTimeoutInSeconds(timeout); ?
? ? ? ? ? ? } ?
? ? ? ? ? ? //把当前数据库Connection和线程ThreadLocal绑定(key为DataSource,value为getConnectionHolder)spring事务管理的关键一步
? ? ? ? ? ? if (txObject.isNewConnectionHolder()) { ?
? ? ? ? TransactionSynchronizationManager.bindResource(getDataSource(), txObject.getConnectionHolder()); ?
? ? ? ? ? ? } ?
? ? ? ? } ?
? ? ? ? catch (Exception ex) { ?
? ? ? ? ? ? DataSourceUtils.releaseConnection(con, this.dataSource); ?
? ? ? ? ? ? throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", ex); ?
? ? ? ? } ?
? ? } ?

技术图片

public class SqlSessionTemplate implements SqlSession, DisposableBean {
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
    Assert.notNull(sqlSessionFactory, "Property ‘sqlSessionFactory‘ is required");
    Assert.notNull(executorType, "Property ‘executorType‘ is required");
    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    this.sqlSessionProxy = (SqlSession)Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionTemplate.SqlSessionInterceptor());
}



// 动态代理中的 InvocationHandler类,真正对方法的前后进行通知的类,代理类对象只是提供一个目标对象的封装以调用而已
 private class SqlSessionInterceptor implements InvocationHandler {
        private SqlSessionInterceptor() {
        }

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
            //查看是否有为关闭的闲置的同个配置的sqlsession,有则调用,这也是你用sqlsessionTemplate代理执行增删查改一直是同一个sqlsession完成事务管理的原因,没有则生成。我们可以看到是由SqlSessionUtils实现的
            
    SqlSession sqlSession = SqlSessionUtils.getSqlSession(SqlSessionTemplate.this.sqlSessionFactory, SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator);

            Object unwrapped;
            try {
                Object result = method.invoke(sqlSession, args);
                if (!SqlSessionUtils.isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
                //查询是否自动提交
                //若是自动则为一条sql一次commit,是为新手设置的,一般手动提交。
                    sqlSession.commit(true);
                }

                unwrapped = result;
            } catch (Throwable var11) {
                unwrapped = ExceptionUtil.unwrapThrowable(var11);
                if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
                    SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
                    sqlSession = null;
                    Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException)unwrapped);
                    if (translated != null) {
                        unwrapped = translated;
                    }
                }

                throw (Throwable)unwrapped;
            } finally {
            
            //关闭sqlsession,同一个事务可以有多个sqlsession
            
                if (sqlSession != null) {
                    SqlSessionUtils.closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
                }

            }

            return unwrapped;
        }
    }
}
public final class SqlSessionUtils {
	    public static SqlSession getSqlSession(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator) {
        Assert.notNull(sessionFactory, "No SqlSessionFactory specified");
        Assert.notNull(executorType, "No ExecutorType specified");
        
        //有相应的sqlsessionHolder则取出里面的SqlSession
        
        SqlSessionHolder holder = (SqlSessionHolder)TransactionSynchronizationManager.getResource(sessionFactory);
        SqlSession session = sessionHolder(executorType, holder);
        if (session != null) {
            return session;
        } else {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Creating a new SqlSession");
            }
	
			//没有则用工厂创建sqlsession,注意:此时的sqlsessionfactory是sqlsessionfactoryBean创建的,即他的configuration中的Enviroment中的transactionFactory是SpringManageTransactionFactory。
			
            session = sessionFactory.openSession(executorType);
            
           // 注册sqlsession到TransactionSyncronizedMager,
           
           
            registerSessionHolder(sessionFactory, executorType, exceptionTranslator, session);
            return session;
        }
    }
}
private static void registerSessionHolder(SqlSessionFactory sessionFactory, ExecutorType executorType, PersistenceExceptionTranslator exceptionTranslator, SqlSession session) {
    if (TransactionSynchronizationManager.isSynchronizationActive()) {
    
    	//从sessionFactory中获取Environment
    	
        Environment environment = sessionFactory.getConfiguration().getEnvironment();
        
        //判断environment中封装的TransactionFactorySpringManagedTransactionFactory,是否用到了Spring的事务管理服务,sqlsession中对TransactionSyncronizedMager的应用只有与Spring集成时才用到,mybatis自身的事务管理并不会用到。
        
        if (environment.getTransactionFactory() instanceof SpringManagedTransactionFactory) {
            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("Registering transaction synchronization for SqlSession [" + session + "]");
            }

            SqlSessionHolder holder = new SqlSessionHolder(session, executorType, exceptionTranslator);
            
            //绑定、注册到TransactionSynchronizationManager
            TransactionSynchronizationManager.bindResource(sessionFactory, holder);
            TransactionSynchronizationManager.registerSynchronization(new SqlSessionUtils.SqlSessionSynchronization(holder, sessionFactory));
            
            holder.setSynchronizedWithTransaction(true);
            holder.requested();
        } else {
            if (TransactionSynchronizationManager.getResource(environment.getDataSource()) != null) {
                throw new TransientDataAccessResourceException("SqlSessionFactory must be using a SpringManagedTransactionFactory in order to use Spring transaction synchronization");
            }

            if (LOGGER.isDebugEnabled()) {
                LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because DataSource is not transactional");
            }
        }
    } else if (LOGGER.isDebugEnabled()) {
        LOGGER.debug("SqlSession [" + session + "] was not registered for synchronization because synchronization is not active");
    }

}
protected Connection getConnection(Log statementLog) throws SQLException {
    Connection connection = this.transaction.getConnection();
    return statementLog.isDebugEnabled() ? ConnectionLogger.newInstance(connection, statementLog, this.queryStack) : connection;
}
public abstract class DataSourceUtils {
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(fetchConnection(dataSource));
   }
   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 = fetchConnection(dataSource);

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;
}
public abstract class AbstractPlatformTransactionManager implements PlatformTransactionManager, Serializable {
 
 public final void commit(TransactionStatus status) throws TransactionException {
     ···
     status 是否已完成或是否需要rollback
    ···    
        //正常流程会调用processCommit         
            this.processCommit(defStatus);
        }   
        }
        }
  }
?```


private void processCommit(DefaultTransactionStatus status) throws TransactionException {
    try {
        boolean beforeCompletionInvoked = false;

        try {
            boolean unexpectedRollback = false;         
            //commit准备      
            this.prepareForCommit(status);
            
            //BeforeCommit:commit前对springTransaciton、sqlsession的commit,大部分未实现这个的功能
            
            this.triggerBeforeCommit(status);
            
            //BeforeCompletion:Complete前对springTransaciton、sqlsession的commit
            
            this.triggerBeforeCompletion(status);
            beforeCompletionInvoked = true;
            ···
            是否有记录回调点/是否需要回调
            ···
            // 在DataSourceTransactionManager中实现对connection的commit
            this.doCommit(status);

            ···          
           异常处理
            ···
    
        try {
        	
        	//对TransactionSynchronizationManager中的synchronizations用Iterator计数器遍历删除
            this.triggerAfterCommit(status);
            
        } finally {
        
        // 若上一步没清理完成,则再次清理一次,用synchronizations用Iterator计数器遍历删除
            this.triggerAfterCompletion(status, 0);
            
        }
    } finally {
    
        // 清空TransactionSynchronizationManager,若有挂起的事务,则恢复执行
        this.cleanupAfterCompletion(status);
    }

}
// 清空TransactionSynchronizationManager,若有挂起的事务,则恢复执行,这和definiton设置的事务级别有关
private void cleanupAfterCompletion(DefaultTransactionStatus status) {
        status.setCompleted();
        if (status.isNewSynchronization()) {
            TransactionSynchronizationManager.clear();
        }

        if (status.isNewTransaction()) {
            this.doCleanupAfterCompletion(status.getTransaction());
        }

        if (status.getSuspendedResources() != null) {
            if (status.isDebug()) {
                this.logger.debug("Resuming suspended transaction after completion of inner transaction");
            }

            Object transaction = status.hasTransaction() ? status.getTransaction() : null;
            
            //SuspendedResourcesHolder用静态方法放置在JVM的方法区,可以直接调用
            
            this.resume(transaction, (AbstractPlatformTransactionManager.SuspendedResourcesHolder)status.getSuspendedResources());
        }
评论(0
© 2014 mamicode.com 版权所有 京ICP备13008772号-2  联系我们:gaon5@hotmail.com
迷上了代码!