
트랜잭션의 실행 과정은 다음과 같다.
기억해야 할 점은 AOP Proxy를 거친다는 점이다.
AOP 기반 기능을 사용할 때 실제 객체 대신 프록시 객체가 생성되고 메서드 호출을 가로채서 트랜잭션을 처리한다.
클래스에 @Transactional이 하나라도 존재하는 경우 클래스의 Proxy 객체를 생성한다.
@Transactional이 하나라도 존재하는 경우 클래스의Proxy 객체를 생성하는 이유
-> AOP는 기본적으로 클래스 또는 인터페이스 수준에서 동작하기 때문이다.
AOP 기능을 적용하기 위해 매서드 실행 전후로 특정 로직을 삽입해야 한다.
트랜잭션의 경우 트랜잭션을 시작하고 커밋하거나 롤백하는 로직이 필요한데 이 기능을 프록시가 수행한다.

@Service
public class MyService {
public void outerMethod() {
// 비지니스 로직
innerMethod();
}
@Transactional
public void innerMethod() {
// 비지니스 로직
}
}
이 상황에서
outerMethod를 호출할 경우innerMethod의 트랜잭션이 작동하지 않는다.
정상적인 호출의 경우 다음과 같다.

innerMethod를 호출할 경우 @Transactional이 있기 때문에 프록시 객체를 거쳐 트랜잭션이 적용된 후 함수를 실행한다.
만약 outerMethod를 호출한 경우 객체를 직접 호출하기 때문에 트랜잭션이 적용되지 않는다.

innerMethod에@Transactional이 있으니까innerMethod를 호출했을 때 프록시를 거쳐야 하는거 아닌가요??
java언어에서 메서드 앞에 별도 참조가 없으면this라는 뜻이다.
따라서 자기 자신의 인스턴스인target의innerMethod를 가리킨다.
이 예외를 해결하는 가장 간단한 방법은 클래스를 구분하는 것이다.
예를 들어 OuterClass와 InnerClass로 구분하면 이와같은 예외가 발생하지 않고 정상적으로 실행될 것이다.
만약 둘 다 @Transactional이 존재하는 경우
@Service
public class MyService {
@Transactional
public void outerMethod() {
// 비지니스 로직
innerMethod();
}
@Transactional
public void innerMethod() {
// 비지니스 로직
}
}
결론부터 말하자면 innerMethod도 트랜잭션이 적용된다.
하지만 이 경우에도 innerMethod를 호출할 때 역시 프록시를 거치는 것이 아니라 직접 호출되기 때문에 innerMethod의 @Transactional은 무시된다.
outerMethod에 @Transactional이 적용되어 있으므로, 이미 트랜잭션이 활성화된 상태에서 innerMethod가 호출된다.innerMethod는 outerMethod의 트랜잭션에 포함되어 실행된다.innerMethod도 트랜잭션이 적용된다.@PostConstruct와 @Transactional을 함께 사용하면 트랜잭션이 적용되지 않는다.
@PostConstruct가 Spring 빈 초기화 단계에서 실행되기 때문이다. 이 시점에서는 AOP가 적용되기 전에 메소드가 실행되기 때문에 트랜잭션을 적용할 수 없다.