AOP 의 @Before ,@AfterThrowing, @AfterReturning, @Around
aop에 대해 보강해보았던 점을 기록한다. 개인적으로 @Around 와 ProceedingJoinPoint, Signature 외에는 모르던 터라, 신비하고 기억해야겠다 싶어 타이핑하며 기억을 되새긴다.
execution명시자의 메서드 명과 파라미터 타입을 정확히 개시한 후, && 기호 이후 args 명시자의 속성 값으로 파라미터 명을 개시하면, advice 의 메서드에서 해당 매서드의 파라미터 값을 가져와 추적할 수 있다.
@Before("execution(* me.soomin.service.SampleService*.doAdd(String, String)) && args(str1, str2)")
public void logBeforeWithParam(String str1, String str2) {
log.info("Str1 : " + str1);
log.info("Str2 : " + str2);
}
@AfterThrowing 은 Target의 PointCut에 명시된 joinPoint 실행 중에 예외가 터질 경우 작동하는데, 이때 throwing 속성값으로 exception을 지정하여 터진 예외를 파라미터명으로 가져와 추적할 수 있다.
@AfterThrowing(pointcut = "execution(* me.soomin.service.SampleService*.*(..))", throwing = "exception")
public void logException(Exception exception) {
log.info("Exception : " + exception);
}
INFO : me.soomin.aop.LogAdvice - Exception : java.lang.NumberFormatException: For input string: "aaa"
aop에서 찍어낸 기록에서 도 어디서 어떤 예외가 터졌는지 알 수 있다. (Log4j 사용)
@Around 에노테이션은 ProceedingJoinPoint 와 함께다닌다. .proceed()로 Target의 메서드를 실행하여 Object로 리턴값을 받아 리턴한다.
AroundAdvice 라고 기억하는데, 이는 메서드 실행전후 예외발생을 뜻한다고 기억하고있다.
@Around("execution( * me.soomin.service.SampleService*.*(..) )")
public Object logTime(ProceedingJoinPoint point) {
long start = System.currentTimeMillis();
log.info("Target : " + point.getTarget());
log.info("Param : " + Arrays.toString(point.getArgs()));
Signature sig = point.getSignature();
log.info("Sig getName : " + sig.getName());
log.info("Sig getLongString : " + sig.toLongString());
log.info("Sig getShortString : " + sig.toShortString());
Object result = null;
try {
result = point.proceed();
} catch (Throwable e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
log.info("Time : " + (end - start));
return result;
}
Target : me.soomin.service.SampleServiceImpl@20ca951f
INFO : me.soomin.aop.LogAdvice - Param : [aaa, 123]
INFO : me.soomin.aop.LogAdvice - Sig getName : doAdd
INFO : me.soomin.aop.LogAdvice - Sig getLongString : public abstract java.lang.Integer me.soomin.service.SampleService.doAdd(java.lang.String,java.lang.String)
INFO : me.soomin.aop.LogAdvice - Sig getShortString : SampleService.doAdd(..)
콘솔내용 ( •_•)>⌐■-■
-
어느 객체가 Target의 메서드를 호출
-
Proxy가 가로채어 @Aspect 클래스 객체의 메서드를 실행(Advice)
-
Advice의 메서드에서 ProceedingJoinPoint 의 proceed 메서드를 호출
-
ProceedingJoinPoint가 Target의 메서드를 실행하고 리턴 값을 받음
-
Advice의 메서드가 리턴 값을 받고 Advice 로직 을 종료하고 리턴
-
Proxy가 리턴값을 받아 호출 객체에게 리턴
으로 종료되는 것으로 알고 있다.
이로 인해, 거슬러올라가는 과정을 거친다는 흐름으로 , Advice가 하나의 메서드에 공통적으로 PointCut을 가질때에 역순으로 결과 값이 찍히는 경우가 있다. 이를 제어하기 위해 @Order에노테이션을 사용한다고 기억하고 있다.
-
ProceedingJoinPoint 의 메서드
-
Signature getSignature() : 호출메서드의 정보를 가진 객체리턴
-
Object getTarget() : 대상 객체를 리턴
-
Object[] getArgs() : 호출 메서드의 파라미터목록을 리턴 ( 실제로 들어오는 파라미터)
-
org.aspectj.lang.Signature 의 메서드
-
String getName() : 호출 메서드의 이름을 리턴
-
String toLongString() : 호출되는 메서드를 완전히 표현한 문장을 리턴 / 리턴타입 파라미터 타입등이 모두 기재
-
String toShortString() : 호출되는 메서드의 축약한 문장을 리턴 / 메서드의 이름.
일단 기억은 여기까지이다.