ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Spring] @PostConstruct와 @Transactional
    legacy/Spring 2023. 9. 5. 01:47

     

    @PostConstruct와 @Transactional이 동시에 사용되었을 때 트랜잭션이 적용되지 않는다. 그 이유는 두 애너테이션이 호출되는 시점이 다르기 때문이다.

     

    스프링 생명 주기

    스프링 컨테이너 생성 -> 스프링 빈 생성 -> 의존 관계 주입 -> 초기화 콜백 -> 사용 -> 소멸 콜백 -> 스프링 컨테이너 종료

    @PostConstruct 호출 시점

    스프링 빈이 생성 되고 의존 관계가 주입된 후에 호출된다.

    @Transactional 호출 시점

    초기화 콜백 이후 컨테이너가 초기화된 후에 호출된다.


    코드

    Hello 클래스가 빈으로 등록되어 있고, initV1() 메서드에 @PostConstruct 애너테이션이 사용되고 있다.

    @SpringBootTest
    @Slf4j
    public class InitTxTest {
    
        @Autowired
        Hello hello;
    
        @Test
        void init() {
        }
    
        @TestConfiguration
        static class ConfigClass {
            @Bean
            public Hello hello() {
                System.out.println("Hello 의존 관계 주입");
                return new Hello();
            }
        }
    
        static class Hello {
            @PostConstruct
            @Transactional
            public void initV1() {
                log.info("Hello init @PostConstruct tx active={}", TransactionSynchronizationManager.isActualTransactionActive());
            }
        }
    }

     

    위에서 말했듯이 @PostConstruct는 의존 관계 주입 완료된 후 호출이 되고, @Transactional은 스프링 컨테이너가 초기화된 후 호출된다.

     

    따라서 다음과 같은 결과를 얻을 수 있다.

    1. @Autowired를 통해 의존 관계가 주입시에 "Hello 의존 관계 주입"이 먼저 출력이 된다.
    2. 의존 관계 주입이 끝났기때문에 초기화 콜백이 일어난다. 이때 @PostConstruct가 호출된다. 따라서 "Hello init @PostConstruct.."가 출력된다.
    3. 스프링 컨테이너가 초기화된다. "Started InitTxTest..."가 출력된다.


    @PostConstruct와 @Transactional 호출 시점이 다르다.

    @PostConstruct는 의존관계 주입이 완료된 후 호출되고, @Transactional은 스프링 컨테이너가 초기화된 시점에 호출된다. 따라서 두 애너테이션을 동시에 사용하면 @PostConstruct가 먼저 호출되기 때문에 트랜잭션이 정상적으로 처리되지 않는다.

     

    트랜잭션의 경우 AOP 기술을 사용한다. AOP의 경우에는 스프링 컨테이너가 완전히 초기화되어야 사용할 수 있다. 

    따라서 @PostConstruct로 인해 스프링 컨테이너가 올라오지 않은 상태에서 @Transactional을 사용할 수 없다.

     

    참고

    https://www.inflearn.com/questions/26902/postconstruct%EC%99%80-transactional-%EB%B6%84%EB%A6%AC

Designed by Tistory.