computer_study

[Spring] 07. AOP 프로그래밍 본문

스터디/스프링5 프로그래밍 입문

[Spring] 07. AOP 프로그래밍

knowable 2022. 4. 18. 01:31

목차

1. 프로젝트 준비

2. 프록시와 AOP

3. 스프링 AOP구현

4. 프록시 생성 방식

1. 프로젝트 준비

  • AOP : Aspect Oriented Programming
  • 스프링에선 spring-aop 모듈을 제공한다.
  • spring-context, aspectjweaver 모듈을 추가하여 사용할 수 있다.

2. 프록시와 AOP

프록시

  • 핵심 기능의 실행은 다른 객체에 위임하고 부가적인 기능을 제공하는 객체
  • ex) a 연산을 진행하는데 걸리는 시간을 구하고 싶다면
    시간을 구하는 객체에서 a연산을 호출만 한다. (직접 구현 x)
  • 여러 객체에 공통으로 적용할 수 있는 기능을 구현한다

AOP

  • 핵심 기능과 공통 기능을 분리하는 것(재 사용성을 높여주는 프로그래밍 기법)
  • 핵심 기능의 코드를 수정하지 않으면서 공통 기능의 구현을 추가하는 것
  • 런타임에 프록시 객체를 생성해서 공통 기능을 삽입하는 방법이 사용된다(spring에서)
  • 관련 용어
    • Advice
      • 언제 공통 기능을 핵심 로직에 적용할지 정의한다
      • Before Advice
        • 대상 객체의 메서드 호출 전 실행
      • After Returning Advice
        • 대상 객체의 메서드가 익셉션 없이 실행된 이후에 실행
      • After Throwing Advice
        • 대상 객체의 메서드 실행 도중 익셉션 발생한 경우 실행
      • After Advice
        • 익셉션에 상관 없이 대상 객체 메서드 실행 후 실행
      • Around Advice
        • 가장 널리 사용
        • 대상 객체의 메서드 실행 전, 후 or 익셉션 발생 시점에 실행
    • Aspect
      • 공통으로 적용되는 기능
    • JointPoint
      • Advice를 적용 가능한 지점
    • Pointcut
      • 실제 Advice가 적용되는 Jointpoint
    • Weaving
      • Advice를 핵심 로직 코드에 적용하는 것

3. 스프링 AOP구현

구현 방법

  • Aspect로 사용할 클래스에 @Aspect 애노테이션 붙인다
  • @Paintcut 애노테이션으로 공통 기능을 적용할 pointcut을 정의
  • 공통 기능을 구현한 메서드에 @Around 애노테이션을 적용
@Aspect
public class ExeTimeAspect{
   // 공통 기능을 적용 할 대상 설정
   // chap07패키지와 그 하위 패키지에 위치한 타입의 public 메서드를 pointcut으로 설정한다는 의미
   @Pointcut("execution(public*chap07..*(..))")
   private void publicTarget(){
   }
   
   // Around Advice 설정
   // publicTarget()메서드에 정의한 pointcut에 공통기능을 적용한다는 의미
   // chap07 패키지나 그 하위 페키지에 속한 빈 객체의 public 메서드에 @Around가 붙은 measure()메서드 적용
   @Around("publicTarget()")
   public Object measure(ProceedingJoinPoint jointpoint) throws Throwable{
     ...
   }

}
// AppCtx.java (스프링 설정클래스)

@Configuration
@EnableAspectJAutoProxy //  @Aspect 애노테애션 클래스를 공통 기능으로 적용하기 위해(스프링이 찾는다)
public class AppCtx{
    @Bean
    public ExeTimeAspect exeTimeAspect(){
        return new ExeTimeAspect();
    }
    
    @Bean
    public Calculator calculator(){
        return new RecCalculator();
    }
}

 

ProceedingJoinPoint의 매서드

Around Advice에서 사용할 공통 기능 메서드를 활용하기 위해 proceed()메서드를 호출한다.

 

ProceedingJointPoint 인터페이스가 제공하는 메서드

  • Signature getSignature()
    • 호출되는 메서드에 대한 정보
  • Object getTarget()
    • 대상 객체 구하기
  • Object[] getArgs()
    • 파라미터 목록 구하기

org.aspectj.lang.Signature 인터페이스가 제공하는 메서드

  • String getName()
    • 호출되는 메서드 이름 구하기
  • String toLongString()
    • 호출되는 메서드를 완전하게 표현한 문장
  • String toShortString()
    • 호출되는 메서드를 축약해서 표현한 문장

4. 프록시 생성 방식

스프링은 AOP를 위한 프록시 객체를 생성할 때 실제 생성할 빈 객체가 인터페이스를 상속하면 인터페이스를 이용해서 프록시를 생성한다.

인터페이스가 아닌 클래스를 이용해 프록시를 생성하기 위해선 설정이 필요하다.

@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppCtx{
}

인터페이스 Calculator , 앞선 인터페이스를 상속받은 RecCalculator가 있다고할 때

Calculator cal = ctx.getBean("calculator", Calculator.class)
//위 코드를 아래처럼 변경할 수 있게 된다.

RecCalculator cal = ctx.getBean("calculator", RecCalculator.class)

//proxyTargetClass 을 true로 하지 않는다면, 생성된 프록시는 RecCalculator가 아닌 Calculator를 상속하기에 에러가 발생한다

 

 

execution 명시자 표현식

  • 위 3번, pointcut 예시 참고
  • Advice를 적용할 메서드를 지정할 때 사용
  • 형식
    • execution([수식어패턴] [리턴타입패턴] [클래스이름 패턴?메서드 이름 패턴(파라미터 패턴)])
    • 수식어 패턴
      • 생략 가능, public이 온다 (스프링 AOP에서)
    • 클래스 이름 패턴, 메서드 이름 팬턴
      • 클래스 이름 및 메서드 이름을 패턴으로 명시
    • 파라미터 패턴
      • 매칭될 파라미터에 대해 명시
  • 명시자 예시
    • '*'
      • 모든 값을 표현 가능
    • '..'
      • 0개 이상임을 표현 가능

 

Advice 적용 순서

@Order 애노테이션을 사용하여 적용 순서를 지정할 수 있다.

import org.springframework.core.annotation.Order;

@Aspect
@Order(1)
public class ExeTimeAspect{
}

@Aspect
@Order(2)
public class CacheAspect{
}

위와 같이 지정한다면, ExeTimeAspect 프록시 -> CacheAspect 프록시 -> 실제 대상 객체 순서로 지정된다.

 

 

@Around의 Pointcut 설정과 @Pointcut 재사용

  • @Around 애노테이션에 execution 명시자를 지정할 수 있다.
    • @Around("executiuon(public * chap07 ..*(..))")
  • 같은 pointcut을 여러 Advice가 함께 사용한다면 공통 Pointcut을 재상용할 수도 있다
  • 여러 Aspect에서 공통으로 사용하는 Pointcut이 있다면 별도 클래스에 Pointcut을 정의하고 Aspect클래스에서 해당 pointcut을 사용하도록 구성하면 관리가 편해진다
    • 공통 Pointcut은 빈으로 등록할 필요 없이 @Around 애노테이션으로 사용할 수 있따.

 

Comments