this
와 target
은 AspectJ에서 사용되는 PCD(Pointcut Designator)로, 둘 다 특정 객체와 관련된 조인 포인트를 지정하지만, 이 둘은 중요한 차이가 있습니다. 두 가지를 혼용하지 않도록 주의해야 합니다.
1. this
PCD
- 정의:
this
PCD는 현재 실행 중인 객체가 특정 타입을 구현하는지를 검사합니다. 이때this
는 프록시(proxy) 객체를 대상으로 합니다. 주로 스프링 AOP와 같은 프록시 기반 AOP 프레임워크에서 사용됩니다. - 사용 예시:
pointcut myPointcut() : this(com.example.MyInterface);
- 위 예시는 조인 포인트가 현재
com.example.MyInterface
타입의 객체에서 실행되고 있는지를 확인합니다. - 즉, 프록시 객체가 특정 인터페이스나 클래스를 구현하는 경우에 포인트컷이 적용됩니다.
- 위 예시는 조인 포인트가 현재
2. target
PCD
- 정의:
target
PCD는 실제 타겟 객체가 특정 타입을 구현하는지를 검사합니다.target
은 프록시가 아닌 실제 비즈니스 로직 객체를 대상으로 합니다. - 사용 예시:
pointcut myPointcut() : target(com.example.MyInterface);
- 위 예시는 조인 포인트가 실제 타겟 객체가
com.example.MyInterface
타입일 때 적용됩니다. - 즉, 실제 객체의 타입이 특정 인터페이스나 클래스와 일치하는 경우에 포인트컷이 적용됩니다.
- 위 예시는 조인 포인트가 실제 타겟 객체가
차이점 요약
this
: 프록시 객체를 대상으로 작동하며, 프록시 객체가 특정 타입을 구현하는 경우에 포인트컷이 적용됩니다. 주로 스프링 AOP처럼 프록시 기반의 AOP 구현에서 사용됩니다.target
: 실제 타겟 객체를 대상으로 작동하며, 실제 객체가 특정 타입을 구현하는 경우에 포인트컷이 적용됩니다. 프록시가 아닌 실제 객체의 타입을 기반으로 포인트컷이 적용됩니다.
언제 this
와 target
을 사용해야 하는가?
- 프록시 기반 AOP 사용 시: 만약 AOP 프레임워크가 프록시를 사용하여 객체를 감싸고 있다면,
this
를 사용할 때는 프록시 객체에 포인트컷이 적용됩니다. 이 경우this
는 프록시의 타입과 일치하는지 확인합니다. - 실제 객체를 대상으로 하고 싶을 때: 만약 프록시가 아닌 실제 객체의 타입에 포인트컷을 적용하고 싶다면
target
을 사용합니다.
정리
this
와target
은 비슷해 보일 수 있지만, 프록시 객체와 실제 객체의 타입을 각각 타겟으로 한다는 차이점이 있습니다.this
는 프록시 객체의 타입을 확인하고,target
은 실제 비즈니스 로직 객체의 타입을 확인합니다.- 사용 환경에 따라 이 둘을 구분하여 사용하는 것이 중요합니다. 프록시가 아닌 실제 객체의 타입을 확인하고 싶다면
target
을, 프록시 객체에 포인트컷을 적용하고 싶다면this
를 사용해야 합니다.
Spring AOP와 AspectJ의 proceed() 메서드 동작 차이와 호환성 고려사항
1. proceed() 메서드의 기본 개념
- proceed() 메서드는 Around 어드바이스에서 사용되며, 타겟 메서드를 실행하는 역할을 합니다.
- 이 메서드를 호출하지 않으면 타겟 메서드가 실행되지 않습니다. 따라서 어드바이스 내에서 proceed()를 호출하는 것이 중요합니다.
2. 두 가지 AOP 접근 방식: Spring AOP vs. AspectJ
- Spring AOP:
- 주로 프록시 기반으로 동작하며, **실행 지점(Execution Join Points)**에만 적용됩니다.
- 상대적으로 단순하고, Spring 프레임워크 내에서 쉽게 통합할 수 있습니다.
- AspectJ:
- 컴파일 타임 또는 로드 타임에 바이트코드를 조작하는 강력한 AOP 프레임워크입니다.
- 더 복잡한 AOP 기능을 제공하며, Spring AOP보다 더 넓은 범위의 조인 포인트(Join Points)를 지원합니다.
3. proceed() 메서드의 동작 차이점
- Spring AOP에서의 proceed():
- proceed(Object[] args)를 호출할 때, args 배열은 타겟 메서드에 전달될 인자들을 나타냅니다.
- 인자를 제공하지 않으면 원래의 인자가 사용되며, 새로운 인자 배열을 제공하면 이 인자들이 타겟 메서드에 전달됩니다.
- AspectJ에서의 proceed():
- AspectJ에서 proceed()를 호출할 때, 어드바이스 메서드가 받는 인자의 수와 proceed() 메서드에 전달되는 인자의 수가 일치해야 합니다.
- 인자의 위치에 따라 타겟 메서드에 적용되는 값이 달라질 수 있으며, 이는 원래 인자를 대체할 수 있습니다.
4. 호환성 문제
- Spring AOP와 AspectJ는 proceed() 메서드를 처리하는 방식에서 차이가 있습니다. 동일한 어드바이스 코드를 두 프레임워크에서 모두 사용하려면 이 차이를 고려해야 합니다.
- @AspectJ 애노테이션을 사용하여 AspectJ 컴파일러와 위버를 사용할 때, Spring AOP의 단순한 인자 처리 방식과 AspectJ의 방식 간의 차이를 이해하고 대응해야 합니다.
5. 해결책
- Spring AOP와 AspectJ에서 모두 호환되는 어드바이스 코드를 작성하는 것이 중요합니다. 이를 위해 각 프레임워크의 proceed() 메서드 처리 방식을 고려한 어드바이스 파라미터 처리 방법을 사용해야 합니다.
- Around 어드바이스에서 리턴된 값은 최종적으로 메서드 호출자가 보게 되는 값이므로, 캐싱 등과 같은 동작을 구현할 때 이 점을 고려해야 합니다.
- proceed() 메서드는 어드바이스 본문 내에서 한 번, 여러 번, 또는 전혀 호출되지 않을 수도 있으며, 이 모든 경우가 합법적입니다.
정리
- Spring AOP와 AspectJ는 AOP 기능을 제공하지만 proceed() 메서드를 처리하는 방식에서 차이가 있습니다.
- Spring AOP는 인자 배열을 통해 타겟 메서드에 전달할 인자를 쉽게 변경할 수 있지만, AspectJ에서는 어드바이스 메서드의 인자 수와 proceed() 메서드에 전달되는 인자 수가 일치해야 합니다.
- 이 차이를 염두에 두고, 두 프레임워크에서 모두 호환되는 어드바이스 코드를 작성해야 합니다.
'Study Memo' 카테고리의 다른 글
2024.09.03(화) { 원자성, 바인딩, 모듈, perthis, 자바 에이전트 } (3) | 2024.09.03 |
---|---|
2024.09.02(월) { 인라인 포인트컷, args(제한&가져오기), (0) | 2024.09.02 |
2024.08.29(목) { 위임 한다는것, AspectJ의 아규먼트&파라미터, PCD, 디지그네이터 } (0) | 2024.08.29 |
2024.08.28(수) { Aspect 적용 시점, 메서드 매처(Method Matcher)와 클래스 필터 } (0) | 2024.08.28 |
2024.08.27(화) { 포인트컷 익스프레션, 정적&동적 매칭, @Qualifier, @CustomAnnotation } (0) | 2024.08.27 |