본문 바로가기
Java Web/Spring Boot

[Spring Boot] AOP (관점 지향 프로그래밍) ★

by 스응 2023. 4. 11.
728x90
728x90

AOP (Aspect Oriented Programming)

  - 프로그램을 구성하는 여러 모듈에서 공통적으로 사용하는 코드를 분리함

      → 재사용성 & 유지보수성 향상

  - 프로그램의 여러 지점에서 반복적으로 사용되는 기능을 모듈화함

      → 코드 중복 감소 & 코드 가독성 향상

  - 핵심적인 코드와 부가적인 코드(방어적 코드 등)를 분리함

      : 핵심 기능에 영향을 미치지 않으면서, 부가적인 기능을 제공할 수 있음

       → 횡단 관심사를 핵심 관심사와 분리하여 구현하는 기법

  - OOP (객체 지향 프로그래밍)의 보완(보조)적인 개념

 

#  AOP 라이브러리 추가하기 (Gradle 빌드)

  1. build.gradle 파일에 명시

 

1
2
3
4
5
dependencies {            // 그룹 아이디     :     아티팩트 아이디
    implementation 'org.springframework.boot:spring-boot-starter-aop' // AOP
 
    ... // 나머지
}
cs

 

  2. build.gradle 파일 내 아무 곳이나 우클릭해서 메뉴 → [Gradle] → [Refresh Gradle Project] 클릭

 

 


관련 어노테이션

  @Aspect   - AOP 클래스로 설정함 (클래스 상단부에 지정)
  @Pointcut("execution표현식")   - AOP를 적용시킬 지점을 설정함 (지켜볼 클래스들을 지정함)
  - JoinPoint가 적용되는 대상 메서드
     (포인트컷은 여러 개의 JoinPoint를 묶은 집합)
  @Before("Pointcut메서드")   - AOP 메서드가 실행되는 지점 이전에 호출
  @After   - AOP 메서드가 실행되는 지점 이후에 호출
  @AfterReturning(value = "Pointcut메서드"
                                  , returning = "리턴타입")
  - AOP 메서드의 호출이 정상일 때 실행

#  조인포인트 (JoinPoint)

  - 특정 메서드가 호출되는 시점

 

#  execution 표현식

1
execution([접근제한자_패턴] [리턴타입_패턴] [패키지_패턴] [클래스명_패턴].[메서드명_패턴]([파라미터_패턴]))
cs

 

* .. + (..)
0개 이상의 문자 0개 이상의 하위 패키지 서브 타입 파라미터가 0개 이상인 메서드

 

1
2
3
// 예시
execution(* com.example.demo.controller.*.*(..))
// == com.examplem.demo.controller 패키지에 있는 모든 클래스의 모든 메서드 
cs

 

 


예제 코드

더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Aspect // AOP 클래스로 설정
@Component // IoC의 관리 대상으로 지정 (싱글톤으로 BEAN 객체가 됨)
public class AopParameter {
    
    // 포인트 컷
    // 모든 접근 제어자, ~.controller 아래의 모든 클래스의 모든 메서드를 지켜봄
    @Pointcut("execution(* com.example.demo4.controller..*.*(..))")
    private void cut() {
        
    }
    
    // controller 패키지 내의 BEAN 객체들을 지켜보고 있다가,
    // controller가 실행되면 before 메서드를 먼저 실행한 후에
    // controller 메서드를 실행함
    
    // cut() 메서드가 실행되는 지점 이전에 before() 메서드를 실행 (before() -> cut())
    @Before("cut()")  
    public void before(JoinPoint joinPoint) {
        
        // controller -> /api/get 호출하기 전에 수행됨
        
        // 어떤 메서드(get, post, put, delete)가 수행되었는지 알아보는 방법
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        
        System.out.println("사용된 method 확인");
        System.out.println("method : " + method.getName());
        
        // 매개변수 확인
        Object[] args = joinPoint.getArgs();
        for (Object obj : args) {
            // 매개변수 타입
            System.out.println("type : " + obj.getClass().getSimpleName()); // 리플렉션 기법 (getClass)
            // 매개변수 값
            System.out.println("value : " + obj);
        }
    }
    
    // value : cut() 메서드를 돌릴 때  // returning : 리턴 타입
    @AfterReturning(value = "cut()", returning = "obj")
    public void afterReturn(JoinPoint joinPoint, Object obj) {
        System.out.println("==============");
        System.out.println("return obj");
        System.out.println("obj " + obj);
    }
    
}
cs

 

320x100
반응형

댓글