package com.example.demo.order.aop;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Slf4j
@Aspect
public class AspectV6Advice {
@Around("com.example.demo.order.aop.Pointcuts.orderAndService()")
//com.demo.order 패키지와 하위 패키지 이면서 클래스 이름이 *Service
public Object doTransaction(ProceedingJoinPoint joinPoint) throws Throwable{
try{
//@Before
log.info("[트랜잭션 시작] {}",joinPoint.getSignature());
Object result = joinPoint.proceed();
//@AfterReturning
//@After
log.info("[트랜잭션 커밋] {}",joinPoint.getSignature());
return result;
}catch (Exception e){
//@AfterThrowing
log.info("[트랜잭션 롤백] {}",joinPoint.getSignature());
throw e;
}finally {
log.info("[리소스 릴리즈] {}",joinPoint.getSignature());
}
}
//기존에서 쓰던 ProceedingJoinPoint는 @Around에서만 사용하는 파라미터다. 여기서는 JoinPoint를 사용한다.
//파라미터를 비워놔도 해당 포인트컷 내에서 코드가 실행된다. 무조건적으로 해당 위치에서 프로세스가 실행되기 전에 실행된다는 이야기.
@Before("com.example.demo.order.aop.Pointcuts.orderAndService()")
public void doBefore(JoinPoint joinPoint){
log.info("[before] {} ",joinPoint.getSignature());
}
//@AfterReturning은 return한 값을 조작할 수 는 있으나, return 자체를 변경할 수는 없다.
@AfterReturning(value = "com.example.demo.order.aop.Pointcuts.orderAndService()", returning = "result")
public void doReturn(JoinPoint joinPoint,Object result){
log.info("[return] {} return={} ",joinPoint.getSignature(),result);
}
//해당 포인트컷의 리턴타입이 무엇이냐에 따라서 여러 타입으로도 받을 수 있다.
@AfterReturning(value = "com.example.demo.order.aop.Pointcuts.allOrder()", returning = "result")
public void doReturn2(JoinPoint joinPoint,String result){
log.info("[return2] {} return={} ",joinPoint.getSignature(),result);
}
@AfterThrowing(value = "com.example.demo.order.aop.Pointcuts.orderAndService()",throwing = "ex")
public void doThrowing(JoinPoint joinPoint,Exception ex){
log.info("[ex] {} message={} ",ex);
}
//@After는 finally 로직과 비슷하다고 보면 된다. 즉, 할수있는 것이 많이 없다.
@After(value = "com.example.demo.order.aop.Pointcuts.orderAndService()")
public void doAfter(JoinPoint joinPoint){
log.info("[after] {} ",joinPoint.getSignature());
}
}
- @Before
- 조인포인트를 실행하기 전
- @Around와 다르게 작업 흐름을 변경할 수 없다.
- ProceedingJoinPoint.proceed()를 사용하지 않는다.
- 메서드 종료 시 자동으로 다음 타겟이 호출된다.
@AfterReturning(value = "hello.aop.order.aop.Pointcuts.orderAndService()",
returning = "result")
public void doReturn(JoinPoint joinPoint, Object result) {
log.info("[return] {} return={}", joinPoint.getSignature(), result);
}
- @AfterReturning
- 메서드 실행이 정상적으로 반환될 때 실행
- returning 속성에 사용된 이름은 어드바이스 메서드의 매개변수 일므과 일치해야 한다.
- returning 절에 지정된 타입의 값을 반환하는 메서드만 대상으로 실행한다.
- @Around와 다르게 반환되는 객체를 변경할 수 는 없다. 반환 객체를 변경하려면 @Around를 사용해야 한다.하지만 조작할 수는 있다.
@AfterThrowing(value = "hello.aop.order.aop.Pointcuts.orderAndService()",
throwing = "ex")
public void doThrowing(JoinPoint joinPoint, Exception ex) {
log.info("[ex] {} message={}", joinPoint.getSignature(), ex.getMessage());
}
- AfterThrowing
- 메서드 실행이 예외를 던져서 종료될 때 실행
- throwing 속성에 사용된 이름은 어드바이스 메서드의 매개변수 이름과 일치해야 한다.
- throwing 절에 지정된 타입과 맞는 예외를 대상으로 실행한다.
- @After
- 메서드 실행이 종료되면 실행된다.
- 정상 및 예외 반환 조건을 모두 처리한다.
- 일반적으로 리소스를 해제하는 데 사용한다.
- @Around
- 메서드의 실행주변에서 실행된다. 메서드 실행 전후에 작업을 수행한다.
- 가장 강력한 어드바이스
- 조인 포인트 실행여부 선택
- 전달 값 변환 : joinPoint.proceed(args[])
- 반환 값 변환
- 예외 변환
- 트랜직션 처럼 try~catch~finally 모두 들어가는 구문 처리 가능
- 어드바이스의 첫 번째 파라미터는 ProceedingJoinPoint를 사용해야 한다
- proceed()를 통해 대상을 실행한다.
- proceed()를 여러번 실행 할 수도 있음(재시도)
'Java > 스프링 AOP' 카테고리의 다른 글
스프링 AOP - execution(2) (0) | 2023.09.14 |
---|---|
스프링 AOP - execution(1) (0) | 2023.09.12 |
Spring AOP - 포인트컷 분리 (0) | 2023.09.07 |
Spring AOP 용어정리 (0) | 2023.09.06 |
Spring AOP - 핵심기능, 부가기능 , 애스펙트 (0) | 2023.09.05 |