모든 xml 설정은 @ 으로 바꿀 수 있다
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
를 하게 되면 aop를 @으로 변경
먼저 Pointcut 을 클래스로 만든다
package com.spring.biz.common;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class PointcutCommon {
@Pointcut("execution(* com.spring.biz..*Impl.*(..))")//추상 아님 비어있는 깡통
public void aPointcut() {}
@Pointcut("execution(* com.spring.biz..*Impl.select*(..))")
public void bPointcut() {}
}
▼
package com.spring.biz.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Service;
//bean 역할
@Service //Impl랑 aspect되서 Service 로 같은 곳에서 연결하기 위해 Component가 아닌 Service로 적는게 유리
@Aspect //얘네를 다 묶어줄래? 결합해줄래?
public class LogAdvice {
//어떤 pointcut이랑 결합하는지 알려준다.
@Before("PointcutCommon.aPointcut()") //aPointcut은 추상메서드가 아니다.
public void printLog(JoinPoint jp) {
String methodName = jp.getSignature().getName();
System.out.println(" BEFORE 어드바이스 : " + methodName);
Object[] args = jp.getArgs();
System.out.println( " 비즈니스 메서드에서 사용하는 인자 : " + args[0]);
//보통은 인자가 DTO 1개일 확률이 높아서 argsp[0]을 사용한다.
for(Object arg:args) {
System.out.println(arg);
}
System.out.println( " 비즈니스 메서드 수행 전에 로그를 출력");
}
}
어노테이션을 사용하여 작성하였다
하지만 AfterThrowingAdvice를 사용할땐 조금 다른 걸 확인 할 수 있다
package com.spring.biz.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
import com.spring.biz.member.MemberDTO;
@Service
@Aspect
public class AfterThrowingAdvice {
// @Pointcut("execution(* com.spring.biz..*Impl.*(..))")
// public void aPointcut() {
// //비어있는 깡통
// }
@AfterThrowing(pointcut="PointcutCommon.aPointcut()", throwing="exceptObj")
public void printException(JoinPoint jp, Object exceptObj) {
String methodName = jp.getSignature().getName();
System.out.println(" AfterThrowing 어드바이스 : " + methodName);
Object[] args = jp.getArgs();
System.out.println( " 비즈니스 메서드에서 사용하는 인자 : " + args[0]);
for(Object arg:args) {
System.out.println(arg);
}
System.out.println(" 비즈니스 메서드의 OUTPUT :" + exceptObj );
if(exceptObj instanceof NumberFormatException) {
System.out.println("값이 숫자가 아닙니다.");
}
else if(exceptObj instanceof ArithmeticException) {
System.out.println("수학적인 오류입니다.");
System.out.println("일부러 발생시킨 에러입니다.");
}
else {
System.out.println("미확인 에러입니다.");
}
System.out.println( " 비즈니스 메서드 수행 전에 로그를 출력");
System.out.println( " 로그 03 예외 발생");
}
}
속성 부분이 다른 걸 확인할 수있는데
@Before는 하나의 속성만 받기때문에 생략되어 pointcut이 사용이 안되는 것을 볼수있고
@AfterThrowing 은 100%로 값이 넘어올 수 있기에 속성 필드에 추가하여 사용할 수 있게 되어있습니다
그래서 throwing 을 사용해서 어떤 애러가 나왔는지도 받아볼수있다
package com.spring.biz.common;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Service;
import com.spring.biz.member.MemberDTO;
@Service
@Aspect
public class AfterReturningAdvice {
// @Pointcut("execution(* com.spring.biz..*Impl.select*(..))")
// public void bPointcut() {
// //반환이 있어야 하니까 select 랑만 연결
// }
@AfterReturning(pointcut="PointcutCommon.bPointcut()", returning="returnObj")
//핵심관심=> bPointcut이 수행하고 반환한 애를 담을거야 Object returnObj
public void afterReturningPringLog(JoinPoint jp, Object returnObj) {
String methodName = jp.getSignature().getName();
System.out.println(" AfterReturning 어드바이스 : " + methodName);
Object[] args = jp.getArgs();
System.out.println( " 비즈니스 메서드에서 사용하는 인자 : " + args[0]);
for(Object arg:args) {
System.out.println(arg);
}
System.out.println(" 비즈니스 메서드의 OUTPUT :" + returnObj );
if(returnObj instanceof MemberDTO) { //데이터 확인함
MemberDTO mDTO = (MemberDTO)returnObj;
if(mDTO != null) {
if(mDTO.getRole().equals("ADMIN")) {
System.out.println("[관리자 로그인]");
System.out.println(mDTO.getName()+"님 입장");
}
else {
System.out.println("[사용자 로그인]");
}
}
}
System.out.println( " 비즈니스 메서드 수행 전에 로그를 출력");
}
//바인드 변수
}
package com.spring.biz.common;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Service;
import org.springframework.util.StopWatch;
@Service
@Aspect
public class AroundAdvice {
@Around("PointcutCommon.aPointcut()")
public Object aroundPrintLog(ProceedingJoinPoint pjp) throws Throwable { //지금 실행하고 있는 포인트컷. 지금 연결된애
String methodName = pjp.getSignature().getName(); // 메서드 이름은 시그니처로 가져올수있다.
System.out.println("[BEFORE]");
StopWatch sw = new StopWatch(); //시간 가져오는거
sw.start();
//왜 오브젝트냐면 뭐가 나올지 몰라서!!!
Object obj = pjp.proceed(); //pjp가 실행이 되면 아웃풋으로 뭔가 뱉어냄
//throws => 예외가 발생할 수 있어서
//11번 라인을 통해서 비즈니스 메서드가 수행된다.
sw.stop();
System.out.println("[AFTER]");
System.out.println("비즈니스 메서드 : " + methodName);
System.out.println(" 수행하는데에 걸린 시간 : " + sw.getTotalTimeMillis()+ "(ms)초");
return obj; //내가 수행하고 있는 메서드가 반환이 있을수도 있잖아?
}
}
'Spring' 카테고리의 다른 글
DAO var.2 사용 (1) | 2024.03.15 |
---|---|
DAO var.1 -> DAO var.2 설정 (0) | 2024.03.14 |
Advice 동작시점 (0) | 2024.03.11 |
AOP 정리 (0) | 2024.03.10 |
Spring 어노테이션을 이용한 연습 (0) | 2024.03.09 |