개발 무지렁이

[Spring Boot] 공통 관심사항을 모아놓고, 원하는 곳에 적용하는 AOP(Aspect Oriented Programming)와 이를 가능하게 하는 프록시 객체(가짜객체) 본문

Backend/스프링부트

[Spring Boot] 공통 관심사항을 모아놓고, 원하는 곳에 적용하는 AOP(Aspect Oriented Programming)와 이를 가능하게 하는 프록시 객체(가짜객체)

Gaejirang-e 2023. 9. 27. 19:28

📕 참고 자료 📕
Tistory's Card

𐂂 AOP (Aspect Oriented Programming)가 필요한 상황
시간을 측정하는 로직을 모든 메서드에 적용하려면
시간을 측정하는 로직핵심 관심사항(CORE CONCERN)은 아니지만
모든 메서드에 들어가야 할 공통 관심사항(CROSS-CUTTING CONCERN)이다.
공통 관심사항을 모아놓고 원하는 곳에 적용할 때, AOP가 필요하다.

🗝️ 원하는 적용대상(target)을 지정할 수 있다.
🗝️ 보통 패키지 레벨target을 설정한다.

📜 TimeTraceAop.java

  @Aspect
  @Component //Spring Bean으로 등록된다.
  public class TimeTraceAop {
      @Around("execution(* hello.hellospring..*(..))") //공통 관심사항(CROSS-CUTTING CONCERN) 타겟팅
      public Object execute(ProceedingJoinPoint joinPoint) throws Throwable {
          long start = System.currentTimeMillis();
          System.out.println("START: " + joinPoint.toString());
          try {
              return joinPoint.proceed();
          } finally {
              long finish = System.currentTimeMillis();
              long timeMs = finish - start;
              System.out.println("END: " + joinPoint.toString() + " " + timeMs + "ms");
          }
      }
  }
🦉 @Around
: 특정 메서드지정한 패턴에 맞는 메서드Advice를 적용하도록 타겟팅하는 역할을 한다.
execution 표현식을 사용하여 타겟팅메서드를 선택한다.

execution(접근제어자__패키지/클래스명__반환타입__메서드명__매개변수 타입과개수__예외타입)
⚠️ 접근제어자, 반환타입, 매개변수 타입과개수, 예외타입생략 가능하다. 생략하면 '어떤~든지 상관없이'는 뜻이다.
⚠️ *(와일드카드)는 '모든'을 의미한다.

@Around("execution(* hello.hellospring..*(..))")
어떤 접근제어자든지 상관없이 hello.hellospring라는 패키지와 하위패키지의 모든 클래스의 모든 메서드의
모든 매개변수에 대해서(타입 개수 상관x) Advice를 적용하도록 타겟팅하겠다.

🦉 ProceedingJoinPoint joinPoint
: Advice실행이 일시중단되고 핵심 관심사항(CORE CONCERN) 메서드가 실행된다.
핵심 관심사항(CORE CONCERN) 메서드완료되면 Advice 실행이 재개된다.
이를 통해 Advice 객체핵심 관심사항Wrapping하여, 부가적인 작업을 수행할 수 있게 된다.

𐁍 HelloController호출하는 건 진짜가 아닌 프록시 객체(가짜객체)다.

📜 HelloController.java

  package hello.hellospring.controller;

  @Controller
  public class HelloController {
      @Autowired
      public HelloController(HelloService helloService) {
          this.helloService = helloService;
          System.out.println("helloService: " + helloService.getClass()); //프록시 객체 찍어보기
      }
  }
  helloService: class hello.hellospring.service.HelloService$$EnhancerBySpringCGLIB$$84ab5f46
⚠️ CGLIB: 복제해서 코드를 조작하는 기술
⚠️ 이 기술이 가능한 것은 Spring Container가짜객체를 만들어서 주입해주기 때문이다.

📕 참고 자료 📕
Tistory's Card

Comments