스프링 AOP - @AOP
참고문헌
스프링 AOP
- 애노테이션 기반의 스프링 @AOP
의존성 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Aspect 정의
- @Aspect
- 빈으로 등록해야 하니까 (컴포넌트 스캔을 사용한다면) @Component도 추가.
Pointcut 정의
- @Pointcut(표현식)
- 주요 표현식
- execution
- @annotation
- bean
- 포인트컷 조합
-
&&, , !
-
Advice 정의
- @Before
- @AfterReturning
- @AfterThrowing
- @Around
참고
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#aop-pointcuts
예시
execution
PerfAspect
@Component
@Aspect
public class PerfAspect {
@Around("execution(*.me.whiteship..*.EventService.*(..))")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
}
Anotation 만들어서 적용하기
- @Retention(RetentionPolicy.~)
- 어노테이션 정보를 얼마나 유지할 것인지.
- CLASS는 class 파일 까지 유지하겠다는 것임.
- 컴파일한 클래스 파일에도 이 정보가 남아있게 됨 (바이트코드에도 해당 어노테이션 정보가 있음)
- 디폴트가 CLASS이므로 이 어노테이션 따로 안붙여도 동일하게 작동.
- RetentionPolicy.SOURCE : 컴파일하고 나면 사라짐
- RetentionPolicy.RUNTIME : 런타임까지 유지. 그러나 굳이 런타임까지 유지할 필요는 없음
PerLogging.java
@Retention(RetentionPolicy.CLASS)
@Documented //javadoc 만들때 document에 포함될 수 있또록
@Target(ElementType.METHOD)
public @Interface PerLogging {
}
PerfAspect.java
@Component
@Aspect
public class PerfAspect {
@Around("@Annotation(PerLogging)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
}
SimpleEventService.java
@Service
public class SimpleEventService {
@PerLogging
@Override
public void createEvent() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Created an event");
}
@PerLogging
@Override
public void publishEvent() {
try{
Thread.sleep(2000);
} catch (InterruptedException e) {
System.out.println("Published an event");
}
}
public void deleteEvent() {
System.out.println("Delete an event")
}
}
Bean
PerfAspect
@Component
@Aspect
public class PerfAspect {
@Around("bean(simpleEventService)")
public Object logPerf(ProceedingJoinPoint pjp) throws Throwable {
long begin = System.currentTimeMillis();
Object retVal = pjp.proceed();
System.out.println(System.currentTimeMillis() - begin);
return retVal;
}
@Before("bean(simpleEventService)")
public void hello() {
System.out.println("hello");
}
}
Intellij는 어디에 적용되는지 알려줌
- 그러나 여기저기 흩어져 있다면 툴에 의존하기 보다는, annotation 만들어서 쓰는 방식이 더 편할 것