- Spring Transaction 22022년 09월 22일
- starryeye
- 작성자
- 2022.09.22.:26
트랜잭션 AOP 주의사항에 대해 알아보자.
1. 동일 클래스에서 내부 @Transaction 메서드 호출
@Component class Service { @Transaction public void A() { } public void B() { A(); } } @Component @RequiredArgsConstructor class Controller { private final Service s; public void X() { s.A(); } public void Y() { s.B(); } }
Service 클래스에서 A() 메서드에 @Transaction 어노테이션이 적용되어있다.
B() 메서드는 @Transaction 어노테이션이 적용되어 있지 않고 내부에서 A()를 호출하고 있다.
Controller 클래스에서 Service 클래스를 참조하고 있다.
Service 클래스는 @Transaction 어노테이션이 존재하므로
스프링 컨테이너에 트랜잭션 프록시 객체가 등록되고..
Controller 클래스에 의존성 주입이 될 때 트랜잭션 프록시 객체가 주입된다.
Controller 클래스에서..
X()를 호출할 경우..
-> Service 클래스 트랜잭션 프록시 객체의 A() 메서드가 호출되며..
-> A() 메서드에는 @Transaction 어노테이션이 적용되어 있으므로 트랜잭션이 적용된다.
-> 트랜잭션 적용 후, 실제 Service 객체 인스턴스의 A() 메서드를 호출한다.
Controller 클래스에서..
Y()를 호출할 경우..
-> Service 클래스 트랜잭션 프록시 객체의 B() 메서드가 호출되며..
-> B() 메서드에는 @Transaction 어노테이션이 적용되어 있지 않으므로 트랜잭션이 적용되지 않는다.
-> 실제 Service 객체 인스턴스의 B() 메서드를 호출한다.
-> B() 메서드에서 A() 메서드를 호출한다.
이 경우, this.A()이고, 트랜잭션 프록시 메서드가 호출된 게 아닌,
실제 객체에서 단순 자신 메서드 호출이므로 트랜잭션이 적용되지 않는다.
-> 정리하자면, 내부 호출은 프록시를 거치지 않으며 트랜잭션을 적용할 수 없다.
<해결>
-> A() 메서드와 B() 메서드를 클래스 자체를 분리하면 가장 간단하게 해결 가능.
2. Public 메서드만 트랜잭션이 적용된다.
private, protected, default 에는 트랜잭션이 적용되지 않는다.
-> 하지만.. 트랜잭션 프록시는 만들어진다.
-> 예외도 없고 트랜잭션 적용만 무시된다.
3. 스프링 초기화 시점에는 트랜잭션 AOP가 적용 안될 수 도 있다.
어떤 메서드(초기화 코드)에..
@PostConstruct, @Transaction 두 어노테이션을 적용하면..
해당 메서드는 트랜잭션이 적용되지 않는다.
-> 초기화 코드가 먼저 호출 된 후, 트랜잭션 AOP가 적용되기 때문
<해결>
@EventListener(value = ApplicationReadyEvent.class) 와 @Transaction 을 같이 사용하자.
-> 트랜잭션 AOP를 포함한 스프링 컨테이너가 완전히 생성되고
-> 해당 어노테이션이 붙은 메서드를 호출 해준다.
'Spring > DB, Cache 연동' 카테고리의 다른 글
Spring Transaction 4 (0) 2022.09.28 Spring Transaction 3 (0) 2022.09.22 Spring Transaction 1 (0) 2022.09.22 JPA 찍먹 1 (1) 2022.09.09 MyBatis 1 (0) 2022.08.23 다음글이전글이전 글이 없습니다.댓글