2021. 8. 11. 14:10ㆍCSE/Spring
- 스프링 AOP를 이용하는 방법은 다음과 같다.
- Aspect로 사용할 클래스에 @Aspect 애노테이션을 붙인다.
- @Pointcut 애노테이션으로 공통 기능을 적용할 Pointcut을 정의한다.
- 공통 기능을 구현한 메서드에 @Around 애노테이션을 적용한다.
- 개발자는 공통 기능을 제공하는 Aspect 구현 클래스를 만들고 자바 설정을 이용해서 Aspect를 어디에 적용할지 설정하면 된다.
- 프록시는 스프링 프레임워크가 알아서 만들어준다.
@Aspect
public class ExeTimeAspect {
//@Pointcut은 공통 기능을 적용할 대상을 설정한다.
@Pointcut("execution(public * chap07..*(..))")
private void publicTarget(){
}
//@Around 애노테이션은 Around Advice를 설정한다.
//publicTarget() 메서드에 정의한 Pointcut에 공통기능을 적용한다
@Around("publicTarget()")
public Object measure(ProceedingJoinPoint joinPoint) throws Throwable{
//ProceedingJoinPoint 파라미터는 프록시 대상 객체의 메서드를 호출할 때 사용한다.
long start = System.nanoTime(); //joinPoint.proceed() 전에 공통 기능 코드 위치
try{
Object result = joinPoint.proceed(); //프록시 대상 객체 메서드 실행
return result;
}finally{
//joinPoint.proceed() 후에 공통 기능 코드 위치
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);
}
}
}
- 위 코드는 메서드 실행 전/후 (Around Advice)에 사용할 공통 기능(Aspect)이다
== 위 코드는 Around Advice에서 사용할 Aspect이다.
★ 메서드 시그니처
- 자바에서 메서드 이름과 파라미터를 합쳐서 메서드 시그니처라고 한다.
- 메서드 이름이나 파라미터 타입, 개수가 다르면 시그니처가 다르다
- 이 때, 리턴 타입이나 익셉션 타입은 시그니처에 포함되지 않는다.
//스프링 설정 파일
@Configuration
@EnableAspectJAutoProxy
public class AppCtx {
@Bean
public ExeTimeAspect exeTimeAspect(){
return new ExeTimeAspect();
}
@Bean
public Calculator calculator(){
return new RecCalculator();
}
}
- @Aspect 애노테이션을 붙인 클래스를 공통 기능으로 적용하려면 @EnableAspectJAutoProxy 애노테이션을 설정 클래스에 붙여야 한다.
=> 스프링은 @Aspect 애노테이션이 붙은 빈 객체를 찾아서 빈 객체의 @Pointcut 설정과 @Around 설정을 사용한다.
public class MainAspect {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(AppCtx.class);
Calculator cal = ctx.getBean(Calculator.class);
long fiveFact = cal.factorial(5);
System.out.println("cal.factorial(5) = " + fiveFact);
System.out.println(cal.getClass().getName());
ctx.close();
}
}
//RecCalculator.factorial([5]) 실행 시간 : 50201 ns
//cal.factorial(5) = 120
//com.sun.proxy.$Proxy17
- Calculator 타입이 RecCalculator 클래스가 아니고 $Proxy17이다. (스프링이 생성한 프록시 타입)
=> 실제 cal.factorial(5) 코드를 호출할 때 실행되는 과정이 다음과 같기 때문
* ProceedingJoinPoint 인터페이스는 다음 메서드를 제공한다.
- Signature getSignature() : 호출되는 메서드에 대한 정보를 구한다
- Object getTarget() : 대상 객체를 구한다
- Object[] getArgs() : 파라미터 목록을 구한다
* org.aspectj.lang.Signauture 인터페이스는 다음 메서드를 제공한다.
- String getName() : 호출되는 메서드의 이름을 구한다
- String toLongString() : 호출되는 메서드를 완전하게 표현한 문장을 구한다 (메서드의 리턴 타입, 파라미터 타입이 모두 표시됨)
- String toShortString() : 호출되는 메서드를 축약해서 표현한 문장을 구한다 (메서드의 이름만을 구한다)
'CSE > Spring' 카테고리의 다른 글
[Spring5입문] DB 연동 (0) | 2021.09.14 |
---|---|
[Spring5입문] 프록시 생성 방식 (0) | 2021.08.11 |
[Spring5입문] AOP 프로그래밍 기초 (0) | 2021.08.09 |
[Spring5입문] 빈 라이프사이클과 범위 (0) | 2021.08.09 |
[Spring5입문] 컴포넌트 스캔 (0) | 2021.08.08 |