빈 후처리기란?(BeanPostProcessor)
@Bean
이나 컴포넌트 스캔으로 스프링 빈을 등록하면 스프링은 대상 객체를 생성하고 스프링 컨테이너 내부의 빈 저장소에 등록한다.
그 이후에는 등록된 빈을 조회하고 사용할 수 있게된다.
스프링이 빈 저장소에 등록할 목적으로 객체를 생성하는데(Singleton) 등록 직전에 조작하고 싶을 때 사용하는 것이 바로 빈 후처리기!!
즉, 빈을 생성한 후에 무언가를 처리하는 용도로 이해하자!
빈 후처리기 기능
- 객체를 조작
- 다른 객체로 바꿔치기
빈 후처리기 과정
- 생성 : 스프링 빈 대상이 되는 객체를 생성
- 전달 : 생성된 객체를 빈 후처리기에 전달
- 후 처리 작업 : 빈 후처리기가 스프링 빈 객체를 조작
- 등록 : 스프링 컨테이너의 내부 저장소에 빈 객체 등록
BeanPostProcessor 인터페이스
BeanPostProcessor
인터페이스는 스프링이 제공하는 것이다.
- 빈 후처리기를 사용하려면 이 인터페이스를 구현하고 스프링 빈으로 등록시켜야한다.
- 두개의 메소드가 존재하는데
javaDoc
를 읽어봐도 알 수 있듯이 하나는 초기화 이전의 후처리기이고 다른 하나는 초기화 이후의 후처리기이다.- 여기 말하는 초기화는 객체 생성 이후를 의미한다.(쉽게 말해
@PostConstruct
이전과 이후라고 생각하자!)
- 여기 말하는 초기화는 객체 생성 이후를 의미한다.(쉽게 말해
- 먼저
BeanPostProcessor
를 구현한 클래스를 하나 만들고 내부에서postProcessAfterInitialization
을 오버라이드하였다. - 스프링 빈이 생성된 후에 여기로 스프링 빈 객체가 전달될 것이다.
- 그 때 빈 객체가 A의 인스턴스라면 B로 바꿔치기 해주는 간단한 코드이다.
@Configuration
을 통해 빈을 등록하는데beanA
라는 빈 이름으로 A의 객체를 생성한다.- 앞서 만든 빈 후처리기 또한 스프링 빈으로 등록한다.
- 우리가 만든 빈 후처리기에서
A
를B
로 후킹했기 때문에 "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 Boot
가 AOP
관련 클래스를 자동으로 스프링 빈에 등록한다.
AutoProxyCreator
- 위에서 설정한 라이브러리를 통해
AnnotationAwareAspectJAutoProxyCreator
라는 빈 후처리기가 스프링 빈에 자동 등록됨 - 자동으로 프록시를 생성해주는 빈 후처리기
- 스프링 빈으로 등록된
Advisor
를 자동으로 찾아 프록시가 필요한 곳에 자동으로 프록시를 적용해줌Advisor
만 찾으면Pointcut
으로 어디에 적용할지 찾고Advice
를 적용
작동 과정
- 스프링이 스프링 빈의 대상 객체를 생성
- 생성된 객체를 빈 후처리기에 전달
- AutoProxyCreator가 스프링 컨테이너에서 모든
Advisor
를 조회 - 조회된
Advisor
의Pointcut
을 사용해 해당 객체가 프록시 적용 대상 유무를 판단 - 적용 대상이라면 프록시를 생성 및 반환하고 아니라면 그대로 반환
- 반환된 객체를 스프링 빈으로 등록
NameMatchMethodPointcut()
은 매우 간편하지만 메서드 이름만으로 매칭하기 때문에 정밀하지 못하다.
AspectJExpressionPointcut
AspectJ
라는 AOP
에 특화된 표현식을 적용할 수 있다.
*
: 모든 반환 타입hello.proxy.app..
: 해당 패키지와 그 하위 패키지*(..)
:*
모든 메서드,(..)
파라미터는 상관없음
만약, 하나의 스프링 빈이 여러 Advisor
의 Pointcut
에 해당된다면 그 개수만큼 프록시가 생성될까??
그렇지 않다! 프록시는 내부에 여러 개의 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 |