AOP V2

Shaun·2024년 6월 16일
1

aop

목록 보기
3/4
post-thumbnail

빈 후처리기

  • 일반적으로 스프링은 스프링 빈으로 등록된 객체를 생성하고 스프링 컨테이너 내부의 빈 저장소에 등록한다. 그 이후에는 여기서 가져다가 사용함.

  • 빈후처리기는 스프링이 빈 저장소에 등록할 목적으로 생성한 객체를 빈 저장소에 등록하기전에 조작할때 사용
  • 빈 후처리기를 사용하려면 BeanPostProcessor 인터페이스를 구현하고, 스프링 빈으로 등록하면 된다.

  • postProcessBeforeInitialization : 객체 생성 이후에 @PostConstruct 같은 초기화가 발생하기
    전에 호출되는 포스트 프로세서이다.
  • postProcessAfterInitialization : 객체 생성 이후에 @PostConstruct 같은 초기화가 발생한 다음
    에 호출되는 포스트 프로세서이다.

  • 이런식으로 빈 조작 가능

@PostCOnstruct

  • 스프링 빈 생성 이후에 초기화 하는 역활(한번만 호출)

  • 스프링은 CommonAnnotationBeanPostProcessor 라는 빈 후처리기를 자동으로 등록하는데 여기서 @PostConstruct이 붙은 메서드 호출함. 스프링 스스로도 스프링 내부의 기능을 확장하기위해 빈 후처리기 사용

빈 후처리기 적용


  • 빈 후처리기를 통해 원본 빈 객체를 프록시 객체로 변환 -> 스프링 컨테이너에는 원본 객체 대신에 프록시가 등록이 된다

  • 프록시 타겟만 프록시를 빈으로 등록함(basePackage) 그렇지 않으면 스프링의 모든 빈들이 빈 후처리기에 들어와서 프록시 빈 등록이 된다.

- 빈 후처리기는 따로 빈 등록해줘야함!

스프링이 제공하는 빈 후처리기

자등 프록시 생성기

implementation 'org.springframework.boot:spring-boot-starter-aop'

  • aspectjweaver 라는 aspectJ 관련 라이브러리를 등록

  • AnnotationAwareAspectJAutoProxyCreator 라는 빈 후처리기가 스프링 빈에 자동 등록

  • 빈 후처리기는 스프링 빈으로 등록된 Advisor 들을 자동으로 찾아서 프록시가 필요한 곳에 자동으로 프록시 를 적용해준다. 왜냐 어드바이저는 이미 포인트컷이 존재하기 때문에 어디에 프록시를 적용해야할지 암

자동 프록시 생성기 과정

  • 빈 후처리기에서 스프링 컨테이너에서 모든 어드바이저를 조회한다

  • 모든 어드바이저에 있는 포인트컷을 조사해 프록시 대상여부를 판단함. 이때 해당 객체의 클래스 정보, 메서드를 포인트컷에 하나하나 모두 매칭해봄

  • 프록시 적용 대상이면 프록시를 생성하고 반환해서 프록시를 스프링 빈으로 등록 한다. 만약 프록 시 적용 대상이 아니라면 원본 객체를 반환해서 원본 객체를 스프링 빈으로 등록한다.

  • 등록된 프록시 내부에는 어드바이저실제 호출해야할 대상 target이 있다.

포인트컷

  1. 프록시 적용 대상 여부를 체크해서 꼭 필요한 곳에만 프록시를 적용한다.(빈후처리기-자동프록시생성)
  2. 프록시의 어떤 메서드가 호출 되었을 때 어드바이스를 적용할 지 판단한다. (프록시 내부)
  3. 클래스, 메스드 조건을 모두 비교한다. 여기서 하나의 메서드라도 대상이되면 프록시 생성

-> 프록시 대상이면 프록시 -> 어드바이스 호출 -> 타겟
-> 프록시 대상이 아니면 -> 어드바이스 호출x ->타겟

  • AspectJExpressionPointcut을 활용한 포인트컷 범위 설정

하나의 프록시 + MutliAdvisor


  • 기존처럼 어드바이저안에 있는 포인트컷을 만족할 경우 프록시하나에 여러 어드바이저를 생성한다.

@Aspect AOP

  • 어드바이저만 만들면 스프링 빈 후처리기가 알아서 프록시 생성해서 빈으로 등록해 준다.

  • @Aspect를 사용해서 어드바이저를 쉽게 만들 수 있다.

  • 실제로는 자동 빈 후처리기가 @Aspect를 찾아서 어드바이저로 만들어줌

  • @Around 의 값에 포인트컷 AspectJ표현식을 넣는다.

  • @Around : 포인트컷 + 공통로직(프록시로직) = 어드바이스

  • ProceedingJoinPoint : 어드바이스에서 살펴본 MethodInvocation invocation 과 유 사한 기능이다. 내부에 실제 호출 대상, 전달 인자, 그리고 어떤 객체와 어떤 메서드가 호출되었는지 정보가 포함
    되어 있다.

  • @Aspect가 있어도 스프링 빈으로 등록을 해줘야 한다.

@Aspect 적용 flow

  • 자동 프록시 생성기(빈 후처리기)는 스프링 컨테이너에서 @Aspect 애노테이션이 붙은 스프링 빈을 모두 조회한다.

  • 그 이후에, @Aspect 어드바이저 빌더를 통해 @Aspect 애노테이션 정보를 기반으로 어드바이저 생성

@Aspect 어드바이저 빌더

  • BeanFactoryAspectJAdvisorsBuilder 클래스이다. @Aspect 의 정보를 기반으로 포인트컷, 어드바이스, 어드바이저를 생성하고 보관하는 것을 담당한다.
  • @Aspect 의 정보를 기반으로 어드바이저를 만들고, @Aspect 어드 바이저 빌더 내부 저장소에 캐시한다. 캐시에 어드바이저가 이미 만들어져 있는 경우 캐시에 저장된 어드바이저를 반환 한다.

  • 스프링 컨테이너에서 어드바이저 빈 을 모두 조회한다

  • @Aspect 어드바이저 빌더 내부에 저장된 어드바이저 모두 조회한다. 이때 안에 있는 포인트컷으로 프록시 적용대상 여부 판단

  • 적용대상이면 프록시 빈 등록 아니면 그대로 빈 등록

AOP

  • 부가 기능은 보통 여러 클래스에 걸쳐서 함께 사용된다. 이런 부가 기능은 횡단관심사(cross-cutting concerns)가 된다.

  • 애플리케이션 로직은 크게 핵심 기능부가 기능으로 나눌 수 있다.

  • 애플리케이션을 바라보는 관점을 하나하나의 기능에서 횡단 관심사 관점으로 달리 보자라는 마인드로 프로그래밍을 보는 방식을 관점지향 프로그래밍 AOP라 한다.

  • AOP는 OOP를 대체하기 위한것이 아니라 횡단 관심사를 깔끔하게 처리하기 어려운 OOP의 부족한 부분을 보조하는 목적으러 개발 됬다.

AOP 적용방식

컴파일 시점

  • .java 소스 코드를 컴파일러를 사용해서 .class 를 만드는 시점에 부가 기능 로직을 추가할 수 있다. 이때는 AspectJ가 제공하는 특별한 컴파일러를 사용해야 한다.

  • 실제 대상 코드에 애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.

  • 이렇게 원본 로직에 부가 기능 로직이 추가되는 것을 위빙 이라 한다.

클래스 로딩 시점

  • .class 파일을 JVM 내부의 클래스 로더에 저장하기전에 조작한다.

  • 실제 대상 코드애스팩트를 통한 부가 기능 호출 코드가 포함된다. AspectJ를 직접 사용해야 한다.

런타임 시점(프록시)

  • 실제 대상 코드는 그대로 유지된다. 대신에 프록시를 통해 부가 기능이 적용된다. 따라서 항상 프록 시를 통해야 부가 기능을 사용할 수 있다. 스프링 AOP는 이 방식을 사용한다

AOP 적용 위치

  • 생성자, 필드 값 접근, static 메서드 접근, 메서드 실행 -> 이렇게 AOP를 적용할 수 있는 지점을 조인 포인트라 한다.
  • 프록시 방식을 사용하는 스프링 AOP의 조인 포인트는 메서드 실행으로 제한된다.
  • 프록시 방식을 사용하는 스프링 AOP는 스프링 컨테이너가 관리할 수 있는 스프링 빈에만 AOP를 적용할 수 있다.

결론

  • 스프링은 AspectJ의 문법을 차용하고 프록시 방식의 AOP를 적용한다. AspectJ를 직접 사용하는 것이 아니다.

  • AOP 프록시는 기능을 구현하기 위해 만든 프록시 객체, 스프링에서 AOP 프록시는 JDK 동적 프록시 또는 CGLIB 프록시이다.

profile
호주쉐프에서 개발자까지..

0개의 댓글