@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncService {
private final MemberRepository memberRepository;
@Transactional
public void saveMember() {
logTransactionStatus("saveMember");
memberRepository.save(Member.factory());
Events.raise(new MailSentEvent(Member.factory()));
}
private void logTransactionStatus(String methodName) {
log.info("in {} method: name={}, active={}, synchronizationActive={}",
methodName,
TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.isActualTransactionActive(),
TransactionSynchronizationManager.isSynchronizationActive());
}
}
@Slf4j
@RequiredArgsConstructor
@Service
public class MailSentEventHandler {
private final MailService mailService;
private final MemberRepository memberRepository;
@Async
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) // 트랜잭션이 커밋된후에 이벤트가 실행된다.
public void handle(MailSentEvent event) {
logTransactionStatus("handle");
memberRepository.save(Member.factory());
mailService.send(event.getMessage());
}
private void logTransactionStatus(String methodName) {
log.info("in {} method: name={}, active={}, synchronizationActive={}",
methodName,
TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.isActualTransactionActive(),
TransactionSynchronizationManager.isSynchronizationActive());
}
}
@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncService {
private final MemberRepository memberRepository;
@Transactional
public void saveMember() {
logTransactionStatus("saveMember");
memberRepository.save(Member.factory());
Events.raise(new MailSentEvent(Member.factory()));
}
private void logTransactionStatus(String methodName) {
log.info("in {} method: name={}, active={}, synchronizationActive={}",
methodName,
TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.isActualTransactionActive(),
TransactionSynchronizationManager.isSynchronizationActive());
}
}
@Slf4j
@RequiredArgsConstructor
@Service
public class MailSentEventHandler {
private final MailService mailService;
private final MemberRepository memberRepository;
@Transactional(propagation = Propagation.REQUIRES_NEW)
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT) // 트랜잭션이 커밋된후에 이벤트가 실행된다.
public void handle(MailSentEvent event) {
logTransactionStatus("handle");
memberRepository.save(Member.factory());
mailService.send(event.getMessage());
}
private void logTransactionStatus(String methodName) {
log.info("in {} method: name={}, active={}, synchronizationActive={}",
methodName,
TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.isActualTransactionActive(),
TransactionSynchronizationManager.isSynchronizationActive());
}
}
앞 트랜잭션 커밋 , 뒤 트랜잭션 롤백
앞 트랜잭션 롤백 , 뒤 트랜잭션 커밋되는경우
뒤 트랜잭션은 실행 되지도 않는다
@Slf4j
@Service
@RequiredArgsConstructor
public class AsyncService {
private final MemberRepository memberRepository;
// @Transactional
public void saveMember() {
logTransactionStatus("saveMember");
memberRepository.save(Member.factory());
Events.raise(new MailSentEvent(Member.factory()));
}
private void logTransactionStatus(String methodName) {
log.info("in {} method: name={}, active={}, synchronizationActive={}",
methodName,
TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.isActualTransactionActive(),
TransactionSynchronizationManager.isSynchronizationActive());
}
}
메일전송은 실행되지않았고, 엔티티매니저에선 새롭게 트랜잭션을 생성해서 내부적으로 커밋을 완료시킨후 서비스로직으로 돌아온걸 확인할 수 있다.