본문 바로가기
  • 기억의 유한함을 기록의 무한함으로✍️            예비 개발자가 꿈꾸는 공간 여기는 안나의 개발 블로그 💻
Programming/Spring

[Spring 입문하기] Section 07. AOP

by 제가안난데여♪(´ε`*) 2024. 1. 25.
728x90


✏️ 핵심 관심사항(core concer)과 공통 관심사항(cross-cutting concer)

  • 핵심관심사항 예) 은행서비스, 계좌서비스 , 소비자 소비스 등등
  • 공통관심사항(부가기능) 예)보안, 트랜잭션, 로그인 인증

✏️ AOP (Aspect Oriented Programming - 관점 지향 프로그래밍)

핵심 로직과 부가 기능을 분리하여 애플리케이션 전체에 걸쳐 사용되는 부가 기능을 모듈화하여 재사용할 수 있도록 지원하는 것

  • 기존 oop는 함수로 뺄 수 없는 공통적으로 처리하는 부가 기능 로직이 중복되는 한계가 있어 이를 해결하기 위해 AOP가 등장하게 되었다.
  • 이런 로직을 어스펙트(Aspect)라는 모듈 형태로 만들어서 설계하고 개발하는 방법이다.
  • 즉 핵심적인 기능에서 부가적인 기능을 분리하는 것이 AOP이다.
  • ex ) 간단한 메소드 성능검사( 시간측정 ), 트랜잭션 처리, 예외 반환, 아키텍처 검증 등
  • 주 메소드에서 부가기능을 시행하는 시점 5가지
    • around → 메소드 실행전, 실행후 두번 부가기능을 시행함
    • before → 메소드 실행전
    • after returning → 메소드가 정상적으로 실행 한 후
    • after throwing → 메소드가 예외를 발생시킨 후
    • after → 메소드 실행 후

✏️ Spring AOP

Spring AOP 용어

  • Target : 핵심기능을 담고 있는 모듈로 부가 기능을 부여할 대상이 된다.
  • Advice : 어느 시점에 어떤 공통관심기능(Aspect)을 적용할지 정의한 것 즉, 부가기능을 담고 있는 모듈
  • JoinPoint : Aspect가 적용될 수 있는 지점, 즉 부가기능을 적용할 수 있는 모듈(메소드 등등)
  • Pointcut : 공통 관심 사항이 적용될 JoinPoint, 부가기능(Advice)를 적용할 target의 메소드를 선별하는 정규 표현식이다
  • Aspect : 여러 객체에서 공통으로 적용되는 공통 관심 사항
    • AOP의 기본모듈이고 싱글톤 형태의 객체로 존재한다.
    • Aspect = Adivce + Pointcut
  • Advisor(spring aop에만 있음)
    • Advisor = Adivce + Pointcut
  • Weaving
    • 어떤 부가 기능(Advice)을 어떤 핵심사항(Pointcut)에 적용시킬에 대한 설정(Advisor)
    • 즉 포인트컷에 의해서 결정된 타겟의 joinpoin에 부가기능(adivce)을 삽입하는 과정

Spring AOP 특징

프록시 기반의 AOP를 지원

  • Spring은 타겟 객체에 대한 프록시를 만들어서 제공한다.
  • 타겟을 감싸는 프록시는 실행시간(Runtime)에 생성된다.
  • 프록시는 Advice를 타겟 객체에 적용하면서 생성되는 객체이다.
  • 프록시 객체를 쓰는 이유는 접근 제어 및 부가기능을 추가하기 위함이다

프록시가 호출을 가로챈다 (Intercept)

  • 전처리 Advice : 프록시는 타겟 객체에 대한 호출을 가로챈 다음 Advice의 부가 기능 로직을 수행한고 난 후 타겟의 핵심 기능 로직을 호출한다.(Object result = joinPoint.proceed();)
  • 후처리 Advice : 타겟의 핵심 기능 로직 메소드를 호출한 후에 부가 기능을 수행하는 경우도 있다.

Sprint AOP는 메소드 JoinPoint만 지원한다.

  • Spring은 동적 프록시 기반으로 AOP를 구현하므로 메소드 조인포인트만 지원한다. (즉 스프링 AOP의 조인포인트는 항상 메소드 실행시점이 된다)

시간측정 AOP 등록

package hello.hellospring.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class TimeTraceAop {
    @Around("execution(* hello.hellospring..*(..))")
    public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println("START: " + joinPoint.toString());
        try {
            return joinPoint.proceed();
        } finally {
            long finish = System.currentTimeMillis();
            long timeMs = finish - start;
            System.out.println("END: " + joinPoint.toString()+ " " + timeMs +
                    "ms");
        }
    }
}
반응형