@Pointcut 가 아닌 @Around에 execution 명시자를 직접 지정할 수 도 있습니다.
@Asepct
public class CacheAspect{
@Around("execution(public * chap07..*(..))")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
...
}
}
만약 같은 Pointcut을 여러 Advice가 함께 사용한다면 공통 Pointcut을 재사용할 수도 있습니다.
ExeTimeAspect
@Aspect
@Order(1)
public class ExeTimeAspect {
@Pointcut("execution(public * chap07..*(long))")
private void publicTarget() {
}
@Around("publicTarget()")
public Object mesaure(ProceedingJoinPoint joinPoint) throws Throwable{
long start = System.nanoTime();
try {
Object result = joinPoint.proceed();
return result;
} finally {
long finish = System.nanoTime();
Signature sig = joinPoint.getSignature();
System.out.printf("%s.%s(%s) 실행시간 : %d ns\n"
, joinPoint.getTarget().getClass().getSimpleName()
, sig.getName()
, Arrays.toString(joinPoint.getArgs())
, finish - start);
}
}
}
이 코드에서 @Around는 publicTarget() 메서드에 설정한 Pointcut을 사용합니다. publicTarget() 메서드는 private인데 이 경우 같은 클래스에 있는 @Around에서만 해당 설정을 사용할 수 있습니다. 다른 클래스에 위치한 @Around에서 publicTarget() 메서드의 Pointcut을 사용하고 싶다면 publicTarget() 메서드를 public으로 바꾸면 됩니다.
@Aspect
public class ExeTimeAspect{
@Pointcut("execution(public * chap07..*(..))")
public void publicTarget(){
}
}
그리고 해당 Pointcut의 완전한 클래스 이름을 포함한 메서드 이름을 @Around을 사용하면 됩니다. 예를 들어 아래 설정은 CacheAspect 클래스의 @Around 클래스의 @Around 메서드에서 ExeTimeAspect 클래스의 publicTarget()에 정의된 Pointcut을 사용합니다.
@Aspect
public class CacheAspect{
@Around("asepct.ExeTimeAspect.publicTarget()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
...
}
}
CacheAspect와 ExeTimeAspect 클래스는 같은 패키지에 위치하므로 패키지 이름 없이 간단한 클래스 이름으로 설정할 수 있습니다.
@Aspect
public class CacheAspect{
@Around("ExeTimeAspect.publicTarget()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
...
}
}
여러 Aspect에서 공통으로 사용하는 Pointcut 이 있다면 아래와 같이 별도 클래스에 Pointcut을 정의하고 각 Aspect 클래스에서 해당 Pointcut을 사용하도록 구성하면 Pointcut 관리가 편해집니다.
별도 클래스로 분리해서 Pointcut 재사용하기
CommonPointcut
public class CommonPointcut{
@Pointcut("execution(public * chap07..*(..))")
public void commonTarget(){
}
}
CacheAspect
@Aspect
public class CacheAspect{
private Map<Long, Object> cache = new HashMap<>();
@Around("CommonPointcut.commonTarget()")
public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
...
}
}
ExeTimeAspect
@Aspect
public class ExeTimeAspect{
@Around("CommonPointcut.commonTarget()")
public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
...
}
}
위와 같이 @Pointcut을 설정한 CommonPointcut은 빈으로 등록할 필요가 없습니다. @Around에서 해당 클래스에 접근 가능하면 해당 Pointcut을 사용할 수 있습니다.
이것으로 스프링 5책의 AOP 챕터 공부를 끝마치게 되었습니다. 굉장히 어려운 챕터였고, 계속 부딪혀보아야 이해가 될 것 같은 개념이었습니다.
'Spring' 카테고리의 다른 글
[Spring] Spring JDBC - DB 연결해보기 (1) | 2024.02.17 |
---|---|
[Spring] 스프링 DB 연동 (0) | 2024.02.16 |
[Spring] Spring AOP - Advice 적용순서 (0) | 2024.02.14 |
[Spring] AOP - execution 명시자 표현식 (0) | 2024.02.05 |
[Spring] AOP - 프록시 생성방식 (0) | 2024.02.05 |