트랜잭션 AOP 주의사항 - 초기화 시점

wangjh789·2022년 8월 20일
0

[Spring] 스프링-DB-2

목록 보기
14/21
    @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를 찾아 수행해준다.

profile
기록

0개의 댓글