[TIL] AOP

정석·2024년 9월 10일

TIL

목록 보기
36/40
post-thumbnail

AOP (Aspect Oriented Programing)
관점지향 프로그래밍

  • 중복문제, 변경문제 등의 이유로 관심사 분리를 통해 유지보수성을 향상시킬 수 있는 프로그래밍이다.

AOP 키워드

  1. 어드바이스
  • 실제로 실행되는 부가기능 코드 (예를 들면 시간측정 로직 OR 트랜잭션 처리)
  1. 포인트컷
  • 어드바이스를 적용할 구체적인 범위를 선택하는 규칙
  1. 타겟
  • AOP 내에서 어드바이스가 적용되는 객체.
  1. 조인포인트
  • 어드바이스가 적용될 수 있는 실행 지점
  1. 에스팩트
  • 어드바이스와 포인트컷을 하나로 묶은 모듈

AOP 적용 실습

  1. aspect 생성
@Slf4j
@Aspect
/**
 * 애스팩트: 어드바이스와 포인트컷을 하나로 묶은 모듈
 */
public class AspectPractice {
    // 포인트컷
    // 어드바이스 위치
}

그리고 config 등록

@Configuration
public class WebConfig {

    @Bean
    public AspectPractice getAspectPracticeAop() {
        return new AspectPractice();
    }
}

@Component 로 등록하지 않는 이유는, AOP 특성상 특별한 수행이 이루어지므로 Config 에서 관리하는게 관례


  1. 포인트 컷 생성
@Pointcut("execution(* com.standard.sparta.service..*(..))")
    private void serviceLayer() {}

  1. 어드바이스 생성
  • Before
/**
     * 어드바이스: @Before
     * 메서드 실행 전에 수행되는 로직을 처리할때 사용합니다.
     */
    @Before("serviceLayer()")
    public void beforeMethod(){
        log.info("::: BEFORE 실행 :::");
    }
  • AfterReturning
/**
     * 어드바이스: @AfterReturning
     * 메서드가 정상적으로 반환된 후에 실행됩니다.
     * 예외가 발생하지 않고 정상적으로 결과값을 반환했을때만 동작합니다.
     * @param result 성공시 반환값
     */
   @AfterReturning(pointcut = "serviceLayer()", returning = "result")
    public void afterReturningMethod(Object result) {
       // result 에 대한 작업을 수행할 수 있겠죠?
       log.info("::: AFTER RETURNING :::");
    }
  • AfterThrowing
/**
     * 어드바이스: @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
     * 메서드가 정상적으로 실행되던 예외가 발생하던 메서드가 완료된 후에 항상 실행됩니다.
     */
    @After("serviceLayer()")
    public void afterMethod(JoinPoint joinPoint) {
        log.info("::: AFTER :::");
    }
  • Around
    /**
     * 어드바이스: 가장 강력한 어드바이저, 전체 흐름을 제어할 수 있습니다.
     * @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 :::");
        }
    }

  1. 어드바이스 적용
    /**
     * 어드바이스: 패키지 범위 기반
     */
    @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);
        }
    }

0개의 댓글