AOP
Aspect Oriented Programming ✨ 여러 객체에 공통으로 적용할 수 있는 기능을 분리해서 재사용성을 높여주는 프로그래밍 기법이다. 공통 기능 구현과 핵심 기능 구현을 분리하는 것이 AOP의 핵심이다.
AOP의 기본 개념은 핵심 기능에 공통 기능을 삽입하는 것이다. 즉 핵심 기능의 코드를 수정하지 않으면서 공통 기능의 구현을 추가하는 것이 AOP인데 이 방법에는 세 가지가 있다.
AOP 주요 용어
스프링에서 구현 가능한 Advice 종류
Around Advice 가 가장 널리 사용되며, 대상 객체의 메서드를 실행하기 전/후, 익셉션 발생 시점 등 다양한 시점에 원하는 기능을 삽입할 수 있기 때문이다. 캐시 기능, 성능 모니터링 기능 같은 Aspect를 구현할 때에는 이 방법을 주로 이용한다.
스프링 AOP 구현
package aspect;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import java.util.Arrays;
// 공통 기능에 필요한 코드
@Aspect
public class ExeTimeAspect {
@Pointcut("execution(public * chap07..*(..))")
// 공통 기능을 적용할 대상 설정 - chap07 패키지와 그 하위 패키지에 위치한 타입의 public 메서드를 Pointcut으로 설정
private void publicTarget() {
}
@Around("publicTarget()")
// publicTarget() 메서드에 정의한 Pointcut에 공통 기능을 적용
// 즉 chap07 패키지나 그 하위 패키지에 속한 빈 객체의 public 메서드에 @Around가 붙은 measure() 메서드를 적용
public Object measure(ProceedingJoinPoint joinPoint) throws Throwable {
// ProceedingJoinPoint 파라미터는 프록시 대상 객체의 메서드를 호출할 때 사용
long start = System.nanoTime();
try {
Object result = joinPoint.proceed();
// proceed() 메서드를 사용하여 실제 대상 객체의 메서드를 호출
// 이 메서드를 호출하면 대상 객체의 메서드가 실행되므로 이 코드 이전과 이후에 공통 기능을 위한 코드를 위치시키면 됨
return result;
} finally {
long finish = System.nanoTime();
Signature sig = joinPoint.getSignature();
System.out.printf("%s.%s(%s) 실행 시간 : %d ns\n",
joinPoint.getTarget().getClass().getSimpleName(),
sig.getName(), Arrays.toString(joinPoint.getArgs()),
(finish - start));
// getSignature() - 호출한 메서드의 시그니처
// getTarget() - 대상 객체
// getArgs() - 인자목록
}
}
}
package config;
import aspect.ExeTimeAspect;
import chap07.Calculator;
import chap07.RecCalculator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
// @Aspect 어노테이션을 붙인 클래스를 공통 기능으로 적용하기 위해 붙여줌
// 이 어노테이션을 추가하면 스프링은 @Aspect 어노테이션이 붙은 빈 객체를 찾아서 빈 객체의 @Pointcut 설정과 @Around 설정 사용
public class AppCtx {
@Bean
public ExeTimeAspect exeTimeAspect() {
return new ExeTimeAspect();
}
@Bean
public Calculator calculator() {
return new RecCalculator();
}
}
🙋♀️@Enable류 어노테이션이란 ?
💡 스프링은 @EnableAspectJAutoProxy 와 같이 이름이 Enable로 시작하는 다양한 어노테이션을 제공한다. @Enable 로 시작하는 어노테이션은 관련 기능을 적용하는데 필요한 다양한 스프링 설정을 대신 처리한다.
ProceedingJoinPoint 메서드
Around Advice에서 사용할 공통 기능 메서드는 대부분 파라미터로 전달받은 ProceedingJoinPoint의 proceed() 메서드만 호출하면 된다.
ProceedingJoinPoint 인터페이스가 제공하는 메서드
org.aspectj.lang.Signature 인터페이스가 제공하는 메서드(호출되는 메서드의 정보 제공)