스프링 초기화 시점, 에는 트랜잭션 AOP가 적용이 되지 않을 수도 있다.
Custom init() 저 부분 인 듯?
그러니까, @PostConstruct가 의존성 주입 이후 우리가 뭔가 초기화? 작업같은 거 해 두고 싶을 때 저거 붙인 메소드 만들면 알아서 실행이 되는데,
만약
@PostConstruct
@Transactional
이렇게 있으면 @Transactional이 적용이 되지 않을 수도 있다.
순서가 @PostConstruct 등 초기화가 모두 된 다음에 프록시로써 쓸 수 있다.
@SpringBootTest
public class InitTxTest {
@Autowired
Hello hello;
@Test
public void initTx(){
}
@TestConfiguration
static class InitTxTestConfig{
@Bean
public Hello hello(){
return new Hello();
}
}
@Slf4j
static class Hello{
@PostConstruct
@Transactional
public void initV1(){
boolean isActive = TransactionSynchronizationManager.isActualTransactionActive();
log.info("@PostConstruct Transaction active = {}", isActive);
}
@EventListener(ApplicationReadyEvent.class)
@Transactional
public void initV2(){
boolean isActive = TransactionSynchronizationManager.isActualTransactionActive();
log.info("@EventListener Transaction active = {}", isActive);
}
}
}
테스트.
@PostConstruct나 @EventListener(ApplicationReadyEvent.class)는 모두 특정 순간에 자동으로 호출 되므로,
그냥 실행만 할 수 있도록 빈 @Test를 넣음.
@PostConstruct 때는 저거 @Transactional을 붙여놨지만 false로 나옴.
@EventListener(ApplicationReadyEvent.class)는 말 그대로 애플리케이션 준비, 즉 사용할 준비가 끝났을 때 발생하는 이벤트인데(프록시, 초기화 등 모든 설정이 끝나고 딱 사용할 준비)
저 때는 true가 나옴.
2023-10-15T13:30:03.188+09:00 INFO 21664 --- [main] j.LocalContainerEntityManagerFactoryBean :
Initialized JPA EntityManagerFactory for persistence unit 'default'
2023-10-15T13:30:03.204+09:00 INFO 21664 --- [ main] hello.springtx.apply.InitTxTest$Hello :
@PostConstruct Transaction active = false
2023-10-15T13:30:03.399+09:00 INFO 21664 --- [main] hello.springtx.apply.InitTxTest :
Started InitTxTest in 2.957 seconds (process running for 4.259)
2023-10-15T13:30:03.470+09:00 TRACE 21664 --- [ main] o.s.t.i.TransactionInterceptor :
Getting transaction for [hello.springtx.apply.InitTxTest$Hello.initV2]
2023-10-15T13:30:03.471+09:00 INFO 21664 --- [main] hello.springtx.apply.InitTxTest$Hello :
@EventListener Transaction active = true
2023-10-15T13:30:03.471+09:00 TRACE 21664 --- [main] o.s.t.i.TransactionInterceptor :
Completing transaction for [hello.springtx.apply.InitTxTest$Hello.initV2]
여기 보면 대충 이해가 됨.
뭐 일단 컨테이너? 빈? 이런 거 JPA EntityManager 관련해서 초기화 되고,
@PostConstruct가 실행이 됨. 이 때는 @Transactional 적용 안되고 false
그 다음, 완전히 InitTxTest 클래스가 초기화가 되고, 시작됨.
그 후 @EventListener(ApplicationReadyEvent.class) 가 이제 모둔 준비가 됐고, 사용할 준비가 되었으니 바로 실행 되는데,
먼저 트랜잭셔널 얻었다고, 프록시가 가로채서 시작됨.
그리고 @EventListener(ApplicationReadyEvent.class) 가 실행되고,
또 프록시가 가로채서 트랜잭션을 안정적으로 끝냄.
그래서
뭔가 시작할 때 프록시 환경에서 뭔가를 하고 싶으면 @EventListener(ApplicationEadyEvent.class)를,
아니면 그냥 프록시 환경 말고 객체(빈)가 만들어 진 직후 하고 싶은 것이 있으면 @PostConstruct에서
객체 생성 -> @PostConstruct -> 빈 등록 및 모든 초기작업 완료 -> 실행 가능 -> @EventListener(ApplicationEadyEvent.class)
'스프링 > 6. 스프링 DB-2' 카테고리의 다른 글
47. 트랜잭션과 예외 -활용 (0) | 2023.10.16 |
---|---|
46. 트랜잭션과 예외 (0) | 2023.10.16 |
43. 트랜잭션 AOP 주의사항 2 -프록시 내부호출 (0) | 2023.10.15 |
42. 트랜잭션 AOP 주의사항 -프록시 내부 호출 (0) | 2023.10.14 |
41. 스프링 트랜잭션 우선순위 (0) | 2023.10.14 |