728x90
횡단 관심의 어드바이스 메서드를 의미 있게 구현하기 위해서는 현재 수행 중인
비즈니스 메서드의 정보를 파악하는것이 좋다.
예를 들어 로그를 남길때 CRUD(select, insert, update, delete)를 사용하고 그에 맞는 각각의 로그가
나온다면 더 정확한 로직을 구현할 수 있게 된다.
joinpoint는 현재 수행 중인 포인트컷을 의미하며 joinpoint를 인자로 가지게되면(ex. pjp)
현재 수행중인 비즈니스 메서드의 시그니쳐 등을 알 수 있다.
public void printLog(JoinPoint jp) {
String methodName = jp.getSignature().getName();
// 현재 수행중인 포인트컷(핵심로직,CRUD)의 메서드명
Object[] args = jp.getArgs();
// 현재 수행중인 포인트컷(핵심로직,CRUD)이 사용하는 인자들의 정보
System.out.println("수행중인 핵심메서드명: "+methodName);
System.out.println("사용하는 인자");
for(Object v:args) {
System.out.println(v);
}
}
바인드 변수는 비즈니스 메서드가 리턴한 결과값을 바인딩할 목적으로 사용하는 것을 바인드 변수라 한다.
(어떤 값이 리턴될지 몰라 Object 타입으로 선언)
설정을 통해 비즈니스 메서드의 반환 값을 변수에 자동으로 매핑할 수 있다.
pjp는 joinpoint를 상속받은 클래스로 조인 포인트의 메서드 모두 사용 가능
joinpoint가 제공하는 메서드
-Signature getSignature()
클라이언트가 호출한 메소드의 시그니처(리턴 타입, 이름, 매개변수) 정보가 저장된 Signature 객체를 리턴
- Object getTarget()
클라이언트가 호출한 비즈니스 메서드를 포함하는 비즈니스 객체를 리턴 (해당 클래스 객체를 리턴)
-Object [] getArgs()
클라이언트가 메서드를 호출할 때 넘겨준 인자 목록을 Object 배열로 리턴
설정 예시
<bean id="ara" class="com.kim.biz.common.AfterReturningAdvice" />
<bean id="ata" class="com.kim.biz.common.AfterThrowingAdvice" />
<bean id="aa" class="com.kim.biz.common.AroundAdvice" />
<aop:config>
<aop:pointcut expression="execution(* com.kim.biz..*Impl.*(..))" id="aPointcut"/>
<aop:pointcut expression="execution(* com.kim.biz..*Impl.select*(..))" id="bPointcut"/>
<aop:aspect ref="ara">
<aop:after-returning method="printLogAfterReturning" pointcut-ref="bPointcut" returning="returnObj"/>
// returning == 해당 메서드에서 반환되어 나온 값을 returnObj라는 이름의 객체에 맵핑
</aop:aspect>
<aop:aspect ref="ata">
<aop:after-throwing method="printLogAfterThrowning" pointcut-ref="bPointcut" throwing="exceptObj"/>
// throwing == 해당 메서드에서 발생된 에러를 exceptObj라는 이름의 객체에 맵핑
</aop:aspect>
<aop:aspect ref="aa">
<aop:around method="printLogAround" pointcut-ref="aPointcut" />
</aop:aspect>
</aop:config>
예시로 작성된 Advice 클래스 파일
after-returning
package com.kim.biz.common;
import org.aspectj.lang.JoinPoint;
import com.kim.biz.member.MemberVO;
public class AfterReturningAdvice {
public void printLogAfterReturning(JoinPoint jp,Object returnObj) {
String methodName = jp.getSignature().getName();
// 현재 수행중인 포인트컷(핵심로직,CRUD)의 메서드명
Object[] args = jp.getArgs();
// 현재 수행중인 포인트컷(핵심로직,CRUD)이 사용하는 인자들의 정보
System.out.println("수행중인 핵심메서드명: "+methodName);
System.out.println("사용하는 인자");
System.out.println("=========");
for(Object v:args) {
System.out.println(v);
}
System.out.println("=========");
if(returnObj instanceof MemberVO) {
MemberVO mvo = (MemberVO)returnObj;
if(mvo.getRole().equals("ADMIN")) {
System.out.println("관리자입니다.");
}
else {
System.out.println("일반 계정 입니다.");
}
}
System.out.println("핵심메서드의 반환값: "+returnObj);
}
}
after-throwing
package com.kim.biz.common;
import org.aspectj.lang.JoinPoint;
public class AfterThrowingAdvice {
public void printLogAfterThrowning(JoinPoint jp,Exception exceptObj) {
String methodName = jp.getSignature().getName();
// 현재 수행중인 포인트컷(핵심로직,CRUD)의 메서드명
Object[] args = jp.getArgs();
// 현재 수행중인 포인트컷(핵심로직,CRUD)이 사용하는 인자들의 정보
System.out.println("수행중인 핵심메서드명: "+methodName);
System.out.println("사용하는 인자");
System.out.println("=========");
for(Object v:args) {
System.out.println(v);
}
System.out.println("=========");
System.out.println("발생한 예외: "+exceptObj.getMessage());
if(exceptObj instanceof IllegalArgumentException) {
System.out.println("올바르지 않은 인자값.....");
}
else if(exceptObj instanceof NumberFormatException) {
System.out.println("숫자 형식이 아닌 값....");
}
else if(exceptObj instanceof Exception) {
System.out.println("예외가 발생...");
}
else {
System.out.println("확인되지 않은 에러 발생!!!");
}
}
}
around
package com.kim.biz.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.springframework.util.StopWatch;
// around로 사용할 advice는 반드시 pjp를 input으로 가져야한다!!
// ex) 필터 서블릿 클래스
public class AroundAdvice {
public Object printLogAround(ProceedingJoinPoint pjp) throws Throwable {
String methodName = pjp.getSignature().getName();
// 현재 수행중인 포인트컷(핵심로직,CRUD)의 메서드명
System.out.println("수행중인 핵심메서드명: "+methodName);
StopWatch sw = new StopWatch();
// 스탑워치 클래스를 통해 해당 메서드가 수행되는 시간측정 가능
sw.start();
Object returnObj = pjp.proceed(); // 수행해야할 포인트컷
// pjp.proceed()에 의해 비즈니스 메서드가 수행됨!
sw.stop();
System.out.println("수행시간: "+sw.getTotalTimeMillis()+"ms");
return returnObj;
}
}
728x90
'Spring' 카테고리의 다른 글
스프링 JDBC 설정 (0) | 2022.09.19 |
---|---|
[AOP] .xml 설정을 @(어노테이션)으로 변경하는법 (0) | 2022.09.18 |
AOP(관점 지향 프로그래밍) (0) | 2022.09.16 |
어노테이션(@)을 이용한 의존성 주입 (0) | 2022.09.15 |
IoC(제어의 역행)과 DI(의존성 주입) (0) | 2022.09.14 |