@Aspect
public class LogAop{
...
}
@Aspect Annotation의 경우 해당 Class가 횡단관심사(부가기능) Class임을 알려주는 Annotation입니다.
@Aspect Annotation이 부여되었다고 해서 자동으로 Bean으로 등록되는것이 아니므로 따로 Bean으로 등록을 해주는 작업이 필요합니다.
@Aspect
public class LogAop{
@Around("execution(* com.example.Car.accelerate(..))")
public Object loggin(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
try{
System.out.println(methodName + "is Start");
Object obj = joinPoint.proceed();
return obj;
}finally{
System.out.println(methodName + "is Finish");
}
}
}
@Around Annotation은 핵심관심사의 실패여부와 상관없이 전 후로 실행되도록 하는 Advice입니다. @Around Annotation의 속성값으로 PointCut을 전달해주어야 합니다.
@Pointcut은 횡단관심사(부가기능)이 적용될 JoinPoint들을 정의한 것입니다.
@Pointcut Annotation의 경우 조금 복잡한 표현식을 가지고 있습니다.
@Pointcut("execution(public void get*(())")
퍼블릭형의 반환형이 없는 (public void)형태의 메소드 중 get으로 시작하는 (get*) 모든 메소드중 파라미터가 존재하지 않는 (()) 메소드들에게 적용
@Pointcut("execution(* *(..))")
첫번째 기호는 접근제어자와 반환형 모두를 상관하지 않고 적용.
두번째 기호는 어떤한 경로에 존재하는 클래스도 상관하지 않고 적용
마지막으로 (..)은 메소드의 파라미터가 몇개가 존재하던지 상관없이 실행하는 경우
@Pointcut("execution(* com.java.example.Car.accelerate())")
첫번째 * 기호는 접근제어자, 반환형을 상관하지 않는다는 의미
com.java.example.Car.accelerate()는 해당 Car 클래스의 accelerate() 파라미터가 없는 메소드가 호출될 때 실행하는 경우를 의미
@Pointcut("execution(* com.java..*.*(())")
com.java 패키지 및 하위 패키지의 모든 클래스의 파라미터가 없는 모든 메서드에 적용한다는 의미
@Aspect
public class LogAop{
@Around("execution(* com.java.car..*.*(())")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable {
String methodName = joinPoint.getSignature().toShortString();
try{
System.out.println(methodName + "is Start");
Object obj = joinPoint.proceed();
return obj;
}finally{
System.out.println(methodName + "is Finish");
}
}
}
패키지의 모든 메소드에 적용할 때 사용합니다.
@Pointcut("within(com.java.example.*)")
@Pointcut("within(com.java.example..*)")
@Pointcut("within(com.java.example.Car)")
@Aspect
public class LogAop{
@Around("within(com.java.example.*)")
public Object loggin(ProceedingJoinPoint joinPoint) throws Throwable{
String methodName = joinPoint.getSignature().toShortString();
try{
Systme.out.println(methodName + "is Start");
Object obj = joinPoint.proceed();
return obj;
}finally{
System.out.println(methodName + "is Finish");
}
}
}
@Pointcut(bean(car))
car라는 bean id를 가지고 있는 bean에게 적용한다는 의미
@Around("bean(car)")
public Object loggin(ProceedingJoinPoint joinPoint) throws Throwable{
String methodName = joinPoint.getSignature().toShortString();
try{
System.out.println(methodName + "is Start");
Object obj = joinPoint.proceed();
return obj;
}finally{
System.out.println(methodName + "is Finish");
}
}
사용자가 직접 만든 Annotation에 기반해 Aspect를 적용할 수 있습니다.
@Documented
@Target(ElementType.METHOD)
public @interface PerfLogging{}
@Aspect
public class LogAop{
@Around("@annotation(PerfLogging)")
public Object logging(ProceedingJoinPoint joinPoint) throws Throwable{
String methodName = joinPoint.getSignature().toShortString();
try{
System.out.println(methodName + "is Start");
Object obj = joinPoint.proceed();
return obj;
}finally{
System.out.println(methodName + "is Finish");
}
}
}
그 후 어드바이스 어노테이션안에 @annotation("어노테이션 class명")을 입력해주면 됩니다.
ex) @Before() 괄호 내에 "execution(* runSomething())" 핵심 메서드 경로를 @Pointcut에 한 번만 설정해주면 생성하는 공통 메서드 매개변수론 지시자(메서드)명만 써주면 됩니다.
@Aspect
public class MyAspect{
// 중복을 해결해주는 어노테이션 - 포인트컷 지시자를 미리 설정해두는 것
@Pointcut("execution(* runSomething())")
private void pointcut() {}
// 핵심 메서드 실행 전 실행
@Before("pointcut()")
public void before(JoinPoint joinPoint){
System.out.println("메서드 before");
}
// 핵심 메서드 실행 후 실행
@After("pointcut()")
public void after(JoinPoint joinPoint){
System.out.println("메서드 after");
}
}