스프링(퀵 스타트) 2일차(AOP)

Lucy in the Sky with Diamond·2023년 8월 4일

스프링 정리

목록 보기
5/5

스프링의 3대 기술은 무엇인가?
Ioc/DI, PSA AOP가 존재한다.

AOP란 관점지향 프로그래밍으로서 각각의 관점에 대해 정리를 하겠다가 골자이다.

말로 설명하면 이해가 안되니 바로 예제를 보자

public class Calculator {
    private int value;

    public Calculator(int value) {
        this.value = value;
    }

    public void add(int value) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        this.value += value;

        stopWatch.stop();
        System.out.println(stopWatch);
    }

    public void sub(int value) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        this.value -= value;

        stopWatch.stop();
        System.out.println(stopWatch);
    }

    public void mul(int value) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        this.value *= value;

        stopWatch.stop();
        System.out.println(stopWatch);
    }

    public int get() {
        return value;
    }
}

자 여기서 중복이 되는 코드가 StopWatch 뭐시기인거는 자명하다.

StopWatch stopWatch = new StopWatch();
stopWatch.start();
//this.value += value;
stopWatch.stop();
System.out.println(stopWatch);

말 그대로 연산이 얼마나 걸릴지를 시간측정하는 프로그램으로써 위의 문장들이 중복이 되는것들을 우리는 파악 할 수 있다.

이렇게 반복이 되는 기능이나 관심사들을 Cross Cutting Concern 이라고 일컫는다.

그리고 이러한 Cross cutting Concern을 분리해내는것이 AOP의 핵심이라고 생각하면 될것 같다.


AOP의 용어정리

  1. 타겟 : 프록시로 감쌀 클래스, 여기서는 Calculator가 타겟이다.
  2. Aspect : 관심사의 모듈화, 즉 위의 Stopwatch 코드를 모듈화 시키는것을 의미
    그냥 쉽게 생각하면 Advice + PointCut이라 생각하면 된다.
  3. Advice : Cross Concerning에 해당하는 코드들을 의미하며 관점(Aspect)에서 수행할 작업을 언제 적용 할 지 정의한 것
  4. Pointcut : 특정 메서드나 클래스와 같이 관심사를 적용할 대상을 지정
    그러니까 add mul sub 위의 3가지 메소드중에서 add,mul에만 AOP를 적용한다면 이 두가지가 Pointcut이 된다.

// Aspect를 적용할 대상을 지정하는 포인트컷 예시
// com.example 패키지 내의 모든 public 메서드
pointcut publicMethods() : execution(public com.example..(..));
// Service 클래스의 모든 메서드
pointcut serviceMethods() : execution(
com.example.Service.(..));
// com.example 패키지 내의 모든 클래스의 모든 메서드
pointcut allMethods() : execution(
com.example..(..));
// com.example 패키지 내의 모든 메서드 중 이름이 'get'으로 시작하는 메서드
pointcut getMethods() : execution( com.example..get*(..));

  1. JoinPoint : 실제 적용할 메소드나 서비스들. 여기서는 add mul sub이나 userserviceImpl,BoardServiceImpl 등등을 의미한다.
@Aspect
@Component
public class PerformanceCheck {
    @Around("execution(* com.example.blogjava..*(..))")
    public Object printlnPerf(ProceedingJoinPoint joinPoint) throws Throwable {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        Object proceed = joinPoint.proceed();
        stopWatch.stop();
        System.out.println(stopWatch);
        return proceed;
    }
}

@Around가 여기서는 advice를 나타내며
"execution 뭐시기"가 pointcut를 나타낸다.
그리고 jointpoint는 Object proceed = joinPoint.proceed(); 이부분을 나타낸다. 즉 여기에 mul,add,sub 이게 들어가는것이다.

  1. Weaving
    위빙은 포인트컷에 해당하는 특정 메소드가 어드바이스를 만난다면 그것을 삽입하는 과정을 의미합니다.
    6-1 .컴파일 타임(Compile Time Weaving): 컴파일할 때 AspectJ 컴파일러를 사용하여 Aspect를 AspectJ 바이트 코드로 변환하는 방법입니다.

    6-2. 로드 타임(Load Time Weaving): 클래스를 로딩하는 시점에 AspectJ 바이트 코드를 로드하여 Aspect를 적용하는 방법입니다.

    6-3. 런타임(Run Time Weaving): 애플리케이션이 실행되는 시점에 Aspect를 적용하는 방법입니다.

// Aspect 정의

public aspect LoggingAspect {
    // Pointcut 정의: com.example 패키지 내의 모든 public 메서드를 대상으로 함
    pointcut publicMethods() : execution(public * com.example.*.*(..));
    // Before Advice: publicMethods()에 해당하는 메서드가 실행되기 전에 로그를 출력함
    before() : publicMethods() {
        System.out.println("Before advice: Method is about to be executed.");
    }
    // After Advice: publicMethods()에 해당하는 메서드가 정상적으로 반환된 후에 로그를 출력함
    after() : publicMethods() {
        System.out.println("After advice: Method has been executed successfully.");
    }
    // After Throwing Advice: publicMethods()에 해당하는 메서드가 예외를 던진 후에 로그를 출력함
    after() throwing(Exception ex) : publicMethods() {
        System.out.println("After throwing advice: Method has thrown an exception - " + ex.getMessage());
    }
    // Around Advice: publicMethods()에 해당하는 메서드 실행 전후에 로그를 출력함
    Object around() : publicMethods() {
        System.out.println("Around advice: Before method execution.");
        Object result = proceed(); // 메서드 실행
        System.out.println("Around advice: After method execution.");
        return result;
    }
}

0개의 댓글