Spring AOP Pointcut 표현식 - this, target

목차

포인트컷 표현식 - this, target

this 와 target 은 객체를 대상으로 AOP 를 적용할 때 사용하는 포인트컷 표현식입니다. 두 표현식 모두 상위 타입이나 인터페이스를 이용해 AOP 를 적용할 수 있습니다.

this 는 스프링 빈으로 등록돼 있는 프록시 객체를 대상으로 Advice 를 적용합니다. 때문에 스프링에서 프록시 객체를 생성하는 전략에 따라 AOP 가 다르게 적용될 수 있습니다.

target실제 객체를 대상으로 Advice 를 적용합니다.

this 와 target 작동방식 확인을 위한 테스트 코드

@Autowired
MemberService memberService;

@Test
void success() {
log.info("memberService Proxy={}", memberService.getClass());
memberService.hello("helloA");
}

@Aspect
static class ThisTargetAspect {

//부모 타입 허용
@Around("this(hello.aop.member.MemberService)")
public Object doThisInterface(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[this-interface] {}", joinPoint.getSignature());
return joinPoint.proceed();
}

//부모 타입 허용
@Around("target(hello.aop.member.MemberService)")
public Object doTargetInterface(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[target-interface] {}", joinPoint.getSignature());
return joinPoint.proceed();
}

@Around("this(hello.aop.member.MemberServiceImpl)")
public Object doThis(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[this-impl] {}", joinPoint.getSignature());
return joinPoint.proceed();
}

@Around("target(hello.aop.member.MemberServiceImpl)")
public Object doTarget(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("[target-impl] {}", joinPoint.getSignature());
return joinPoint.proceed();
}
}

JDK 동적 프록시를 이용한 프록시 객체 생성

프록시 객체와 구현객체인 MemberServiceImpl 모두 MemberService 인터페이스를 이용해 생성됐습니다.

this 와 target 모두 MemberService 를 지정하면 AOP 가 적용됩니다. 하지만, MemberServiceImpl 을 지정할 경우 프록시 객체를 대상으로 하는 this 는 AOP 가 적용되지 않습니다.

JDK 동적 프록시를 이용한 프록시 객체 생성

JDK 동적 프록시 객체에 대한 AOP 적용 결과

JDK 동적 프록시로 생성된 객체의 경우 this 에 구현 객체를 지정했을 때 AOP 가 적용되지 않은 것을 확인할 수 있습니다.

2024-11-28 13:43:19.569  INFO 27320 --- [    Test worker] h.a.p.ThisTargetTest$ThisTargetAspect    : [target-impl] String hello.aop.member.MemberService.hello(String)
2024-11-28 13:43:19.569 INFO 27320 --- [ Test worker] h.a.p.ThisTargetTest$ThisTargetAspect : [target-interface] String hello.aop.member.MemberService.hello(String)
2024-11-28 13:43:19.569 INFO 27320 --- [ Test worker] h.a.p.ThisTargetTest$ThisTargetAspect : [this-interface] String hello.aop.member.MemberService.hello(String)

CGLIB 를 이용한 프록시 객체 생성

CGLIB 를 사용하게 될 경우 프록시 객체는 구현객체 MemberServiceImpl 를 기반으로 생성됩니다.

때문에 this 와 target 모두 MemberService 와 구현체인 MemberServiceImpl 를 지정하더라도 AOP 가 적용됩니다.

CGLIB 를 이용한 프록시 객체 생성

CGLIB 프록시 객체에 대한 AOP 적용 결과

CGLIB 로 생성된 객체의 경우 this 에 구현 객체를 지정했을 때 AOP 가 적용되지 않은 것을 확인할 수 있습니다.

2024-11-28 13:43:42.768  INFO 28167 --- [    Test worker] h.a.p.ThisTargetTest$ThisTargetAspect    : [target-impl] String hello.aop.member.MemberServiceImpl.hello(String)
2024-11-28 13:43:42.768 INFO 28167 --- [ Test worker] h.a.p.ThisTargetTest$ThisTargetAspect : [target-interface] String hello.aop.member.MemberServiceImpl.hello(String)
2024-11-28 13:43:42.768 INFO 28167 --- [ Test worker] h.a.p.ThisTargetTest$ThisTargetAspect : [this-impl] String hello.aop.member.MemberServiceImpl.hello(String)
2024-11-28 13:43:42.768 INFO 28167 --- [ Test worker] h.a.p.ThisTargetTest$ThisTargetAspect : [this-interface] String hello.aop.member.MemberServiceImpl.hello(String)
Share