继续学习TransactionManager。
上一篇文章分析了PlantformTransactionManager的getTransaction方法的一小部分......这部分内容确实特别多,不过Spring的事务管理的大部分内容都是在TransactionManager中实现的,分析完事务管理器的功能,基本就算是掌握了Spring事务管理了。
今天应该从startTransaction开始,他是定义在AbstractPlantFormTransactionManager中的。
startTransaction
前面说过,startTransaction是真正开启事务的地方。
首先创建了一个DefaultTransactionStatus,因为我们知道开启事务最终要返回的是事务状态对象。
调用doBegin,开启事务。之后调用prepareSynchronization方法善后,这个方法我们上一篇文章已经看过了,绑定当前事务的现场数据到当前线程并保存。
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition);
prepareSynchronization(status, definition);
return status;
}
继续跟踪doBegin方法。
doBegin
doBegin方法跳到DataSourceTransactionManager中实现了,因为我们说过真正需要和数据库打交道的时候就会跳到事务管理的这个落地实现类中了。
首先获取DataSource(其实transaction对象就是),然后定义我们非常熟悉的数据库连接Connection。
看到这个Connection,会不会有一点点惊奇呢?因为我们一步步的摸到了Spring事务管理的底层实现了。
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
Connection con = null;
之后就是判断当前事务对象是否已经存在ConnectionHolder,没有的话创建ConnectionHolder对象并让他持有新创建的数据库连接。
try {
if (!txObject.hasConnectionHolder() ||
txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
Connection newCon = obtainDataSource().getConnection();
if (logger.isDebugEnabled()) {
logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
然后,从ConnectinHolder中重新获取Connection:
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
然后就是你非常熟悉的、最激动人心的:
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (logger.isDebugEnabled()) {
logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
con.setAutoCommit(false);
}
设置数据库连接的autoCommit为false,也就是开启了事务。
之后就是设置事务为激活状态,根据事务定义设置timeout等操作:
prepareTransactionalConnection(con, definition);
txObject.getConnectionHolder().setTransactionActive(true);
int timeout = determineTimeout(definition);
if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
最后还有一步:
// Bind the connection holder to the thread.
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder());
}
就是绑定ConnectionHolder到当前线程。如果大家没有忘记的话,判断当前是否存在已开启事务就是通过这个TransactionSynchronizationManager完成的,当然了,已开启事务本来就是由他持有、所以当然是由他来判断了。
至此,数据库事务完美开启。
同时,到这里我没也就对Spring事务管理器的当前存在已开启事务的情况下的getTransaction代码逻辑分析完毕。
后续部分,下一篇文章分析。