각 클래스에 핵심기능은 가운데의 test1, 2, 3임
여기서 AAA가 바뀌어야하는 경우 3군데를 모두 바꾸어 주어야 함
따라서, 부가적인 기능들(AAA,BBB)을 분리해 모듈화하면 핵심 기능과 부가적인 기능들이 분리되어 있기 때문에 핵심 기능의 수정 없이 쉽게 부가 기능을 붙이거나 수정할 수 있고 코드의 재사용성을 높일 수 있다.
@Target(ElementType.METHOD) // 해당 어노테이션을 어디에 적용할 것인지 => 메소드에 적용할 것이다
@Retention(RetentionPolicy.RUNTIME) // 해당 어노테이션을 언제까지 유지할 것인지 => 런타임까지 유지
public @interface LogExecutionTime {
}
@Component // Bean 으로 등록해야 하므로
@Aspect // Aspect Class
public class LogAspect {
Logger logger = LoggerFactory.getLogger(LogAspect.class);
// Around 애노테이션으로 pointcut 표시 해줌 (advice 가 적용될 위치)
@Around("@annotation(LogExecutionTime)")
// joinPoint => target method (LogExecutionTime 애노테이션이 붙은 method)
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
// target method 실행하기 전 앞 뒤로 부가 기능을 붙여줌
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object proceed = joinPoint.proceed(); // target method 실행
stopWatch.stop();
logger.info(stopWatch.prettyPrint());
return proceed;
}
}
위 예시는 프록시 패턴으로 구현이 되었는데 핵심 기능 외에 부가적인 공통된 기능을 담고 있는 객체를 프록시 객체라고 하고 이렇게 프록시 객체를 통해 기존 코드를 건들이지 않고 부가 기능을 붙이는 패턴을 프록시 패턴이라고 한다.
@Transactional 어노테이션 역시 AOP 가 적용된 사례라고 볼 수 있다.
해당 어노테이션이 붙은 함수는 자동적으로 try catch 가 감싸져 예외가 발생하면 해당 동작이 실행되기 이전 시점으로 롤백시켜준다.
Spring AOP는 아래와 같은 type의 Advice를 제공합니다.
@Before
Before는 target 메서드가 실행되기 전에 Advice가 실행됩니다. target이 실행되지 못하도록 막는 방법은 가지고 있지 않습니다. (exception을 발생시키면 되기는 합니다.)
@After
After는 target 메서드가 실행된 후에 Advice가 실행됩니다. 정상적으로 메서드가 마무리되든 비정상적으로 exception이 발생하든 무조건 실행되는 Aspect입니다..
@Around
Around는 traget 메서드를 감싸는 Advice입니다. 즉, 앞과 뒤에 모두 영향을 미칠 수 있습니다. 또한 Around는 target을 실행할 지 아니면 바로 반환할지도 정할 수 있습니다. Advice 중 가장 강력하다고 할 수 있겠습니다.
@AfterReturning
AfterReturning은 target 메서드가 정상적으로 끝낫을 경우 실행되는 Advice입니다.
@AfterThrowing
AfterThrowing은 target 메서드에서 throwing이 발생했을 때 실행되는 Advice입니다.
출처
https://ant-programmer.tistory.com/79
https://sabarada.tistory.com/95