우선 아래 코드를 보자

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 기반으로 작동하기 때문이다.

이에 대한 해결책은 세가지가 있다.


  1. self invocation이 발생하지 않도록 코드 리펙토링