@Slf4j
static class Hello {
@PostConstruct
@Transactional
public void initV1() {
boolean isActive = TransactionSynchronizationManager.isActualTransactionActive();
log.info("Hello init @PostConstruct tx active = {}", isActive);
}
}
Hello 빈이 생성된 후에 트랜잭션을 사용한 로직을 수행하려고 하는 상황이다.
Hello init @PostConstruct tx active = false
로그가 찍히는데 트랜잭션이 걸리지 않았다는 것을 의미한다.
-> 초기화 코드가 먼저 호출되고, 그 다음에 트랜잭션 AOP가 적용되기 때문에 초기화 시점에는 해당 매서드에서 트랜잭션을 걸 수 없다.
@EventListener(ApplicationReadyEvent.class)
@Transactional
public void initV2() {
boolean isActive = TransactionSynchronizationManager.isActualTransactionActive();
log.info("Hello init ApplicationReadyEvent tx active = {}", isActive);
}
EventListener를 이용한 방법이다.
Hello init @PostConstruct tx active = false
Started InitTxTest in 1.266 seconds (JVM running for 1.917)
Getting transaction for [hello.springtx.apply.InitTxTest$Hello.initV2]
Hello init ApplicationReadyEvent tx active = true
Completing transaction for [hello.springtx.apply.InitTxTest$Hello.initV2]
첫번쨰 줄의 로그는 Hello 객체가 생성된 뒤에 수행되었다는 로그이고,
두번째 줄의 로그는 스프링 컨테이너가 세팅을 마쳤다는 얘기이다.
그리고 나머지 로그는 @EventListener(ApplicationReadyEvent.class)
를 가진 initV2() 메서드를 호출하는 로그이다.
스프링 컨테이너의 셋팅이 완료되면 (AOP 프록시나 트랜잭션 준비 등등) 스프링은 단계에 맞춰 등록된 빈들의 @EventListener를 찾아 수행해준다.