우선 아래 코드를 보자
public class SimplePojo implements Pojo {
public void foo() {
// this next method invocation is a direct call on the 'this' reference
this.bar();
}
public void bar() {
// some logic...
}
}
public class Main {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new SimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(new RetryAdvice());
Pojo pojo = (Pojo) factory.getProxy();
// this is a method call on the proxy!
pojo.foo();
}
}
간단하게 설명하면, SimplePojo에 프록시를 적용하는 상황이다.
이렇게 하면 SimplePojo의 메서드를 호출할 때 RetryAdvice가 호출될 것을 기대할 수 있다.
하지만 실상은, foo를 호출할 때 foo에는 advice가 실행되지만 bar에는 실행되지 않을 것이다.
이는 aop의 self invocation이 발생했기 때문이다.
즉 advice는 정상적으로 실행되지만, bar의 호출은 foo 내부, 즉 advice가 종료된 후에 발생하기에 프록시가 적용되지 않는것이다.
보다 정확하게 설명하자면 foo는 프록시를 거치치만 bar는 직접 내부 메서드를 호출하므로 프록시를 거치치 않는다.
이러한 개념이 AOP의 Self invocation이다.
이는 @Transactional에서도 발생할 수 있다.
Transactional은 기본적으로 aop 기반으로 작동하기 때문이다.
이에 대한 해결책은 세가지가 있다.