[Spring] AOP (Aspect-Oriented Programming)

kang·2024년 9월 10일

SPRING

목록 보기
18/22

1. AOP란?

  • AOP는 관심사를 분리하여 모듈화하는 프로그래밍 패러다임입니다.
    OOP가 객체를 통해 복잡한 문제를 해결하려는 것처럼, AOP는 핵심 기능과 부가 기능을 분리해 여러 곳에서 발생하는 횡단 관심사(cross-cutting concerns)를 모듈화하는 데 초점을 맞춥니다.

2. 핵심 개념

  • 핵심기능: 애플리케이션에서 주로 실행되는 기능.
  • 부가기능: 로그, 인증, 시간 측정 등 주요 기능에 부가되는 기능.
  • 횡단관심사: 여러 곳에서 반복적으로 발생하는 부가기능.
  • 어드바이스(Advice): 실제로 실행되는 부가기능 코드.
  • 포인트컷(Pointcut): 어드바이스를 적용할 범위.
  • 타겟(Target): 어드바이스가 적용되는 객체.
  • 조인포인트(JoinPoint): 어드바이스가 적용되는 실행 지점.
  • 애스팩트(Aspect): 어드바이스와 포인트컷을 하나로 묶은 모듈.

3. AOP 적용

AOP는 스프링에서 빈 후처리기(Bean Post Processor)를 통해 적용됩니다. 객체를 빈으로 등록할 때 해당 객체를 프록시로 감싸는 방식으로 AOP를 적용합니다. AOP 적용 후에는 프록시 객체가 실제로 호출되며, 이를 통해 부가기능이 실행됩니다.

4. 실습 코드

1. Aspect Class (횡단 관심사를 정의한 클래스)

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Slf4j
@Aspect
@Component
public class ExecutionTimeAspect {

    // 포인트컷: 서비스 레이어의 모든 메서드에 적용
    @Pointcut("execution(* com.example.demo.service..*(..))")
    public void serviceLayer() {}

    // 어드바이스: 메서드 실행 전후에 걸쳐 시간을 측정하는 로직
    @Around("serviceLayer()")
    public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis(); // 시작 시간 측정

        try {
            // 메서드 실행
            Object result = joinPoint.proceed();
            return result;
        } finally {
            // 종료 시간 측정 및 실행 시간 출력
            long endTime = System.currentTimeMillis();
            long executionTime = endTime - startTime;
            log.info("Method {} executed in {}ms", joinPoint.getSignature(), executionTime);
        }
    }
}

2. WebConfig Class (Aspect 등록)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WebConfig {

    @Bean
    public ExecutionTimeAspect executionTimeAspect() {
        return new ExecutionTimeAspect();
    }
}

3. Service Class (핵심 기능이 구현된 클래스)

import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@Service
public class CourseService {

    public String createCourse(String courseName) {
        // 실제 비즈니스 로직: 수업 생성
        log.info("Course {} is being created...", courseName);
        return "Course created: " + courseName;
    }
}

4. Controller Class (API 엔드포인트)

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class CourseController {

    private final CourseService courseService;

    @GetMapping("/course/create")
    public String createCourse(@RequestParam String name) {
        return courseService.createCourse(name);
    }
}

5. 어드바이스 종류

  • Before: 메서드 실행 전에 실행됨.
  • AfterReturning: 메서드가 정상적으로 실행된 후에 실행됨.
  • AfterThrowing: 메서드 실행 중 예외가 발생했을 때 실행됨.
  • After: 메서드가 완료된 후 항상 실행됨.
  • Around: 메서드 실행 전, 후, 예외 발생 시 모든 흐름을 제어할 수 있음.
profile
뉴비 개발 공부중

0개의 댓글