본문 바로가기
Everyday Study

2024.08.30(금) { PCD-this와target차이, proceed() }

by xogns93 2024. 8. 30.

thistarget은 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: 실제 타겟 객체를 대상으로 작동하며, 실제 객체가 특정 타입을 구현하는 경우에 포인트컷이 적용됩니다. 프록시가 아닌 실제 객체의 타입을 기반으로 포인트컷이 적용됩니다.

언제 thistarget을 사용해야 하는가?

  • 프록시 기반 AOP 사용 시: 만약 AOP 프레임워크가 프록시를 사용하여 객체를 감싸고 있다면, this를 사용할 때는 프록시 객체에 포인트컷이 적용됩니다. 이 경우 this는 프록시의 타입과 일치하는지 확인합니다.
  • 실제 객체를 대상으로 하고 싶을 때: 만약 프록시가 아닌 실제 객체의 타입에 포인트컷을 적용하고 싶다면 target을 사용합니다.

정리

  • thistarget은 비슷해 보일 수 있지만, 프록시 객체와 실제 객체의 타입을 각각 타겟으로 한다는 차이점이 있습니다.
  • 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() 메서드에 전달되는 인자 수가 일치해야 합니다.
  • 이 차이를 염두에 두고, 두 프레임워크에서 모두 호환되는 어드바이스 코드를 작성해야 합니다.