AOP(Aspect Oriented Programming)

박대운·2022년 12월 12일

Spring

목록 보기
3/4

AOP(Aspect-Oriented Programming)는 기존과 다른 프로그램 구조 사고 방식을 제공함으로써 객체 지향 프로그래밍(OOP)의 부족한 부분을 보완한다.

객체를 잘 활용하기 위해선 관심사 분리 (Separation of Concerns, SoC)의 디자인 원칙을 준수해야 한다.

관심사의 분리는 모듈화의 핵심이다.

AOP의 핵심 기능과 부가 기능

애플리케이션 로직은 크게 핵심 기능과 부가 기능으로 나눌 수 있다.

핵심 기능(Core Concerns)

  • 객체가 제공하는 고유의 기능(업무 로직 등을 포함).

부가 기능(CROSS-CUTTING CONCERNS)

  • 핵심 기능을 보조하기 위해 제공되는 기능.

  • 로그 추적 로직, 보안, 트랜잭션 기능 등이 있다.

  • 단독으로 사용되지 않고 핵심 기능과 함께 사용된다.

AOP의 용어 및 개념들

애스팩트(Aspect)

  • 여러 객체에 공통으로 적용되는 기능을 말한다. (공통 기능)
  • 어드바이스 + 포인트컷을 모듈화하여 애플리케이션에 포함되는 횡단 기능이다.
  • 여러 어드바이스와 포인트컷이 함께 존재한다.

조인 포인트(join point)

  • 클래스 초기화, 객체 인스턴스화, 메소드 호출, 필드 접근, 예외 발생과 같은 애플리케이션 실행 흐름에서의 특정 포인트를 의미한다.
  • 횡단 관심은 조인포인트 전/후에 AOP에 의해 자동으로 추가된다.
  • 스프링 AOP는 프록시 방식을 사용하므로 조인 포인트는 항상 메소드 실행 지점으로 제한된다.

어드바이스(Advice)

  • 조인포인트에서 수행되는 코드를 의미한다.
  • Aspect를 언제 핵심 코드에 적용할 지를 정의한다.
  • 부가 기능에 해당된다.

포인트컷(Pointcut)

  • 조인 포인트 중에서 어드바이스가 적용될 위치를 선별하는 기능이다.
  • 프록시를 사용하는 스프링 AOP는 메서드 실행 지점만 포인트컷으로 선별 가능하다.

위빙(Weaving)

  • 포인트컷으로 결정한 타겟의 조인 포인트에 어드바이스를 적용하는 것이다.
    - Advice를 핵심 코드에 적용하는 것을 의미한다.
  • 핵심 기능 코드에 영향을 주지 않고 부가 기능을 추가 할 수 있다.
  • AOP 적용을 위해 애스펙트 객체에 연결한 상태이다.
    - 컴파일 타임(AspectJ compoiler)
    - 로드 타임
    - 런타임, 스프링 AOP는 런타임, 프록시 방식.

AOP 프록시(proxy)

  • AOP 기능을 구현하기 위해 만든 프록시 객체이다.
  • 스프링에서 AOP 프록시는 JDK 동적 프록시 또는 CGLIB 프록시이다.

타겟 (Target)

  • 핵심 기능을 담고 있는 모듈로 타겟은 부가기능을 부여할 대상이 된다.
  • Adivce를 받는 객체이고 포인트컷으로 결정된다.

어드바이저(Advisor)

  • 하나의 어드바이스와 하나의 포인트 컷으로 구성됩니다.
  • 스프링 AOP에서만 사용되는 특별한 용어입니다.

포인트컷 지시자 종류

1. execution : 메서드 실행 조인트 포인트를 매칭한다. 스프링 AOP에서 가장 많이 사용하며, 기능도 복잡하다.
2. within : 특정 타입 내의 조인 포인트를 매칭한다.
3. args : 인자가 주어진 타입의 인스턴스인 조인 포인트
4. this : 스프링 빈 객체(스프링 AOP 프록시)를 대상으로 하는 조인 포인트
5. target : Target 객체(스프링 AOP 프록시가 가르키는 실제 대상)를 대상으로 하는 조인 포인트

  • @target : 실행 객체의 클래스에 주어진 타입의 애너테이션이 있는 조인 포인트
  • @within : 주어진 애너테이션이 있는 타입 내 조인 포인트
  • @annotation : 메서드가 주어니 애너테이션을 가지고 있는 조인 포인트를 매칭
  • @args : 전달된 실제 인수의 런타임 타입이 주어진 타입의 애너테이션을 갖는 조인 포인트
  • bean : 스프링 전용 포인트컷 지시자이고 빈의 이름으로 포인트컷을 지정한다.

execution을 가장 많이 사용하고 나머지는 자주 사용하지 않는다.

일반적인 pointcut 표현식들

  • 모든 공개 메서드 실행
    execution(public * *(..))

  • set 다음 이름으로 시작하는 모든 메서드 실행
    execution( set(..))

  • AccountService 인터페이스에 의해 정의된 모든 메소드의 실행
    execution( com.xyz.service.AccountService.(..))

  • service 패키지에 정의된 메서드 실행
    execution( com.xyz.service..*(..))

  • 서비스 패키지 또는 해당 하위 패키지 중 하나에 정의된 메서드 실행
    execution( com.xyz.service...*(..))

  • 서비스 패키지 내의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    within(com.xyz.service.*)

  • 서비스 패키지 또는 하위 패키지 중 하나 내의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    within(com.xyz.service..*)

  • AccountService 프록시가 인터페이스를 구현하는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    this(com.xyz.service.AccountService)

  • AccountService 대상 객체가 인터페이스를 구현하는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    target(com.xyz.service.AccountService)

  • 단일 매개변수를 사용하고 런타임에 전달된 인수가 Serializable과 같은 모든 조인 포인트 (Spring AOP에서만 메소드 실행)
    args(java.io.Serializable)

  • 대상 객체에 @Transactional 애너테이션이 있는 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    @target(org.springframework.transaction.annotation.Transactional)

  • 실행 메서드에 @Transactional 애너테이션이 있는 조인 포인트 (Spring AOP에서만 메서드 실행)
    @annotation(org.springframework.transaction.annotation.Transactional)

  • 단일 매개 변수를 사용하고 전달된 인수의 런타임 유형이 @Classified 애너테이션을 갖는 조인 포인트(Spring AOP에서만 메서드 실행)
    @args(com.xyz.security.Classified)

  • tradeService 라는 이름을 가진 스프링 빈의 모든 조인 포인트 (Spring AOP에서만 메서드 실행)
    bean(tradeService)

  • 와일드 표현식 Service 라는 이름을 가진 스프링 빈의 모든 조인 포인트
    bean(
    Service)

AOP 사용예제

@Aspect
public class TimeTraceAop {
    @Around("execution(* jpabook.jpashop..*(..))")
    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");
        }
    }
}
profile
성장하는사람이 되자

0개의 댓글