Spring에서 제공하는 @Aspect를 사용하면 컴파일 빈으로 등록되어 다이나믹 프록시가 작동하게 된다. 하지만 이를 사용하게 되면 문제점이 발생 할 수 있다. aop로 등록한 두 메서드가 있을때,
메서드에서 메서드를 호출하게 되면 내부메서드의 aop가 걸리지 않게 된다는점이다.
다이나믹 프록시에 대해 직접적인 예를 가지고 구현해보자.
CustomerService인터페이스와 이에 대한 구현체인 CustomerServiceImpl,
그리고 프록시 클래스인 CustomerServiceProxy가있다. 프록시 클래스에서 weaving작업을 진행 할것이다.
//인터페이스
public interface CustomerService {
public void dosomething1();
public void doSomething2();
}
//구현체
public class CustomerServiceImpl implements ICustomerService {
public void doSomething1() {
System.out.println("doSomething1()");
doSomething2(); //내부에서 다른 메서드 호출
}
public void doSomething2() {
System.out.println("doSomething2()");
}
//프록시
public class CustomerServiceProxy implements ICustomerService {
private ICustomerService customerService;
public void setCustomerService(ICustomerService customerService) {
this.customerService = customerService;
}
public void doSomething1() {
doBefore();
customerService.doSomething1();
doAfter();
}
public void doSomething2() {
doBefore();
customerService.doSomething2();
doAfter();
}
private void doBefore() {
System.out.println("do some important things before...");
}
private void doAfter() {
// For example, you can commit or roll back a transaction, free resources, etc.
System.out.println("do some important things after...");
}
}
//메인함수
public class TestProxy {
public static void main(String[] args) {
CustomerService serviceProxyTarget = new CustomerServiceImpl();
CustomerServiceProxy serviceProxy = new CustomerServiceProxy();
serviceProxy.setCustomerService(serviceProxyTarget);
ICustomerService serviceBean = (ICustomerService) serviceProxy;
serviceBean.doSomething1();
}
이럴경우에는 doSomething1()의 before와 after는 작용하지만 doSomething에서 호출하는 doSomething2에 해당하는 weaving은 호출이 되지 않을것이다. 왜냐하면 doSomething1에 있는 doSomething2는 프록시가 걸려있지 않기때문이다.
이를 해결할려면 별도의 빈으로 분할 method1/ method2분리하거나 스프링 지향이 아닌 AOP 프레임 워크를 사용하면 된다.
참고자료 및 도움자료:https://www.baeldung.com/spring-aop-vs-aspectj