그라가승훈
[SpringBoot] - AOP 본문
- AOP(Aspect Oriented Programming)란?
AOP는 OOP 를 더욱 OOP답게 사용하도록 도와주는 개념이다.
AOP는 애플리케이션 전반에서 사용되는 기능(로그, 권한 체크, 인증, 예외처리 등)을 여러 코드에 쉽게 적용할 수 있도록 한다.
AOP 는 각 부가 기능의 관점에서 바라본 관점지향프로그래밍으로, 해당 부가 기능이 적용되어야 하는 시점을 설정하여 적용한다.
1. AOP 용어
- 관점(Aspect) : 공통적으로 적용될 기능을 의미, 횡단 관심사의 기능이라고도 할 수있다. 한 개 이상의 포인트컷과 어드바이스의 조합으로 만들어진다.
- 어드바이스(Advice) : 관점의 구현체로 조인포인트에 삽입되어 동작한다. 스프링에서 사용하는 어드바이스는 동작 시점에 따라 다섯 종류로 구분된다.
- 조인포인트(Joinpoint) : 어드바이스를 적용하는 지점을 의미한다. 스프링프레임워크에서 조인포인트는 항상 메서드 실행 단계만 가능.
- 포인트컷(Pointcut) : 어드바이스를 적용할 조인포인트를 선별하는 과정이나 그 기능을 정의한 모듈을 의미.
- 타깃(Target) : 어드바이스를 받을 대상을 의미.
- 위빙(Weaving) : 어드바이스를 적용하는 것을 의미. 즉, 원하는 대상에 공통코드를 삽입하는 것을 뜻한다.
- AOP 적용
컨트롤러, 서비스, 매퍼 메서드가 실행될 때 로그를 출력하는 로그 AOP 를 적용.
1. LoggerrAspect 클래스
aop 패키지 생성 후 LoggetAspect 클래스 생성.
@Component
@Aspect
@Slf4j
public class LoggerAspect {
@Around("execution(* com.example..controller.*Controller.*(..)) || " +
"execution(* com.example..service.*Impl.*(..)) ||" +
"execution(* com.example..mapper.*Mapper.*(..))")
public Object logPrint(ProceedingJoinPoint joinPoint) throws Throwable {
String type = "";
String name = joinPoint.getSignature().getDeclaringTypeName();
if (name.contains("Controller")) {
type = "Controller \t: ";
} else if (name.contains("Service")) {
type = "ServiceImpl \t: ";
} else if (name.contains("Mapper")) {
type = "Mapper \t\t: ";
}
log.debug(type + name + "." + joinPoint.getSignature().getName() + "()");
return joinPoint.proceed();
}
}
- @Aspect : 어노테이션을 이용해서 AOP 설정.
- @Around : 어노테이션으로 해당 기능이 실행될 시점, 즉 어드바이스를 정의.
어드바이스는 다섯 종류가 있지만 여기서는 대상 메서드를 실행 전후 또는 예외 발생 시점에 사용할 수 있는 Around 를 적용했다. - execution : 포인트컷 표현식으로, 적용할 메서드를 명시할 때 사용.
2. 적용결과 확인

AOP 를 이용해서 공통적으로 적용할 로그 기능을 LoggerAspect 라는 외부 클래스에 정의하고, 애플리케이션의 실행 시점에 기능이 삽입되어서 빨간색으로 밑줄 친 부분에 로그가 추가되었다.
- AOP 주요 개념
1. 어드바이스
어드바이스는 관점의 구현체로 조인포인트에 삽입되어 동작하는 것을 의미.
시점에 따라 다섯 종류로 구분된다.
종류 | 어노테이션 | 설명 | ||||||||
Before Advice | @Before | 대상 메서드가 실행되기 전에 적용할 어드바이스를 정의. | ||||||||
After returning | @AfterReturning | 대상 메서드가 성공적으로 실행되고 결괏값을 반환한 후 적용할 어드바이스를 정의. | ||||||||
After throwing Advice | @AfterThrowing | 대상 메서드에서 예외가 발생했을 때 적용할 어드바이스를 정의. try/catch 의 catch와 비슷한 역할. |
||||||||
After Advice | @After | 대상 메서드의 정상적인 수행 여부와 상관없이 무조건 실행되는 어드바이스를 정의. 즉 예외가 발생하더라도 실행되기 때문에 자바의 finally 와 비슷한 역할. | ||||||||
Around Advice | @Around | 대상 메서드의 호출 전후, 예외 발생 등 모든 시점에 적용할 수 있는 어드바이스. 가장 범용적으로 사용할 수 있다. |
2. 포인트컷
어드바이스를 적용할 조인포인트를 선별하는 과정이나 그 기능을 정의한 모듈.
정규표현식이나 AspectJ 의 문법을 이용해서 어떤 조인포인트를 사용할 것인지 결정.
- execution
- 가장 대표적이고 강력한 지시자로 접근 제어자, 리턴타입, 타입패턴, 메서드, 파라미터 타입, 예외 타입 등을 조합해서 가장 정교한 포인트컷을 만들 수 있다.
- * : 모든 값을 의미
- .. : 파라미터, 메서드, 패키지 등 0개 이상을 의미
예시
execution(void select*(..)) // 1번
execution(* com.example.controller.*()) // 2번
execution(* com.example.controller.*(..)) // 3번
execution(* com.example..select*(*)) // 4번
execution(* com.example..select*(*, *)) // 5번
- 1번 : 리턴 타입이 void이고, 메서드 이름이 select로 시작하고, 파라미터가 0개 이상인 메서드가 호출될 때
- 2번 : com.example.controller 패키지 밑에 파라미터가 없는 모든 메서드가 호출될 때
- 3번 : com.example.controller 패키지 밑에 파라미터가 0개 이상인 모든 메서드가 호출될 때
- 4번 : com.example 패키지의 모든 하위 패키지에 있는 select로 시작하고 파라미터가 한 개인 모든 메서드가 호출될 때
- 5번 : com.example 패키지의 모든 하위 패키지에 있는 select로 시작하고 파라미터가 두 개인 모든 메서드가 호출될 때
- within
- 특정 타입에 속하는 메서드를 포인트컷으로 설정.
예시
within(com.example.service.boardServiceImpl) // 1번
within(com.example.service.*ServiceImpl) // 2번
- 1번 : com.example.service 패키지 밑에 있는 boardServiceImpl 클래스의 메서드가 호출될 때
- 2번 : com.example.service 패키지 밑에 있는 ServiceImpl 이라는 이름으로 끝나는 메서드가 호출될 때
- bean
- 스프링의 빈 이름의 패턴으로 포인트컷을 설정.
예시
bean(boardServiceImpl) // 1번
bean(*ServiceImpl) // 2번
- 1번 : boardServiceImpl 이라는 이름을 가진 빈의 메서드가 호출될 때
- 2번 : ServiceImpl 이라는 이름으로 끝나는 빈의 메서드가 호출될 때
'Spring' 카테고리의 다른 글
[SpringBoot] - Mybatis 설정 (0) | 2023.10.15 |
---|---|
[SpringBoot] - @ControllerAdvice 를 이용한 전역 예외처리 (0) | 2023.10.15 |
[SpringBoot] - 인터셉터(Interceptor) (0) | 2023.10.15 |
[SpringBoot] -Logback 사용하기 - (Slf4j, log4jdbc, p6spy) (0) | 2023.10.13 |
[유튜브-메타코딩] - 나만의 블로그 만들기 - 13. 전형적인 방식의 로그인 방법 (0) | 2022.08.21 |