22년 12월 작성한 글입니다.
@Transactional
어노테이션을 통해 트랜잭션을 처리합니다.PlatformTransactionManager
가 어떻게 동작하는지 알아봅니다.TransactionInterceptor
가 트랜잭션 advice 로 사용되는것을 확인했습니다.TransactionInterceptor#invoke
가 호출되고, 내부적으로 TransactionAspectSupport#invokeWithinTransaction
를 호출합니다.PlatformTranscationManager
를 통해 트랜잭션을 획득, 커밋 그리고 롤백합니다.TransactionInterceptor
가 트랜잭션을 획득, 커밋 그리고 롤백하는 과정은 아래와 같이 도식화할수 있습니다.PlatformTranscationManager
의 추상 구현체는 AbstractPlatformTranscationManager
로 대부분의 구현체가 해당 클래스를 상속하고 있습니다.DataSourceTransactionManager
JdbcTransactionManager
HibernateTransactionManager
JtaTransactionManager
getTransaction
commit
rollback
TransactionStatus
(트랜잭션) 을 획득합니다.Propagation
과 Isolation
에 따라서 동작이 달라집니다.TransactionSynchronizationManager
에 새로운 트랜잭션을 등록합니다.public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException {
TransactionDefinition def = (definition != null ? definition : TransactionDefinition.withDefaults());
Object transaction = doGetTransaction(); // 트랜잭션 획득
if (isExistingTransaction(transaction)) {
// 이미 트랜잭션이 존재하는 경우 핸들링
return handleExistingTransaction(def, transaction, debugEnabled);
}
...
try {
// 트랜잭션 시작
return startTransaction(def, transaction, debugEnabled, suspendedResources);
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
...
}
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;
}
TransactionSynchorinization
를 호출합니다#beforeCommit
#beforeCompletion
#afterCommit
#afterCompletion
TransactionSynchronizationManager
에 등록된 트랜잭션을 해제합니다.public final void commit(TransactionStatus status) throws TransactionException {
...
processCommit(defStatus);
}
private void processCommit(DefaultTransactionStatus status) throws TransactionException {
try {
boolean beforeCompletionInvoked = false;
try {
boolean unexpectedRollback = false;
prepareForCommit(status);
// TransactionSynchorinization#beforeCommit 호출
triggerBeforeCommit(status);
// TransactionSynchorinization#beforeCompletion 호출
triggerBeforeCompletion(status);
beforeCompletionInvoked = true;
...
doCommit(status); // 커밋
...
} ...
catch (RuntimeException | Error ex) {
if (!beforeCompletionInvoked) {
triggerBeforeCompletion(status);
}
doRollbackOnCommitException(status, ex); // 롤백
throw ex;
}
try {
// TransactionSynchorinization#afterCommit 호출
triggerAfterCommit(status);
}
finally {
// TransactionSynchorinization#afterCompletion 호출
triggerAfterCompletion(status, TransactionSynchronization.STATUS_COMMITTED);
}
}
finally {
// TransactionSynchronizationManager 해제
cleanupAfterCompletion(status);
}
}
TransactionSynchorinization
를 호출합니다#beforeCompletion
#afterCompletion
TransactionSynchronizationManager
에 등록된 트랜잭션을 해제합니다.public final void rollback(TransactionStatus status) throws TransactionException {
...
DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status;
processRollback(defStatus, false);
}
private void processRollback(DefaultTransactionStatus status, boolean unexpected) {
try {
boolean unexpectedRollback = unexpected;
try {
// TransactionSynchorinization#beforeCompletion 호출
triggerBeforeCompletion(status);
...
doRollback(status); // 롤백
...
}
catch (RuntimeException | Error ex) {
// TransactionSynchorinization#afterCompletion 호출
triggerAfterCompletion(status, TransactionSynchronization.STATUS_UNKNOWN);
throw ex;
}
// TransactionSynchorinization#afterCompletion 호출
triggerAfterCompletion(status, TransactionSynchronization.STATUS_ROLLED_BACK);
...
}
finally {
// TransactionSynchronizationManager 해제
cleanupAfterCompletion(status);
}
}
@Transactional
를 통해 트랜잭션이 적용될때, PlatformTransactionManager
를 통해 트랜잭션이 적용됩니다.AbstractPlatformTranscationManager
에 트랜잭션을 획득, 커밋, 그리고 롤백하는 과정이 일부 작성되어 있습니다.