execution(수식어? 반환타입 패키지.클래스.메서드(파라미터) 예외?)
execution(* com.example.service.*.*(..))
│ │ │ │ └ 파라미터: (..) = 개수/타입 무관
│ │ │ └ 메서드: * = 모든 메서드
│ │ └ 클래스: * = 모든 클래스
│ └ 패키지
└ 반환타입: * = 모든 타입
💻 자주 쓰는 패턴
// service 패키지 + 하위 패키지(..) 전체
@Pointcut("execution(* com.example.service..*(..))")
// 이름이 find 로 시작하는 메서드만
@Pointcut("execution(* com.example..*.find*(..))")
// 반환타입이 특정 타입
@Pointcut("execution(java.util.List com.example..*(..))")
// 파라미터가 (Long) 하나인 메서드
@Pointcut("execution(* com.example..*(Long))")
💻 다른 지정자
// within: 특정 타입(클래스) 내부의 모든 조인포인트
@Pointcut("within(com.example.service.MemberService)")
// @annotation: 특정 어노테이션이 붙은 메서드 (5·6강 핵심)
@Pointcut("@annotation(com.example.aop.LogExecutionTime)")
// @within: 특정 어노테이션이 붙은 클래스의 모든 메서드
@Pointcut("@within(org.springframework.stereotype.Service)")
// bean: 특정 이름의 스프링 빈
@Pointcut("bean(memberService)")
💻 조합
// service 패키지이면서 + Repository는 제외
@Pointcut("execution(* com.example.service..*(..)) " +
"&& !execution(* com.example.service..*Repository.*(..))")
// 두 Pointcut 메서드를 조합
@Before("serviceLayer() && loggable()")
public void advice(JoinPoint jp) { /* ... */ }
⚠️ 주의사항
스프링 AOP는 메서드 실행(execution) 조인포인트만 지원합니다(필드 접근 등은 불가 — 그건 AspectJ 위빙 필요).
표현식이 너무 넓으면(예: execution(* *(..))) 모든 빈에 프록시가 생겨 성능·예측성이 나빠집니다.
💡 팁
공통 Pointcut은 별도 클래스에 모아 @Pointcut 메서드로 정의하고 여러 Aspect에서 참조하세요.
실무에서는 패키지 표현식보다 커스텀 어노테이션(@annotation) 방식이 의도가 명확해 선호됩니다(다음 강).