[AOP? 먹는건가?] AOP Proxy 톺아보기

David Lee·2024년 1월 26일
0

AOP? 먹는건가?

목록 보기
3/3
post-thumbnail

이 포스트는 Spring Framework Documentation에서 제공하는 Proxying Mechanisms문서의 예제를 활용하여 설명을 진행하고 있습니다.

Spring AOP의 가장 중요한 핵심인 AOP Proxy가 어떤 식으로 동작하는지 살펴봅니다.

시작하기 전!

Proxy 적용 전과 적용 후에 대해서 살펴보기 위해서 간단한 클래스를 하나 작성합니다.

// Source from Spring Framework Documentation
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...
	}
}

Proxy를 적용하지 않은 경우엔 어떤 식으로 동작할까?

Proxy를 적용하지 않고 기존 객체를 생성 및 메서드를 사용하는 시나리오를 살펴보면 아래와 같습니다.

// Source from Spring Framework Documentation
public class Main {

	public static void main(String[] args) {
		Pojo pojo = new SimplePojo();
		// this is a direct method call on the 'pojo' reference
		pojo.foo();
	}
}

Main method에서 객체 참조에 의한 메서드를 호출하면 아래 이미지처럼 해당 객체에 대한 메서드가 직접적으로 호출됩니다.

Proxy 적용해보기

Proxy를 적용해 메서드의 참조가 프록시인 경우의 시나리오는 어떻게 이루어질까요?

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();
	}
}

여기서 우리가 확인해야할 점은 Main 클래스의 main 메서드에서 클라이언트 코드에 대해서 프록시 참조를 진행했다는 점입니다.
main에서 호출하는 pojo.foo()의 경우 아래 그림과 같이 프록시 객체에서의 메서드 호출로 진행됩니다. → 이를 통해서 특정 메서드 호출과 관련된 Advice를 적용할 수 있게 되는 것입니다.
하지만 메서드 호출이 최종적으로 SimplePojo에 도달한다면 this.bar()와 같이 객체 자체에 대한 호출은 직접적으로 객체에 참조되어 호출이 됩니다. → 자체 호출이 있는 경우에 대해서는 메서드 호출에 의한 Advice를 적용할수 없는 것입니다.

Spring AOP를 완벽히 적용시키기

자체 호출을 사용하지 않도록 코드를 리팩토링하는 방식이 가장 알맞는 방식이라고 할 수 있습니다.

Spring Framework Documentation에서는 아래 예시를 horrendous한 방식이라고 표현합니다.

public class SimplePojo implements Pojo {

	public void foo() {
		// this works, but... gah!
		((Pojo) AopContext.currentProxy()).bar();
	}

	public void bar() {
		// some logic...
	}
}

위와 같은 방식으로 SimplePojo 클래스를 리팩토링하고 main 메서드에 factory.setExposeProxy(true)를 추가한다면 SimplePojo 클래스는 Spring AOP에 완전히 적용될 수 있습니다.

AspectJ를 활용하는 경우 자체 호출과 관련된 문제를 신경쓰지 않아도 됩니다. 왜냐하면 AspectJ는 프록시 기반의 AOP 프레임워크가 아니기 때문입니다.

참고문헌

profile
쌓아가기

0개의 댓글

관련 채용 정보