💬 AOP(Aspect oriented Programming, 관점지향 프로그래밍)
- 프로그램에서 핵심 로직과 부수 로직(DB 연결, 로깅, 파일 입출력 등)을 분리해 모듈화하는 방식
- 그림 1을 통해 설명하자면, 각각의 클래스에서 공통된 기능(X,Y,Z)를 가질 때 핵심 로직(A,B,C)과 부수 로직(X,Y,Z)으로 분리하는 것을 말한다.
✅ 목적 및 장점
- 중복 코드 제거
- 효율적 유지보수
- 높은 생산성
- 재활용성 극대화
- 변화 수용 용이
✅ 용어 정리
- JointPoint
- 애플리케이션을 실행할 때 특정 작업이 실행되는 시점
- Advice가 적용될 위치( method 진입 지점, 생성자 호출 시점) 등
- Advice
- JointPoint에서 실행되어야 하는 코드
- 부수 로직(X,Y,Z)에 해당
- Target
- 실질적 비지니스 로직(A,B,C)를 구현하고 있는 코드
- Pointcut
- Target 클래스와 Advice가 결합(Weaving)될 때 둘 사이의 결합 규칙을 정의
- 예) Advice가 실행된 Target의 특정 메소드를 지정
- Aspect
- Advice+Pointcut
- 일정한 패턴을 가지는 클래스에 Advice를 적용할 수 있도록 지원
- Weaving
- Jointpoint들을 Advice로 감싸는 과정
✅ 특징
Proxy
- Aspect의 적용 대상(Target)이 되는 객체에 대한 Proxy를 만들어 제공
- 대상 객체(Target)을 사용하는 코드는 대상객체(Target)을 Proxy를 통해 간접적으로 접근
- Proxy는 공통 기능(Advice)를 실행한 뒤 대상 객체(Traget)의 실제 메서드 호출하거나 대상 객체(Target)의 실제 메소드가 호출된 뒤 공통 기능(advice)를 실행
✅ 포인트컷
지시자(Pointcut designators, PCD)의 종류
- execution : 가장 정교한 포인트컷 구현 가능.
- within : 타입패턴 내에 해당하는 모든 것들을 포인트컷
- bean : bean 이름으로 포인트컷
execution을 활용한 표현식
execution(modifiers-pattern? ret-type-pattern declaring-type-pattern.?name-pattern(param-patten) throws-pattern?)
- modifiers-pattern : 접근 제어자(public, private), 생략 가능
- ret-type-pattern : 리턴 타입 지정
- declaring-type-pattern : 선언 타입, 생략 가능
- name-pattern : 메서드 지정
- param-patten : 매개변수 지정
- throws-pattern : 예외 패턴, 생략 가능
정리하자면 다음과 같다.
public java.lang.String hello.advanced.aop.member.MemberServiceImpl.hello(java.lang.String)
1️⃣ 리턴 타입 지정
표현식 | 설명 |
* | 모든 타입 허용 |
void | 리턴타입이 void인 메소드 |
!void | 리턴타입이 void 아닌 메소드 |
2️⃣ 패키지 지정
표현식 | 설명 |
com.example.demo.service | 정확한 패키지 선택 |
void com.example.demo.service.. | void com.example.demo.service로 시작하는 모든 패키지 선택 |
3️⃣ 클래스 지정
표현식 | 설명 |
UserCheck | 정확한 클래스만 선택 |
*AB | 이름이 AB로 끝나는 클래스만 선택 |
BaseObject+ | 클래스 이름 뒤 + : 해당 클래스로부터 파생된 모든 자식 클래스 선택 인터페이스 이름 뒤 + : 해당 인터페이스 구현한 모든 클래스 선택 |
4️⃣ 메소드 지정
표현식 | 설명 |
*(..) | 모든 메소드 선택 |
update*(..) | 메소드 명이 update로 시작하는 모든 메소드 선택 |
5️⃣ 매개변수 지정
표현식 | 설명 |
(..) | 모든 매개변수 |
(*) | 반드시 1개의 매개변수를 가지는 메소드만 선택 |
(com.example.demo.service.User) | 매개변수로 User을 가지는 메소드만 선택, 꼭 전체 패키지명 기재 |
(!com.example.demo.service.User) | 매개변수로 User을 가지지 않는 메소드만 선택 |
(Integer, ..) | 한 개 이상의 매개변수 + 첫 번째 매개변수의 타입이 Integer인 메소드만 선택 |
(Integer,*) | 반드시 두 개의 매개변수 + 첫 번째 매개변수의 타입이 Integer인 메소드만 선택 |
예시
1️⃣ set으로 시작하는 모든 메서드
execution(* set*(..))
2️⃣ com.example.demo.service 패키지 안의 모든 클래스의 모든 메서드
execution(* com.example.demo.service.*.*(..))
3️⃣ 모든 public 메서드
execution(public * *(..))
4️⃣ 첫 번째 파라미터가 String인 모든 메서드
execution(* *.*(String, ..))
✅ 어드바이스
- Before
- jointPoint 이전에 실행되며, 예외가 발생하는 경우를 제외하고 항상 실행
- After
- jointPoint에서 처리가 완료된 후 실행. 예외 발생•정상종료 여부와 관계 없이 항상 실행
- After Returning
- jointPoint가 정상적으로 종료한 후에 실행. 예외 발생시에만 실행
- After Throwing
- JointPoint에서 처리가 완료된 후 실행. 예외 발생•정상종료 여부와 관계 없이 항상 실행
- Around
- JointPoint 전후에 실행
참고
'🏕 멋사 Java 백엔드 13기 > TIL' 카테고리의 다른 글
250218 TIL | 상속 매핑 전략과 임베디드 타입 (0) | 2025.02.18 |
---|---|
250205 TIL | 람다식 (1) | 2025.02.05 |
240117 TIL : DI (1) | 2025.01.17 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 241231 백엔드 Java 부트캠프 21일차 (2) | 2024.12.31 |
[멋쟁이사자처럼 부트캠프 TIL 회고] 백엔드 Java 부트캠프 12일차 | DB (2) | 2024.12.17 |