Springboot 빈 후처리기

25gStroy·2022년 3월 22일
0

Springboot

목록 보기
6/41

빈후처리기

@Bean이나 컨포넌트 스캔으로 스프링빈을 등록하면, 스프링은 대상객체를 생성하고 스프링 컨테이너 내부의 빈 저장소에 등록을 한다.
그리고 이후에는 스프링 컨테이너를 통해 등록한 스프링빈을 조회해서 사용하면 된다.

빈 후처리기 - BeanPostProcesser

스프링이 빈 저장소에 등록할 목적으로 생성한 객체를 빈 저장소에 등록하기 직전에 조작하고 싶다면 빈 후처리기를 사용하면 된다.
빈을 생성한 후에 무언가를 처리하는 용도로 사용한다.

빈 후처리기 기능

객체를 조작할 수도 있고 완전히 다른객체로 바꿔치기 하는것도 가능하다.

빈등록과정 and 빈후처리기

  1. 생성: 스프링 빈 대상이 되는 객체를 생성한다.
  2. 전달:생성된 객체를 빈 저장소에 등록하기 직전에 빈후처리기에 전달한다
  3. 후처리작업: 빈후처리기는 전달된 스프링 빈 객체를 조작하거나 다른 객체로 바꿔치기 할 수 있다.
  4. 등록: 빈후처리기는 빈을 반환한다. 전달 된 빈을 그대로 반환하면 해당 빈이 등록되고 바꿔치기 하면 다른 객체가 빈저장소에 등록된다.

사용 예시

A객체를 빈등록하고 빈후처리기에서 빈객체를 B객체로 바꿔치기를 해서 B객체를 등록시키도록한다.


 @Slf4j
    static class AToBPostProcessor implements BeanPostProcessor{
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            log.info("beanName={} bean={}",beanName,bean);
            if(bean instanceof A){
                return new B();
            }
            return bean;
        }
    }

해당 BeanPostProcessor을 스프링 빈으로 등록하기만하면 스프링컨테이너가 빈후처리로 인식하고 동작한다.

정리

빈 후처리기는 빈을 조작하고 변경할 수 있는 후킹 포인트이다.
이것은 빈 객체를 조작하거나 심지 다른 객체로 바꾸어 버릴 수 있을 정도로 막강하다.
여기서 조작이라는 것은 해당 객체의 특정 매서드를 호출하는 것을 뜻한다.
일반적으로 스프링 컨테이너가 등록하는 특히 컨포넌트 스캔의 대상이 되는 빈들을 중간에 조작할 방법이 없는데 빈후처리기를 사용하면
개발자가 등록하는 모든 빈을 중간에 조작할 수 있다.

@PostConstruct의 비밀

@PostConstruct는 스프링 빈 생성 이후에 빈을 초기화 하는 역할을 한다. 그런데 생각해보면
빈의 초기화 라는 것이 단순히 @PostConstruct이 붙은 초기화 메서드를 한번 호출만 하면된다.
쉽게 이야기 해서 생성된 빈을 한번 조작하는 것이다.
따라서 빈을 조작하는 행위를 하는 적절한 빈 후처리기가 있으면 될것같다.
스프링은 "CommonAnnotationBeanProcessor"라는 빈 후처리기를 자동으로 등록하는데 여기에서 @PostConstruct애노테이션이 붙은 메서드를 호출한다.
따라서 스프링 스스로도 스프링 내부에 기능을 확장하기 위해 빈 후처리기를 사용한다.

중요 포인트

프록시의 적용 대상 여부를 패키지를 기준으로 설정했지만 포인트컷을 사용하면 더 깔끔하게 할수 있을것같다.
포인트컷은 이미 클래스 . 메서드 단위의 필터 기능을 가지고 있기 때문에, 프록시 적용 대상 여부를 정밀하게 설정할 수 있다.
참고로 어드바이저는 포인트 컷을 가지고 있다. 따라서 어드바이저를 통해 포인트 컷을 확인할 수 있다.
스프링 AOP는 포인트컷을 사용해서 프록시 적용 대상여부를 체크한다.
포인트컷이 사용되는 곳
1. 프록시 적용 대상여부를 체크해서 꼭 필요한 곳에만 프록시를 적용한다
2. 프록시의 어떤 메서가 호출되었을때 어드바이스를 적용할 지 판단한다.

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

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

자동 프록시 생성기 -AutoProxyCreator

  • 스프링 부트 자동 설정으로 AnnotationAwareAspectAutoProxyCreator 라는 빈 후처리기가 스프링 빈에 자동으로 등록된다.
  • 이름 그대로 자동으로 프록시를 생성해주는 빈 후처리기다.
  • 이 빈 후처리기는 스프링 빈으로 등록된 "Advisor"들을 자동으로 찾아서 프록시가 필요한 곳에 자동으로 프록시를 적용해 준다.
  • Advisor안에는 pointcut과 advice가 이미 모두 포함되어 있다. 따라서 Advisor만 알고 있으면 그 안에는 Pointcut으로 어떤 스프링 빈에
    프록시를 적용해야 할지 알 수 있다. 그리고 Advice로 부가기능을 적용하면 된다.

AnnotationAwareAspectAutoProxyCreator는 @AspectJ와 관련된 AOP기능도 자동으로 찾아서 처리해 준다.
Advisor는 물론이고 @Aspect도 자동으로 인식해서 프록시를 만들고 AOP를 적용해 준다.

자동 프록시 생성기의 작동과정
1. 생성: 스프링이 스프링 빈 대상이 되는 개체 생성
2. 전달: 생성된 객체를 빈 저장소에 등록하기 직전에 빈 후처리기전달
3. 모든 Advisor빈 조회: 자동 프록시 생성기-빈 후처리기는 스프링 컨테이너에서 모든 Advisor를 조회한다.
4. 프록시 적용 대상 체크 : 앞서 조회한 Advisor에 포함되어 있는 포인트컷을 사용해서 해당 객체가 프록시를 적용할 대상인지
아닌지 판단한다. 이때 객체의 클래스 정보는 물론이고 해당 객체의 모든 메서드를 포인트컷 하나하나 모두 매칭해 본다. 그래서 조건이 하나라도 만족하면
프록시 적용 대상이된다. 예를 들어 10개중에 하나만 만족돼도 프록시 적용대상이 되는것
5. 프록시 생성 프록시 적용 대상이면 프록시를 생성하고 반환해서 프록시를 스프링 빈으로 등록한다.
6. 빈등록 : 반환된 객체는 스프링빈으로 등록된다.

사용 예제는 간단하다

    @Bean
    public Advisor getAdvisor(LogTrace logTrace) {
        //poincut
        NameMatchMethodPointcut pointcut = new NameMatchMethodPointcut();
        pointcut.setMappedNames("request*" , "order*","save*");
        LogTraceAdvice advice = new LogTraceAdvice(logTrace);
        return new DefaultPointcutAdvisor(pointcut,advice);
    }

위와 같이 Advisor만 빈에 등록되면 내부적으로 자동으로 작동된다.

포인트컷은 2가지에 사용된다.

  1. 프록시 적용여부 판단. -> 생성단계
  • 모든 메서드를 체크해서 조건에 맞는것이 하나라도 있으면 프록시 생성 하나도 없으면 원본객체 등록
  1. 어드바이스 적용 여부 판단 -> 사용단계
  • 프록시가 호출됐을때 부가 기능인 어드바이스를 적용할지 말지 포인트컷을 보고 판단해야한다.

AspectJExpressionPointcut

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

profile
애기 개발자

0개의 댓글