Java/Spring

맨날 까먹는 AOP 정리

Icarus8050 2019. 7. 20. 01:57
반응형

AOPAspect-Oriented Programming 의 약자입니다. AOP 로 로직상에서 문제를 해결하고자 하는 핵심 기능과 공통 기능을 분리하는 프로그래밍 방법입니다.

AOP 의 주요 키워드

Target

공통 기능을 부여할 대상입니다. 즉, 핵심 기능을 담당하는 비즈니스 로직이고, 어떤 관심사들과도 관계를 맺지 않습니다.

 

Aspect

여러 핵심 기능에 적용될 관심사 모듈입니다. Aspect 에는 구체적인 기능을 구현한 Advice 와 Advice 가 어디에서 적용될지를 결정하는 PointCut 을 포함하고 있습니다.

 

Advice

Advice 는 공통 기능을 담은 구현체입니다. Advice 는 Aspect 가 무엇을 언제 적용할 지를 정의합니다.

 

PointCut

PointCut 은 공통 기능이 적용될 대상을 결정합니다.

 

JoinPoint

Advice 가 적용될 지점을 의미합니다. Spring 에서는 메서드만이 JoinPoint 로 제공하고 있습니다.

 

Proxy

Target 을 랩핑하여 Target 의 요청을 대신 받아주는 오브젝트입니다.

 

Weaving

지정된 객채에 Aspect 를 적용해서 새로운 프록시 객체를 생성하여 적용하는 것을 말합니다. 즉, 공통 코드를 핵심 로직 코드에 삽입하는 과정입니다.

Advice 정리

@Before

Advice 의 Target 메서드가 호출되기 전에 실행되는 Advice 입니다.

 

@After

Advice 의 Target 메서드가 호출된 후에 그 결과에 상관없이(성공 or 실패) 실행되는 Advice 입니다.

 

@AfterReturning

Target 메서드가 정상적으로 실행된 후에 실행되는 Advice 입니다.

 

@AfterThrowingAdvice

Target 메서드가 수행도중 예외가 발생했을 때 예외를 던지게 되면 실행되는 Advice 입니다.

 

@Around

Advice 가 Target 메서드를 감싸서 Target 메서드 호출 전과 후에 실행되는 Advice 입니다. @Around 는 ProceedingJoinPoint 의 proceed() 를 수행하는데, proceed() 의 리턴 값이 sub 메서드의 리턴 값이다. 즉, @Advice 내부에서 결과값을 제어할 수 있다.


PointCut 표현식

포인트 컷에는 아래와 같은 명시자를 이용할 수 있습니다.

  • execution : Advice 를 적용할 메서드를 명시할 때 사용합니다.
  • within : 특정 타입에 속하는 메서드를 JoinPoint 로 설정되도록 명시할 때 사용합니다.
  • bean : 스프링 버전 2.5 버전부터 지원하기 시작했으며, 스프링 빈을 이용하여 JoinPoint 를 설정합니다.

execution 명시자

execution([수식어] 리턴 타입 [클래스 이름].이름(파라미터))

  • 수식어 : public, private 등 수식어를 명시합니다. (생략가능)
  • 리턴 타입 : 리턴 타입을 명시합니다.
  • 클래스 이름 및 이름 : 클래스 이름과 메서드 이름을 명시합니다. (클래스 이름은 풀 패키지 명으로 명시해야합니다. 클래스 이름은 생략할 수도 있습니다.)
  • 파라미터 : 메서드의 파라미터를 명시합니다.
  • " * " : 모든 값을 표현합니다.
  • " .. " : 0개 이상을 의미합니다.

ex)

execution(public Integer com.edu.aop..(*))

  • com.edu.aop 패키지에 속해있고, 파라미터가 1개인 모든 메서드

execution(* com.edu...get(..))

  • com.edu 패키지 및 하위 패키지에 속해있고, 이름이 get 으로 시작하는 파라미터가 0개 이상인 모든 메서드

execution(* com.edu.aop..Service.(..))

  • com.edu.aop 패키지 및 하위 패키지에 속해있고, 이름이 Service 로 끝나는 클래스의 파라미터가 0개 이상인 모든 메서드

execution(* com.edu.aop.BoardService.*(..))

  • com.edu.aop.BoardService 클래스에 속한 파라미터가 0개 이상인 모든 메서드

execution(* some(, *))

  • 메서드 이름이 some 으로 시작하고 파라미터가 2개인 모든 메서드

within 명시자

ex)

within(com.edu.aop.SomeService)

  • com.edu.aop.SomeService 클래스의 모든 메서드

within(com.edu.aop.*)

  • com.edu.aop 패키지의 모든 메서드

within(com.edu.aop..*)

  • com.edu.aop 패키지 및 하위 패키지의 모든 메서드

bean 명시자

ex)

bean(someBean)

  • 이름이 someBean인 빈의 모든 메서드

bean(somm*)

  • 빈의 이름이 some 으로 시작하는 빈의 모든 메서드

아래의 @PointCut 애너테이션을 이용하여 JoinPoint 를 지정할 수 있다.

@Component
@Aspect
public class SampleAspect {

    @Pointcut("@annotation(com.edu.aop.Sample)")
    private void pointcut() { }

    @AfterReturning(pointcut = "pointcut()", returning = "returnValue")
    public Object afterReturning(JoinPoint joinPoint, Object returnValue) {
                //TODO : Something logic...
        return returnValue;
    }
}

 모든 어드바이스는 org.aspectj.lang.JoinPoint 타입의 파라미터를 어드바이스의 첫 파라미터로 선언할 수 있다. Around advice 는 JoinPoint 의 하위 클래스인 ProceedingJoinPoint 타입의 파라미터를 필수적으로 첫 파라미터로 선언해야 한다.

 JoinPoint 인터페이스는 getArgs() (메서드 argument를 반환한다.), getSignature() (advice되는 메서드의 시그니처를 반환한다.), toString() (advice 되는 메서드의 유용한 설명을 출력한다.) 같은 다수의 유용한 메서드를 제공한다.


유용한 자료

[Spring 레퍼런스] 8장 스프링의 관점 지향 프로그래밍 #2 :: Outsider's Dev Story

반응형