스프링 AOP 사용법

이해찬·2023년 9월 13일
0

TIL

목록 보기
13/20

2023.09.13

AOP 예제

📙 AOP란?

AOP(Aspect-Oriented Programming)는 프로그래밍 패러다임 중 하나로, 핵심 비즈니스 로직과는 별개로 횡단 관심사(Cross-cutting Concerns)를 모듈화하고 재사용 가능한 방법으로 분리하는 것을 목표로 한다.


주요 개념

  • 어드바이스(Advice): 실제로 수행되어야 할 작업을 정의한 코드 조각입니다. 예를 들면 메서드 실행 전/후에 수행되어야 할 작업 등입니다.
  • 타겟(Target): 어드바이스가 적용될 대상 객체 또는 메서드입니다.
  • 조인 포인트(Join Point): 타겟 객체 내에서 Advice가 적용될 수 있는 위치를 말합니다. 예를 들면 메서드 호출 시점, 필드 값 변경 시점 등입니다.
  • 포인트컷(Pointcut): 조인 포인트 중 일부만 선택하는 기준을 정의하는 것으로, 어느 Join Point에 Advice를 적용할지 결정합니다.
  • 위빙(Weaving): AOP 프레임워크가 컴파일 시간, 클래스 로딩 시간 또는 실행 시간에 Aspect와 Target 사이에 연결 작업을 수행하여 Aspect 코드가 적절한 위치에서 동작하도록 하는 과정입니다.

동작 원리 👉 컴파일 타임 / 클래스 로딩 타임 /런타임

런타임 방식은 애플리케이션이 이미 시작된 이후부터 동작하며, 프록시 객체를 생성하여 Advice 코드를 적용하는 방식입니다. 대부분의 AOP 프레임워크는 런타임 방식을 사용한다.



예제

implementation 'org.springframework.boot:spring-boot-starter-aop' = 의존성 추가

@Aspect / @Component
-LoggingAspect

@Aspect
@Component
public class LoggingAspect {

    @Before("execution(* com.example.practice.service.Calculator.divide(..))")
    public void beforeDivide(JoinPoint joinPoint) {
        System.out.println("나눗셈 연산 시작");
        Object[] args = joinPoint.getArgs();
        System.out.println("나누는 수: " + args[0]);
        System.out.println("나눠지는 수: " + args[1]);
    }

    @AfterReturning(pointcut = "execution(* com.example.practice.service.Calculator.divide(..))", returning = "result")
    public void afterDivide(JoinPoint joinPoint, Object result) {
        System.out.println("나눗셈 연산 종료");
        System.out.println("결과: " + result);
    }
}

@Before : 대상 메서드 실행 전
("execution(* com.example.practice.service.Calculator.divide(..))")
: 해당 메서드의 위치와 포인트컷 표현식 사용

따라서, joinPoint.getArgs()를 호출하면 divide 메서드의 매개변수 int a와 int b의 값이 Object 배열로 반환된다. 배열의 첫 번째 원소(args[0])는 int a의 값이고, 두 번째 원소(args[1])는 int b의 값

  • JoinPoint 자체는 매개변수를 나타내지 않지만, 그를 통해 메서드의 매개변수에 접근할 수 있다.


@Service
-Calculator

@Service
public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }

    public int divide(int a, int b) {
        return a / b;
    }
}

@SpringBootApplication
@EnableAspectJAutoProxy
-PracticeApplication

@SpringBootApplication
@EnableAspectJAutoProxy
public class PracticeApplication {

	public static void main(String[] args) {
		ApplicationContext context = SpringApplication.run(PracticeApplication.class, args);

		Calculator calculator = context.getBean(Calculator.class);
		int result = calculator.divide(10, 2);
		System.out.println("결과: " + result);
	}
}
profile
디자인에서 개발자로

0개의 댓글