티스토리 뷰

빈 후처리기

빈 후처리기는 빈을 생성한 후에 무언가를 처리하는 용도로 사용하는데, 객체를 조작하거나, 다른 객체로 바꿔치기 하는 기능을 제공하므로 스프링이 생성한 객체를 빈 저장소에 등록하기 직전에 조작하고 싶다면 빈 후처리기를 사용하면 된다.


public interface BeanPostProcessor {
      Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
      Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException
  }

빈 후처리기를 사용하려면 BeanPostProcessor 인터페이스를 구현하고, 스프링 빈으로 등록하면 된다.


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

빈 후처리기 과정

스프링의 일반적인 빈 등록과정을 빈 후처리기와 함께 살펴보자.


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



빈 후처리기 적용해보기

A 클래스를 Bean으로 등록했지만, 빈 후처리기를 이용하여 B 클래스로 바꿔치기 해보자.


A.class

  @Slf4j
  static class A {

    public void helloA() {
      log.info("hello A");
    }

  }

B.class

  @Slf4j
  static class B {

    public void helloB() {
      log.info("hello B");
    }

  }

AToBPostProcessor.class

  @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;
    }
  }

A타입의 beanB 타입으로 바꾸기 위해 BeanPostProcessor를 구현하고, postProcessAfterInitialization 메서드를 Override하였다. A 대신 반환된 B가 스프링 컨테이너에 등록된다.


BeanPostProcessorConfig.class

  @Slf4j
  @Configuration
  static class BeanPostProcessorConfig {

    @Bean(name = "beanA")
    public A a() {
      return new A();
    }

    @Bean
    public AToBPostProcessor helloPostProcessor() {
      return new AToBPostProcessor();
    }
  }

BeanPostProcessorbean으로 등록하였다.


Test code

  @Test
  void basicTest() {
    ApplicationContext applicationContext = new AnnotationConfigApplicationContext(
        BeanPostProcessorConfig.class);

    // beanA 이름으로 B 객체가 빈으로 등록된다.
    B b = applicationContext.getBean("beanA", B.class);
    b.helloB();

    // A는 빈으로 등록되지 않는다.
    Assertions.assertThrows(NoSuchBeanDefinitionException.class,
        () -> applicationContext.getBean(A.class));
  }

결과

실행 결과를 보면 최종적으로 beanA라는 스프링 빈 이름에 A 객체 대신에 B 객체가 등록된 것을 확인할 수 있다. A는 스프링 빈으로 등록조차 되지 않았다.


일반적으로 스프링 컨테이너가 등록하는, 특히 컴포넌트 스캔의 대상이 되는 빈들은 중간에 조작할 방법이 없는데, 빈 후처리기를 사용하면 개발자가 등록하는 모든 빈을 중간에 조작할 수 있다. 이 말은 빈 객체를 프록시로 교체하는 것도 가능하다는 뜻이다. 다음 포스팅에서는 빈 후처리기를 사용해서 빈 객체를 프록시로 교체해보겠다.



Reference

김영한. 스프링 핵심 원리 - 고급편. 인프런.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B3%A0%EA%B8%89%ED%8E%B8#

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30
글 보관함