[데브코스] Spring AOP

Updated: Categories:

W4D5 Part1 - Spring AOP 개념과 사용법에 대해 공부하자

AOP(Aspect Orient Programming)

  • 관점 지향 프로그래밍.
  • OOP를 대신하는 개념이 아닌, OOP를 더욱 잘 활용하게 해주는 개념이다.
  • 핵심기능과 부가기능을 분리하여 관리하는 것.

기본 구조

image

  • (Cross Cutting) Concerns : 기능이 중복되는 부분이다. 이 부분을 Aspect로 만들어 주는 것이 바로 AOP!


aop

  • Aspect : 기존 뜻은 ‘관점’이지만 -> ‘기능’을 묶는 모듈이라고 생각하면 좋다
  • Advice : 기존 Concern을 Aspect 모듈에 넣으면 Advice.
  • Target : 핵심 기능을 담고 있는 모듈. 부가기능을 부여할 대상 -> 즉 적용대상 클래스/메소드임
  • PointCut : Advice를 적용할 Target의 메소드를 선별하는 정규표현식
  • Join point : Advice가 Target에 적용되는 시점을 뜻한다


AOP 적용 - Weaving

image

  • 컴파일 시점 : AspectJ 같은 프레임워크를 사용해 컴파일 전 소스코드를 삽입하는 방식
  • 클래스 로딩 시점 : 클래스 로딩시 Byte Code를 삽입
  • 런타임 시점 : 스프링에서 사용하는 방식으로 Proxy 객체를 활용한다 더 알아보자!

Advice Join Point 분류

image


JDK dynamic Proxy

??


Spring AOP

  • aspectJ 어노테이션을 사용하나, 런타임 시점에서 적용됨

설정

  • 우선 pom.xml에 의존성 추가
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-aop</artifactId>
</dependency>

Aspect 클래스 생성

  • @Aspect 어노테이션을 달아줌
  • 반드시 Bean으로 등록되어야함.
@Aspect
@Component
public class 클래스 {
	...
}

PointCut 설정

  • 정규표현식으로 Advice가 적용될 범위인 PointCut을 설정한다
  • 정규표현식에 와일드카드로 *을 사용하고, 경로/인자값타입 생략은 ..으로 한다
  • Spring AOP는 public만 설정가능…
@Around("execution([접근지정자] [리턴타입] [패키지].[클래스].[메소드]([인자값타입]))")

PointCut 설정 - 메소드 분리

  • @PointCut을 사용해 정규표현식을 메소드로 분리하여 미리 정의할 수 있다.
  • 분리 메소드들은 하나의 클래스에 모아놓으면 깔끔하겠쥬?
// ex)  public의 모든 리턴타입을 포함하는 
//      ~kdt 패키지 하위의 Service 이름이 붙은 모든 클래스가 가지는 
//      인자값은 상관없는 모든 메소드
@PointCut("execution(public * org.prgrms.kdt..*Service.*(..))")
public void servicePublicMethodPointCut(){};

// 미리 정의된 PointCut 메소드 사용
@Around("servicePublicMethodPointCut()")
... Advice ...

PointCut 설정 - 어노테이션 분리

  • PointCut을 경로로 설정하지 않고 특정 어노테이션으로 설정할 수 있다.
  • 해당 어노테이션이 붙은 메소드만이 Target으로 선정됨
// 어노테이션 만들기
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface 어노테이션명 {
}
@Around("@annotation(~패키지경로.어노테이션명)")
... Advice ...

Advice 설정

  • 위에서 PointCut 범위 내의 모든 Target들에게 적용될 Advice 로직을 써준다
  • joinPoint.proceed()Target의 리턴값이 됨
@Around(정규표현식)
public Object 메소드명(ProceedingJoinPoint joinPoint) throws Throwable {
    var result = joinPoint.proceed();
    return result;
}
  • 이제 Target으로 선정된 메소드가 실행될때마다 위에서 정의한 Advice 로직이 실행된다.
  • Bean으로 등록된 객체만이 Target으로 지정된다