Spring/Spring Core Advanced

빈 후처리기

민철킹 2022. 1. 15. 16:45

빈 후처리기란?(BeanPostProcessor)

@Bean이나 컴포넌트 스캔으로 스프링 빈을 등록하면 스프링은 대상 객체를 생성하고 스프링 컨테이너 내부의 빈 저장소에 등록한다.

그 이후에는 등록된 빈을 조회하고 사용할 수 있게된다.

스프링이 빈 저장소에 등록할 목적으로 객체를 생성하는데(Singleton) 등록 직전에 조작하고 싶을 때 사용하는 것이 바로 빈 후처리기!!

즉, 빈을 생성한 후에 무언가를 처리하는 용도로 이해하자!

빈 후처리기 기능

  • 객체를 조작
  • 다른 객체로 바꿔치기

빈 후처리기 과정

  • 생성 : 스프링 빈 대상이 되는 객체를 생성
  • 전달 : 생성된 객체를 빈 후처리기에 전달
  • 후 처리 작업 : 빈 후처리기가 스프링 빈 객체를 조작
  • 등록 : 스프링 컨테이너의 내부 저장소에 빈 객체 등록

BeanPostProcessor 인터페이스

BeanPostProcessor 인터페이스는 스프링이 제공하는 것이다.

  • 빈 후처리기를 사용하려면 이 인터페이스를 구현하고 스프링 빈으로 등록시켜야한다.
  • 두개의 메소드가 존재하는데 javaDoc를 읽어봐도 알 수 있듯이 하나는 초기화 이전의 후처리기이고 다른 하나는 초기화 이후의 후처리기이다.
    • 여기 말하는 초기화는 객체 생성 이후를 의미한다.(쉽게 말해 @PostConstruct이전과 이후라고 생각하자!)

  • 먼저 BeanPostProcessor를 구현한 클래스를 하나 만들고 내부에서 postProcessAfterInitialization을 오버라이드하였다.
  • 스프링 빈이 생성된 후에 여기로 스프링 빈 객체가 전달될 것이다.
  • 그 때 빈 객체가 A의 인스턴스라면 B로 바꿔치기 해주는 간단한 코드이다.

  • @Configuration을 통해 빈을 등록하는데 beanA라는 빈 이름으로 A의 객체를 생성한다.
  • 앞서 만든 빈 후처리기 또한 스프링 빈으로 등록한다.
  • 우리가 만든 빈 후처리기에서 AB로 후킹했기 때문에 "beanA"라는 스프링 빈은 B타입일 것이다.
  • 만약 A로 빈을 조회한다면 일치하는 스프링 빈은 존재하지 않기 때문에 NoSuchBeanDefinitionException이 발생한다.

 

  • 결과를 살펴보면, 먼저 A타입의 beanA라는 스프링 빈이 싱글톤으로 생성된다.
  • 그 후, 빈 후처리기에 이 객체가 전달된다.
  • 빈 후처리기가 A타입의 스프링 빈을 B타입으로 후킹한다.

테스트 성공!!

 

 

빈 후처리기는 빈을 조작하고 변경할 수 있는 후킹 포인트!!

조작 : 해당 객체의 특정 메서드를 호출하는 것

컴포넌트 스캔의 대상이 되는 빈들을 조작할 방법이 없었는데 빈 후처리기를 사용하면 조작이 가능해진다.

 

빈 객체를 프록시로 교체하는 것도 가능하다는 의미이다!

 

@PostConstruct

@PostConstruct는 스프링 빈 생성 이후에 빈을 초기화하는 역할을 하는 애노테이션이다.

이것이 어떻게 동작할까?

이는 생성된 빈을 한번 조작해서 초기화하는 것인데 앞서 배운 빈 후처리기의 기능과 똑같지 않은가??

맞다. 스프링은 CommonAnnotationBeanPostProcessor라는 빈 후처리기를 자동으로 등록하는데 이것이 바로 @PostConstruct가 붙은 메소드를 호출하여 동작하게 된 것이다!!

 

 

빈 후처리기로 프록시 객체 적용

  • 지정된 패키지에 존재하는 빈 객체라면 프록시를 생성해 이를 반환해 실제 빈 객체로 등록해주는 후킹 작업을 하는 빈 후처리기이다.

이런 식으로 실제 스프링 컨테이너에 등록되는 빈 객체를 프록시 객체로 바꿔치기하여 등록할 수 있다.

 

 


 

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

먼저, gradle에 aop 의존성을 추가하자.

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

이는, aspectjweaver라는 aspectJ 관련 라이브러리를 등록하고, Spring BootAOP관련 클래스를 자동으로 스프링 빈에 등록한다.

 

 

AutoProxyCreator

  • 위에서 설정한 라이브러리를 통해 AnnotationAwareAspectJAutoProxyCreator라는 빈 후처리기가 스프링 빈에 자동 등록됨
  • 자동으로 프록시를 생성해주는 빈 후처리기
  • 스프링 빈으로 등록된 Advisor를 자동으로 찾아 프록시가 필요한 곳에 자동으로 프록시를 적용해줌
    • Advisor만 찾으면 Pointcut으로 어디에 적용할지 찾고 Advice를 적용

AutoProxyCreator 클래스 다이어그램

 

 

작동 과정

  1. 스프링이 스프링 빈의 대상 객체를 생성
  2. 생성된 객체를 빈 후처리기에 전달
  3. AutoProxyCreator가 스프링 컨테이너에서 모든 Advisor를 조회
  4. 조회된 AdvisorPointcut을 사용해 해당 객체가 프록시 적용 대상 유무를 판단
  5. 적용 대상이라면 프록시를 생성 및 반환하고 아니라면 그대로 반환
  6. 반환된 객체를 스프링 빈으로 등록

 


 

NameMatchMethodPointcut()은 매우 간편하지만 메서드 이름만으로 매칭하기 때문에 정밀하지 못하다.

 

 

AspectJExpressionPointcut

AspectJ라는 AOP에 특화된 표현식을 적용할 수 있다.

  • * : 모든 반환 타입
  • hello.proxy.app.. : 해당 패키지와 그 하위 패키지
  • *(..) : *모든 메서드, (..) 파라미터는 상관없음

 


 

만약, 하나의 스프링 빈이 여러 AdvisorPointcut에 해당된다면 그 개수만큼 프록시가 생성될까??

그렇지 않다! 프록시는 내부에 여러 개의 Advisor를 가질 수 있기 때문에 프록시는 하나만 생성한다.

반응형

'Spring > Spring Core Advanced' 카테고리의 다른 글

Spring AOP  (2) 2022.01.25
@Aspect AOP  (0) 2022.01.25
Spring의 프록시 기술  (0) 2021.12.16
동적 프록시 기술  (0) 2021.11.18
프록시 패턴과 데코레이터 패턴  (0) 2021.11.08