[Spring] 포인트컷 지시자
@Pointcut("execution(...)")
지금까지 포인트컷을 작성할 때는 AspectJ가 제공하는 execution 지시자를 사용해서 작성했다.
execution 지시자를 가장 많이 사용하긴 하지만.. AspectJ는 다른 지시자도 제공한다.
포인트컷을 작성하는 방식을 살펴보자.
execution
execution(접근제어자? 반환타입 선언타입?메서드명(파라미터) 예외?)
?가 뒤에 붙어있으면 생략 가능함을 의미한다.
선언타입은 패키지명과 클래스명을 모두 포함하고 * 표현을 사용할 수 있다.
pointcut.setExpression("execution(public String start.aop.member.MemberServiceImpl.hello(String))");
pointcut.setExpression("execution(* *(..))");
pointcut.setExpression("execution(* start(..))");
pointcut.setExpression("execution(* hello.aop.member..*.*(..))");
* 은 아무 값이나 허용함을 의미하고 .. 은 파라미터에서 사용될 시 파라미터의 타입과 개수에 상관없음을 의미하고 패키지에서 사용될 시 해당 위치의 패키지와 하위 패키지도 포함함을 의미한다.
execution 에서는 부모 타입에서 정의한 메서드를 지정해주면 자식 타입에서 해당 메서드를 구현하고 있다면 AOP가 지정된다.
within
within 지시자는 특정 타입 내의 조인포인트로 매칭을 제한한다. (조인포인트 : Aspect가 적용되는 지점)
execution 지시자가 제공하는 기능 중 타입 부분만 사용한다고 보면 되지만 execution과는 다르게 표현식에 부모 타입을 지정하면 안된다.
거의 사용하지 않는다.
args
말 그대로 파라미터를 조인포인트로 매칭을 제한한다.
execution 지시자가 제공하는 기능 중 파라미터 부분만 사용하지만 execution은 파라미터 타입이 정확하게 매칭되어야 하지만 args는 실제로 넘어온 파라미터 객체를 보고 판단한다.
execution은 정적 정보로만 판단하고 args는 동적 정보로 판단한다고 생각하면 된다.
단독으로 사용하기보다는 주로 파라미터 바인딩에서 사용한다.
@target, @within
두 지시자 모두 실행 객체의 클래스에 주어진 타입의 애너테이션이 있는지를 조인포인트로 설정한다.
클래스 레벨에서 수행된다.
@target은 부모 클래스까지 조인포인트로 적용하지만 @within은 해당 메서드만 조인포인트로 적용한다.
파라미터 바인딩에서 사용된다.
@annotation
실행 중인 메서드에 붙은 애너테이션으로 조인포인트를 설정한다.
@Transactional 애너테이션이 붙은 모든 메서드에 AOP를 적용할 수 있다.
bean
스프링 전용 포인트컷 지시자로 스프링 빈의 이름으로 조인포인트를 설정한다.
this, target
AOP를 사용하면 실제 객체 대신 프록시 객체가 스프링 빈으로 등록된다.
this는 스프링 빈 객체 (프록시) 를 대상으로 조인포인트를 지정하고 target은 프록시가 가르키는 실제 대상으로 조인포인트를 지정한다. (모두 부모 타입을 포함한다)
프록시를 대상으로 하는 this 지시자는 구체 클래스를 지정 시 프록시 생성 전략 (JDK 동적 프록시, CGLIB) 에 따라 다른 결과가 나올 수 있다.
JDK 동적 프록시 전략 사용 시 프록시는 구현체에 대한 정보를 알지 못한다.
포인트컷 표현식을 사용해 어드바이스의 메서드에 매개변수를 전달할 수 있다.
추가된 매개변수는 실행 중인 조인포인트와 관련된 정보를 얻을 수 있다.
@Pointcut("execution(* start.aop.member..*.*(..))")
private void allMember() {
}
@Around("allMember()")
public Object logArgs1(ProceedingJoinPoint joinPoint) throws Throwable {
Object arg1 = joinPoint.getArgs()[0];
log.info("[logArgs1]{}, arg={}", joinPoint.getSignature(), arg1);
return joinPoint.proceed();
}
@Around("allMember() && args(arg,..)")
public Object logArgs2(ProceedingJoinPoint joinPoint, Object arg) throws Throwable {
log.info("[logArgs2]{}, arg={}", joinPoint.getSignature(), arg);
return joinPoint.proceed();
}
@Before("allMember() && args(arg,..)")
public void logArgs3(String arg) {
log.info("[logArgs3] arg={}", arg);
}
@Before("allMember() && this(obj)")
public void thisArgs(JoinPoint joinPoint, MemberService obj) {
log.info("[this]{}, obj={}", joinPoint.getSignature(), obj.getClass());
}
@Before("allMember() && target(obj)")
public void targetArgs(JoinPoint joinPoint, MemberService obj) {
log.info("[target]{}, obj={}", joinPoint.getSignature(), obj.getClass());
}
@Before("allMember() && @target(annotation)")
public void atTarget(JoinPoint joinPoint, ClassAop annotation) {
log.info("[@target]{}, obj={}", joinPoint.getSignature(), annotation);
}
@Before("allMember() && @within(annotation)")
public void atWithin(JoinPoint joinPoint, ClassAop annotation) {
log.info("[@within]{}, obj={}", joinPoint.getSignature(), annotation);
}
@Before("allMember() && @annotation(annotation)")
public void atAnnotation(JoinPoint joinPoint, MethodAop annotation) {
log.info("[@annotation]{}, annotationValue={}", joinPoint.getSignature(), annotation.value());
}
어드바이스의 동작을 세부적으로 제어할 때 사용하자.
arg, @args, @target 등 특정 포인트컷 지시자는 단독으로 사용할 수 없다.
해당 지시자들은 프록시를 통해 실제 객체 인스턴스가 생성되고 실행될 때 어드바이스 적용 여부를 판단할 수 있는데.. 프록시는 스프링 컨테이너가 초기화 될 때 적용할 수 있으니 지시자가 있는 모든 스프링 빈에 AOP를 적용하려 시도한다.
스프링 빈에 AOP 프록시를 적용하려 할 때 final로 지정된 빈이 있는 경우 오류가 발생할 수 있으니 프록시 적용 대상을 축소하는 표현식과 함께 사용하는 편이 합리적이다.
@Around("execution(* hello.aop..*(..)) && @target(start.aop.member.annotation.ClassAop)")
'Spring > Spring' 카테고리의 다른 글
[Spring] AOP 주의사항 (0) | 2023.07.29 |
---|---|
[Spring] AOP 적용 (0) | 2023.07.27 |
[Spring] 빈 후처리기 (0) | 2023.07.26 |
[Spring] 프록시 팩토리 (0) | 2023.07.24 |
[Spring] 동적 프록시 기술 (0) | 2023.07.23 |
댓글
이 글 공유하기
다른 글
-
[Spring] AOP 주의사항
[Spring] AOP 주의사항
2023.07.29 -
[Spring] AOP 적용
[Spring] AOP 적용
2023.07.27 -
[Spring] 빈 후처리기
[Spring] 빈 후처리기
2023.07.26 -
[Spring] 프록시 팩토리
[Spring] 프록시 팩토리
2023.07.24