OOP: Object Oriented Programming
복잡한 프로그래밍 세상을 객체로 정의하는 목적이 있다.
AOP: Aspect Oriented Programming
복잡한 프로그래밍 세성에서 관심사를 분리하여 모듈로 사용하는데 목적이 있다.
AOP는 여러가지 소프트웨어 개발 패러다임 중 하나이다.
프로그램의 핵심 비즈니스 로직에서 횡단 관심사(cross-cutting concerns)를 분리하는 방법이다.
AOP를 사용하면 이러한 관심사를 핵심 비즈니스 로직과 분리하여 코드의 중복을 줄이고 가독성 및 유지보수성을 높일 수 있다.
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logMethodDetails(JoinPoint joinPoint) {
System.out.println("Method: " + joinPoint.getSignature().getName());
System.out.println("Arguments: " + Arrays.toString(joinPoint.getArgs()));
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void logMethodDetails(JoinPoint joinPoint) {
System.out.println("Method: " + joinPoint.getSignature().getName());
System.out.println("Arguments: " + Arrays.toString(joinPoint.getArgs()));
}
}
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example.service.*.*(..))")
public void beforeAdvice() {
System.out.println("Before method execution");
}
@After("execution(* com.example.service.*.*(..))")
public void afterAdvice() {
System.out.println("After method execution");
}
@Around("execution(* com.example.service.*.*(..))")
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("Before method execution (Around)");
Object result = joinPoint.proceed(); // 실제 메서드 실행
System.out.println("After method execution (Around)");
return result;
}
@AfterThrowing("execution(* com.example.service.*.*(..))")
public void afterThrowingAdvice() {
System.out.println("Exception occurred");
}
}
@Aspect
public class LoggingAspect {
@Pointcut("execution(* com.example.service.UserService.*(..))") // UserService의 모든 메서드
public void userServiceMethods() {}
@Before("userServiceMethods()") // 위에서 정의한 포인트컷에 대해 Advice 적용
public void logBeforeUserServiceMethods() {
System.out.println("UserService method is about to be called");
}
}
@Target(ElementType.METHOD) // 이 어노테이션을 메서드에만 사용할 수 있게 지정
@Retention(RetentionPolicy.RUNTIME) // 런타임에도 어노테이션 정보가 유지되도록 설정
public @interface LogExecutionTime {
}
@Aspect
@Component
public class ExecutionTimeAspect {
// @LogExecutionTime 애노테이션이 붙은 메서드에 대해 AOP 적용
@Around("@annotation(LogExecutionTime)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis(); // 메서드 실행 전 시간 측정
Object proceed = joinPoint.proceed(); // 실제 메서드 실행
long executionTime = System.currentTimeMillis() - start; // 메서드 실행 후 시간 계산
System.out.println(joinPoint.getSignature() + " executed in " + executionTime + "ms");
return proceed;
}
}
@Aspect와 @Component를 사용하여 이 클래스가 Aspect 역할을 할 것임을 선언한다.
@Around("@annotation(LogExecutionTime)"): @LogExecutionTime 애노테이션이 붙은 모든 메서드에 대해 이 Aspect가 적용될 수 있다.
ProceedingJoinPoint를 사용하여 실제 메서드를 실행하고 그 실행 시간까지 측정한다.
@Service
public class UserService {
@LogExecutionTime
public void createUser(String name) {
// 사용자 생성 로직
System.out.println("Creating user: " + name);
}
@LogExecutionTime
public void deleteUser(String name) {
// 사용자 삭제 로직
System.out.println("Deleting user: " + name);
}
}
@LogExecutionTime을 사용하여 createUser와 deleteUser 메서드에 AOP를 적용한다.
이 메서드가 실행될 때, ExecutionTimeAspect의 로직이 먼저 실행되어 실행 시간을 측정하고, 메서드가 종료된 후 측정된 시간을 출력한다.