Aspect 사용법을 알아보기 앞서 AOP에 대한 사전지식이 필요하신 분들은 위 글을 참고해주세요.
⚡️AOP 어노테이션 사용법
자바 스프링에서 AOP를 사용하기 위해선 2가지 방법이 존재합니다.
XML과 어노테이션을 이용하는 방법이 있는데, 이 글에서는 어노테이션을 이용한 방법을 다뤄볼 겁니다.
기본적인 내용들을 설명 후 AOP를 직접 사용해보겠습니다.
📌 pom.xml 사전 설정
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.0</version>
</dependency>
AOP를 이용하기 전 pom.xml의 dependencies에 위 코드를 추가해서,
AspectJ Weaver 라이브러리를 추가해주도록 합니다.
📌 Pointcut 어노테이션
포인트 컷에 대한 자세한 내용은 위 글에서 소개했으니 참고 바랍니다.
📌 Advice 어노테이션
어노테이션 | 설명 |
@Before | 메소드가 실행되기 이전에 실행됩니다. |
@After | 메소드의 종료 후 무조건 실행됩니다. (try-catch에서 finally와 같은 동작) |
@After-returning | 메소드가 성공적으로 완료되고 리턴한 다음에 실행됩니다. |
@After-throwing | 메소드 실행 중 예외가 발생하면 실행됩니다. (try-catch에서 catch와 같은 동작) |
@Around | 메소드 호출 자체를 가로채서 메소드 실행 전후에 처리할 로직을 삽입할 수 있습니다. |
Advise의 종류와 사용법은 위와 같이 5가지가 존재합니다.
이를 사용하기 위해선 Pointcut 표현식으로 적용 범위를 적용해주어야 하는데,
대표적으로 다음과 같이 3가지 방식으로 Advice 어노테이션에 Pointcut을 적용 가능합니다.
@Component
@Aspect
public class SpringAspect {
// -1-
@Before("execution(* aop *.*(..)")
public void aop1() {}
// -2-
private final String pointcut = "execution(* aop *.*(..)";
@Before(pointcut)
public void aop2() {}
// -3-
@Pointcut("execution(* aop *.*(..)")
private void method() {}
@Before("method()")
public void aop3() {}
}
⚡️AOP 사용 예제
AOP 사용 예제 주제로 메소드 실행 시 실행 시간을 측정하는 기능을 준비해봤습니다.
실행 시간을 측정하기 위해선 메소드 실행 전과 실행 후를 하나의 변수에 담아 측정해야하기 때문에
@Around Advice를 사용했습니다.
아래는 문자열을 파라미터로 받는 searchMember 메소드입니다.
데이터베이스에서 1초만큼 작업 시간이 소요된다고 가정하고 1초의 지연시간을 주었습니다.
@Repository
public class MemberDao {
public void searchMember(String id) throws InterruptedException {
System.out.println("searchMember 실행");
Thread.sleep(1000); // 1초 정지
System.out.println("searchMember 종료");
}
}
이 searchMember 메소드의 시간을 구하기 위해 아래와 같은 Aspect를 사용했습니다.
@Component
@Aspect
public class SpringAspect {
@Around("execution(* aop_obj.*.*(..))")
public void timer(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("[Around] 시작");
StopWatch sw = new StopWatch();
sw.start();
joinPoint.proceed(); // 메소드 시작
sw.stop();
System.out.println("[Around] 메소드 이름 : "+joinPoint.getSignature().getName());
System.out.println("[Around] 메소드 첫번째 파라미터 : "+joinPoint.getArgs()[0]);
System.out.println("[Around] 메소드 소요 시간 : "+sw.getTotalTimeMillis());
}
}
@Around("execution(* aop_obj.*.*(..))")
포인트컷 표현식으로 MemberDao 클래스의 memberSearch 메소드를 포함 범위에 추가시켰습니다.
Around 어드바이스는 ProceedingJoinPoint를 파라미터로 받아
실행할 메소드의 시점을 조절하거나, 각종 정보들을 받아올 수 있습니다.
스톱워치를 시작하고 joinPoint.proceed()를 통해 가로챈 메소드를 실행시킨 후
메소드가 종료되면 스톱워치를 종료시켜 실행시간을 측정합니다.
그 후 메소드의 정보들과 측정한 시간을 출력합니다.
그럼 memberSearch 메소드를 실행시켜 AOP가 적용되는지 확인해보겠습니다.
public class Main {
public static void main(String[] args) throws InterruptedException {
ApplicationContext factory =
new AnnotationConfigApplicationContext(ConfigClass.class);
MemberDao md = factory.getBean("memberDao", MemberDao.class);
md.searchMember("LasBe");
}
}
컨테이너에서 빈을 받아와 searchMember 메소드를 실행시켜봤습니다.
메소드 전, 후로 Around 어드바이스가 잘 적용되어 출력된 것을 확인할 수 있습니다.
댓글