개발/Spring

[Spring] - AOP 예제

dongdev 2022. 2. 8. 00:08

AOP(Aspect Oriented Programming)는 관점 지향 프로그래밍이라 불린다.

공통 관심사(=횡단 관심사(Cross-Cutting Concerns))를 깔끔하게 처리하기 어려운 OOP를 보완하기 위해 개발되었다.

 

Spring에서 제공하는 Spring AOP는 프록시 기반으로 동작하며, 런타임 시점에 빈 후처리기(Bean Post Processor)를 통하여 기존 Bean 객체를 부가 기능이 더해진 프록시 객체로 바꿔친다. 또 프록시 기반으로 동작하기 때문에 메서드 실행 지점에만 AOP를 적용할 수 있다(프록시는 메서드 오버라딩 개념으로 동작). 마지막으로 Spring AOP는 스프링 컨테이너가 관리할 수 있는 Bean에만 AOP를 적용할 수 있다.

 

아래의 예제코드를 살펴보자.


build.gradle 

implementation 'org.springframework.boot:spring-boot-starter-aop'

Controller

package hello.helloaop.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AopContoller {

    @GetMapping("/aop")
    public String aopController() {
		
        System.out.println("aopController 실행");
        return "Hello Aop!";
    }
}

AopConfig 

package hello.helloaop.aop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AopConfig {

    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    public void getMapping() {}
	
    // @Around("execution(* hello.helloaop.controller..*(..))") 
    // hello.helloaop.controller 패키지 아래로 모두 적용하겠다는 뜻
    @Around("getMapping()")
    public Object excute(ProceedingJoinPoint jointPoint) throws Throwable {
        System.out.println("START: " + jointPoint.toString());
        try {
            return jointPoint.proceed();    //proceed() 기준으로 메소드 실행 전, 후로 나뉜다
        } finally {
            System.out.println("END: "+jointPoint.toString());
        }
    }
}

@Around 밑 메소드 부분이 Advice이다.

Advice는 '부가기능'을 뜻한다.

Advice 종류

  • @Before (이전)
    • 어드바이스 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
  • @After (이후)
    • 타겟 메소드의 결과에 관계없이(즉 성공, 예외 관계없이) 타겟 메소드가 완료 되면 어드바이스 기능을 수행
  • @AfterReturning (정상적 반환 이후)
    • 타겟 메소드가 성공적으로 결과값을 반환 후에 어드바이스 기능을 수행
  • @AfterThrowing (예외 발생 이후)
    • 타겟 메소드가 수행 중 예외를 던지게 되면 어드바이스 기능을 수행
  • @Around (메소드 실행 전후)
    • 어드바이스가 타겟 메소드를 감싸서 타겟 메소드 호출전과 후에 어드바이스 기능을 수행

이러한 Advice들이 적용될 수 있는 모든 위치를 Join point(조인 포인트)라 한다.

 

@Pointcut은 '어디에'라는 타겟을 정의해준다. 

Advice(부가기능) 와 Pointcut(적용대상)을 합해 Advisor을 이룬다. 개념상 하나의 애스펙트(@Aspect)로 봐도된다.

 

포인트컷에 이름을 부여해서 따로 정의하는 대신 어드바이스 메소드 애노테이션에 포인트컷 표현식을 넣어서 적용할 수 도 있다.

@Around("@annotation(org.springframework.web.bind.annotation.GetMapping)")

 

모든 용어들을 정리하자면 아래와 같다

  • Join point(조인 포인트): 어드바이스가 적용될 수 있는 모든 위치
  • Pointcut(포인트컷): 조인 포인트 중에서 어드바이스가 적용될 위치를 선별
  • Target(타겟): 어드바이스를 받는 객체, 포인트컷으로 결정
  • Advice(어드바이스): 부가 기능
  • Aspect(애스펙트): 어드바이스 + 포인트컷을 모듈화 한 것(@Aspect)

 

실행