AOP(Aspect Oriented Programming) : 관점 지향 프로그래밍
프록시 패턴을 이용해 AOP 효과를 낸다.
클래스가 AOP의 대상이라면
Target - 어떤 대상에 기능을 부여할 것 인가
Advice - 어떤 부가기능?(before,after 등등)
Join point - 어디에 적용할 것 인가? (메서드,생성자 등등)
Point cut - 실제 advice가 적용될 지점, Spring AOP에서는 advice가 적용될 메소드를 선정
기존의 회원유저와 관련된 서비스 클래스가 아래와 같이 있다고 해보자.
class MemberServiceImpl{
public void join(MemberDto memberDto){
memberRepository.join(memberDto);
}
public void modify(MemberDto memberDto){
memberRepository.modify(memberDto);
}
//여러 서비스 메소드
}
각 메소드의 실행시간을 측정하고 싶을때 아래와 같이 메소드에 시간측정을 해주는 코드를 작성하면된다.
class MemberServiceImpl{
@Override
public void join(MemberDto memberDto){
long startTime = System.currentTimeMillis();
memberRepository.join(memberDto);
log.info(System.currentTimeMillis() - startTime);
}
@Override
public void modify(MemberDto memberDto){
long startTime = System.currentTimeMillis();
memberRepository.modify(memberDto);
log.info(System.currentTimeMillis() - startTime);
}
//여러 서비스 메소드
}
모든 클래스에 모든 메소드에 시간측정 코드를 넣는다면 아마 매우 귀찮을 것 이다.
그래서 AOP를 이용한다.
의존성을 추가해준뒤 AOP @Aspect 어노테이션을 붙여 Aspect를 나타내는 클래스라는 것을 명시한뒤 Component를 붙여 스프링 빈으로 등록한다. @Around어노테이션으로
org.springframework.boot
spring-boot-starter-aop
@Component //등록
@Aspect //aspect
public class PerfAspect {
@Around("@annotation(TimeLogging)") //point cut
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable{
long start = System.currentTimeMillis();
Object retVal = pjp.proceed(); // 메서드 호출 자체를 감쌈
System.out.println(System.currentTimeMillis() - start);
return retVal;
}
}
class MemberServiceImpl{
@TimeLogging
@Override
public void join(MemberDto memberDto){
long startTime = System.currentTimeMillis();
memberRepository.join(memberDto);
log.info(System.currentTimeMillis() - startTime);
}
@TimeLogging
@Override
public void modify(MemberDto memberDto){
long startTime = System.currentTimeMillis();
memberRepository.modify(memberDto);
log.info(System.currentTimeMillis() - startTime);
}
//여러 서비스 메소드
}
@Before (메소호출 이전) : 타겟 메소드가 호출되기 전에 어드바이스 기능을 수행
@After (메소드호출 이후) : 타겟 메소드가 종료되면 어드바이스 기능을 수행
@AfterReturning (실행 성공 후) : 타겟 메소드가 종료 후 어드바이스 기능을 수행
@AfterThrowing (예외 발생 후) : 타겟 메소드가 예외를 던지면 어드바이스 기능을 수행
@Around (메소드 호출 전후) : 타겟 메소드가 호출되기 전후에 어드바이스 기능을 수행