728x90
포인트컷(Pointcut)의 주요 용도
포인트컷(Pointcut)은 AOP(Aspect-Oriented Programming)에서 Aspect(부가기능)가 적용될 지점을 결정하는 역할을 합니다. 즉, 어떤 메소드, 클래스 또는 패키지에 Advice(부가기능 로직)를 실행할지를 지정하는 것입니다. 이를 통해 특정 로직을 선택적으로 적용하고 불필요한 부분을 배제할 수 있습니다.
포인트컷(Pointcut) 왜 쓸까?
특정 메소드나 클래스에 부가기능을 정확히 적용하기 위해
- 모든 메소드에 일괄적으로 적용하면 불필요한 코드 실행이 발생할 수 있습니다.
- 포인트컷을 통해 정확히 필요한 클래스/메소드만 필터링해 부가기능(로깅, 트랜잭션)을 적용할 수 있습니다.
- 예시 : 특정 컨트롤러 클래스에만 로깅을 적용할 때.
유지보수성과 코드 간결성 향상
- 부가기능을 여러 곳에 반복적으로 추가하는 대신 한 번의 선언으로 특정 지점들에 부가기능을 적용할 수 있습니다.
- 만약 수정이 필요하면 포인트컷만 변경하면 되기 때문에 유지보수가 용이합니다.
- 예시 : 서비스 계층의 모든 메소드에 동일한 트랜잭션 관리 적용.
공통 관심사의 분리와 코드 중복 제거
- 로깅, 예외 처리 등과 같은 공통 기능을 Aspect로 분리하고, 포인트컷을 통해 여러 메소드에 적용하면 코드 중복을 줄이고 가독성을 높일 수 있습니다.
- 예시 : 모든 컨트롤러의 요청을 로깅.
유연하고 세밀한 부가기능 적용
- 포인트컷 표현식(within, execution, args 등)을 조합해 특정 조건에 맞는 지점에만 부가기능을 유연하게 적용할 수 있습니다.
- 예시: 매개변수로 특정 인자를 받는 메소드에만 부가기능 적용.
AOP 주요 어노테이션
- @Aspect : AOP를 정의하는 Class에 할당합니다
- @Pointcut : 어디(메소드, 어노테이션 등등)에 적용시킬지 지정하는 어노테이션입니다.
- @Before : 메소드 실행하기 이전에 실행됩니다 .
- @After : 메소드가 성공적으로 실행 후, 예외가 발생하더라도 실행됩니다 .
- @AfterReturing : 메소드 호출에 성공 했을 때 실행됩니다 .
- @AfterThrowing : 메소드 호출 실패(예외) 했을 때 실행됩니다 .
- @Around : @Before + @After 메소드 실행 전, 후로 실행됩니다.
AOP Pointcut 지시자(PCD : PointCut Designators)
- execution : 반환타입, 타입, 메소드, 파라미터 기준으로 지정(가장 세밀하게 제어가능)
- within : 특정 경로의 타입을 기준으로 지정
- this : 특정 타입의 객체를 기준으로 지정
- target : 특정 타입의 객체를 기준으로 지정
- args : 특정 타입의 파라미터를 가지는 메소드를 기준으로 지정
- @target : 특정 어노테이션을 가지는 객체를 기준으로 지정
- @args : 특정 어노테이션의 파라미터를 가지는 메소드를 기준
- @within : 특정 클래스의 경로의 어노테이션을 기준
- @annotation : 특정 메소드의 어노테이션을 기준
- bean : 스프링 빈을 기준으로 저징
자세한 내용은 여기를 클릭!!
간단한 포인트컷 예제
// AOP를 사용하여 메소드 실행 시간을 측정하고, 요청 인자를 수정하는 기능을 정의하는 클래스입니다.
@Aspect
@Component
public class TimerAop {
// 특정 클래스에 대해 AOP를 적용하기 위한 포인트컷을 정의합니다.
@Pointcut(value = "within(com.example.pointcut.controller.TestController)")
public void timerPointCut() {
// 포인트컷 메소드는 내용이 없으며, AOP에서 이 메소드를 참조하여 특정 지점을 지정합니다.
}
// 포인트컷에 정의된 메소드 실행 전 호출되는 메소드입니다.
@Before(value = "timerPointCut()")
public void before() {
System.out.println("Before");
}
// 포인트컷에 정의된 메소드 실행 후 호출되는 메소드입니다.
@After(value = "timerPointCut()")
public void after() {
System.out.println("After");
}
// 포인트컷에 정의된 메소드가 정상적으로 실행된 후 호출되는 메소드입니다.
@AfterReturning(value = "timerPointCut()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
System.out.println("after returning");
// 여기서 result를 통해 메소드의 반환 값을 확인할 수 있습니다.
}
// 포인트컷에 정의된 메소드 실행 중 예외가 발생했을 때 호출되는 메소드입니다.
@AfterThrowing(value = "timerPointCut()", throwing = "ex")
public void afterThrowing(JoinPoint joinPoint, Throwable ex) {
System.out.println("afterThrowing");
// 발생한 예외를 로깅하거나 처리할 수 있습니다.
}
// 포인트컷에 정의된 메소드를 감싸고, 실행 전후의 처리를 할 수 있는 메소드입니다.
@Around(value = "timerPointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 메소드 실행 전 로깅
System.out.println("메소드 실행 시작: " + joinPoint.getSignature().getName());
// 실행 시간을 측정하기 위한 StopWatch 객체 생성
StopWatch stopWatch = new StopWatch();
stopWatch.start();
Object result;
try {
// 실제 메소드 실행
result = joinPoint.proceed();
} catch (Throwable throwable) {
// 예외 발생 시 로깅
System.out.println("메소드 실행 중 예외 발생: " + throwable.getMessage());
throw throwable; // 예외를 다시 던져서 호출자에게 전달
}
// 메소드 실행 시간 측정
stopWatch.stop();
System.out.println("메소드 실행 완료: " + joinPoint.getSignature().getName() +
", 총 소요 시간: " + stopWatch.getTotalTimeMillis() + " ms");
// 메소드의 결과를 반환
return result;
}
}
728x90
'Spring Boot' 카테고리의 다른 글
[Spring Boot] HTTP Cookie 사용하기 (7) | 2024.10.20 |
---|---|
[Spring Boot] Http Session 사용하기 (8) | 2024.10.19 |
[Spring Boot] AOP (0) | 2024.10.14 |
[Spring Boot] 핸들러 인터셉터(Handler Interceptor) (0) | 2024.10.14 |
[Spring Boot] Spring MVC 아키텍처: 요청 처리 흐름과 주요 컴포넌트 (0) | 2024.10.14 |