스프링 핵심 기술 익히기(2) - AOP(관점 지향 프로그래밍)

김태은·2022년 4월 26일
0

AOP(Aspect Oriented Programming)

  • 메서드 안의 주기능과 보조 기능을 분리한 후 선택적으로 메서드에 적용해서 사용한다는 개념
  • 전체 코드에서 흩어져 있는 보조 기능을 하나의 장소에 모아서 관리 가능
  • 보조 기능을 자신이 원하는 주기능에 선택적으로 적용할 수 있어 코드가 단순해지고 가독성 향상
  • 각각의 보조 기능을 미리 만들어 놓고 설정만 해주면 각각의 주기능을 수행하는 메서드나 클래스에 선택적으로 보조 기능 적용

AOP 관련 용어

  • aspect : 구현하고자 하는 보조 기능을 의미, AOP 중에서 가장 많이 활용되는 부분은 @Transactional (트랜잭션 관리) 기능
  • advice : aspect의 실제 구현체(클래스)를 의미, 메서드 호출을 기준으로 여러 지점에서 실행, AOP에서 실제로 적용하는 기능(로깅, 트랜잭션, 인증 등)을 뜻함
  • joinpoint : advice를 적용하는 지점을 의미, 모듈화된 특정 기능이 실행될 수 있는 연결 포인트
  • pointcut : advice가 적용되는 대상을 지정, 패키지이름/클래스이름/메서드이름을 정규식으로 지정하여 사용
  • target : advice가 적용되는 클래스를 의미
  • weaving : advice를 주기능에 적용하는 것을 의미

AOP 기능 구현

  1. Aspect의 생성
package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
@Component  // Component를 붙인 것은 해당 Aspect를 스프링의 Bean으로 등록해서 사용하기 위함
public class UsefulAspect {

}
  • 구현하고자 하는 보조 기능 UsefulAspect 생성
  • Aspect = UsefulAspect 클래스
  1. Pointcut 선언
package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
@Component  // Component를 붙인 것은 해당 Aspect를 스프링의 Bean으로 등록해서 사용하기 위함
public class UsefulAspect {

	@Pointcut("execution(* transfer(..))")
	private void anyOldTransfer() {}
}
  • 해당 Aspect의 Advice(실행할 액션)이 적용될 Join point를 찾기 위한 패턴 또는 조건 생성
  • 포인트 컷 표현식이라고 부름
  • Advice = anyOldTransfer()
  1. Pointcut 결합
package org.xyz;
import org.aspectj.lang.annotation.Aspect;

@Aspect
@Component  // Component를 붙인 것은 해당 Aspect를 스프링의 Bean으로 등록해서 사용하기 위함
public class UsefulAspect {

	@Pointcut("execution(public * *(..))")
	private void anyPublicOperation() {} //public 메서드 대상 포인트 컷

	@Pointcut("within(com.xyz.myapp.trading..*)")
	private void inTrading() {} // 특정 패키지 대상 포인트 컷
	
	@Pointcut("anyPublicOperation() && inTrading()")
	private void tradingOperation() {} // 위의 두 조건을 and(&&) 조건으로 결합한 포인트 컷
}

Advice 정의

포인트컷들을 활용하여 포인트컷의 전/후/주변에서 실행될 액션을 정의함

  1. Before Advice
  • dataAccessOperation()이라는 미리 정의된 포인트 컷의 바로 전에 doAccessCheck가 실행
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class BeforeExample {

    @Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
    public void doAccessCheck() {
        // ...
    }
}
  1. After Returning Advice
  • dataAccessOperation()라는 미리 정의된 포인트컷에서 return이 발생된 후 실행
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.AfterReturning;

@Aspect
public class AfterReturningExample {

    @AfterReturning("com.xyz.myapp.CommonPointcuts.dataAccessOperation()")
    public void doAccessCheck() {
        // ...
    }
}
  1. Around Advice
  • businessService()라는 포인트컷의 전/후에 필요한 동작을 추가함
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.ProceedingJoinPoint;

@Aspect
public class AroundExample {

    @Around("com.xyz.myapp.CommonPointcuts.businessService()")
    public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable {
        // start stopwatch
        Object retVal = pjp.proceed();
        // stop stopwatch
        return retVal;
    }
}

참고 : https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop

0개의 댓글