AOP (Aspect Oriented Programing)
관점지향 프로그래밍
@Slf4j
@Aspect
/**
* 애스팩트: 어드바이스와 포인트컷을 하나로 묶은 모듈
*/
public class AspectPractice {
// 포인트컷
// 어드바이스 위치
}
그리고 config 등록
@Configuration
public class WebConfig {
@Bean
public AspectPractice getAspectPracticeAop() {
return new AspectPractice();
}
}
@Component로 등록하지 않는 이유는,AOP특성상 특별한 수행이 이루어지므로Config에서 관리하는게 관례
@Pointcut("execution(* com.standard.sparta.service..*(..))")
private void serviceLayer() {}
/**
* 어드바이스: @Before
* 메서드 실행 전에 수행되는 로직을 처리할때 사용합니다.
*/
@Before("serviceLayer()")
public void beforeMethod(){
log.info("::: BEFORE 실행 :::");
}
/**
* 어드바이스: @AfterReturning
* 메서드가 정상적으로 반환된 후에 실행됩니다.
* 예외가 발생하지 않고 정상적으로 결과값을 반환했을때만 동작합니다.
* @param result 성공시 반환값
*/
@AfterReturning(pointcut = "serviceLayer()", returning = "result")
public void afterReturningMethod(Object result) {
// result 에 대한 작업을 수행할 수 있겠죠?
log.info("::: AFTER RETURNING :::");
}
/**
* 어드바이스: @AfterThrowing
* 메서드 실행 중 예외가 발생했을 때만 실행됩니다.
* @param joinPoint 조인포인트
* @param ex 발생한예외 객체
*/
@AfterThrowing(pointcut = "serviceLayer()", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex) {
// 서비스에서 발생한 예외 ex.getMessage() <- 예외 조작 가능
log.info("::: AFTER THROWING :::");
}
/**
* 어드바이스: @After
* 메서드가 정상적으로 실행되던 예외가 발생하던 메서드가 완료된 후에 항상 실행됩니다.
*/
@After("serviceLayer()")
public void afterMethod(JoinPoint joinPoint) {
log.info("::: AFTER :::");
}
/**
* 어드바이스: 가장 강력한 어드바이저, 전체 흐름을 제어할 수 있습니다.
* @param joinPoint
* @return
* @throws Throwable
*/
@Around("serviceLayer()") // 어노테이션 기반으로 포인트컷 설정
public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
log.info("::: BEFORE :::");
try {
Object result = joinPoint.proceed();
System.out.println(result);
log.info("::: AFTER RETURNING :::");
return result;
} catch (Exception e) {
log.info("::: AFTER THROWING :::");
throw e;
} finally {
log.info("::: AFTER :::");
}
}
/**
* 어드바이스: 패키지 범위 기반
*/
@Around("serviceLayer()")
public Object advicePackage(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
try {
return joinPoint.proceed();
} finally {
long endTime = System.currentTimeMillis();
long executionTime = endTime - startTime;
log.info("::: ExecutionTime: {}ms", executionTime);
}
}