BeanFactory와 Application Context 빈 로딩시점의 차이

강상우·2021년 7월 17일
0

Spring

목록 보기
3/3
post-thumbnail

시작하며

IoC 컨테이너라고 하는 스프링 컨테이너는 DI의 관점에서는 빈 팩토리라고도 하고, 이런 빈 팩토리에 여러가지 기능을 추가한 것을 어플리케이션 컨텍스트라고 합니다.

일반적으로 스프링의 IoC 컨테이너는 애플리케이션 컨텍스트를 말하게 됩니다.

간단하게 인터페이스들의 관계를 살펴보면, 빈 팩토리의 기능을 대표하는 BeanFactory 인터페이스, 애플리케이션 컨텍스트의 기능을 대표하는 ApplicationContext 인터페이스가 있습니다.

위에서도 말한 것 처럼, 애플리케이션 컨텍스트는 빈 팩토리에 여러 기능을 추가한 것을 의미하기 때문에, 실질적인 인터페이스에서도 ApplicationContext 인터페이스는 BeanFactory 인터페이스를 상속받고 있습니다.

사진을 보면 ApplicationContext 인터페이스가 BeanFactory 인터페이스의 서브인터페이스인 ListableBeanFactory와 HierarhicalBeanFactory 인터페이스를 상속받고 있는 것을 알 수 있습니다.

결국 스프링 컨테이너(IoC 컨테이너)는 ApplicationContext 인터페이스를 구현한 클래스의 오브젝트가 됩니다.
(ex. Annotation 방식을 사용하는 IoC 컨테이너는 AnnotationConfigApplicationContext.class)

그렇다면, ApplicationContextBeanFactory 둘은 애플리케이션 컨텍스트가 기능을 확장했다는 거 외에는 다른 차이점이 없는 걸까요?

여러 차이점이 있겠지만, 이번 포스팅에서는 빈 로딩 시점의 차이에 대해 다뤄보려 합니다.

BeanFactory - Lazy loading

먼저 BeanFactory는 on-demand 방식, 즉 빈을 사용할 때 빈을 로딩시켜 줍니다.
반면, ApplicationContext는 실행 시 모든 빈을 로딩하게 됩니다.

테스트를 통해 알아보겠습니다.
테스트는 XML 빈 설정을 사용하였습니다.

먼저 빈으로 설정해줄 클래스를 만들어보겠습니다.

public class TestService {

  private static boolean isLoaded;

  public TestService() {
    isLoaded = true;
  }

  public static boolean isIsLoaded() {
    return isLoaded;
  }
}

TestService의 스태틱 변수를 통해 오브젝트가 생성되기 전과 생성되고 난 후의 값 변화를 구별해보겠습니다.

이제, xml 파일에 빈을 등록시켜 보겠습니다.

<bean id="testService" class="io.hala.springstudy.TestService"/>

BeanFactory를 사용하여 빈을 등록하는 테스트 코드를 작성해보겠습니다.

@Test
void beanfactoryTest() {
  DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
  XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
  reader.loadBeanDefinitions(new ClassPathResource("app-config.xml"));

  Assertions.assertFalse(TestService.isIsLoaded());

  TestService testService = (TestService) beanFactory.getBean("testService");
  Assertions.assertTrue(TestService.isIsLoaded());
}

참고로, XmlBeanFactory는 deprecated 되었기 때문에, 위와 같이 XmlBeanDefinitionReader를 통해 등록해야 합니다.

빈 팩토리는 초기화되었지만, TestService 오브젝트는 초기화되지 않은 것을 알 수 있습니다.
하지만 testService를 불러오는 순간 빈이 로딩되기 때문에 테스트가 통과됩니다.

즉, BeanFactory는 해당 빈이 필요할 때 로딩시켜주는 것을 알 수 있습니다.

ApplicationContext - Eager loading

애플리케이션 컨텍스트는 런타임 실행 시, 모든 빈을 로딩시키는 Eager loading 방식입니다.

@Test
void applicationContextTest() {
  ApplicationContext applicationContext = new ClassPathXmlApplicationContext("app-config.xml");

  Assertions.assertTrue(TestService.isIsLoaded());
}

위의 테스트 코드를 통해, ApplicationContext만 초기화했지만, TestService의 빈 역시 로딩되는 것을 알 수 있었습니다.

마무리

ApplicationContext 인터페이스를 구현한 컨테이너들은 실행 시점에 모든 빈을 로딩하기 때문에 무거운 컨테이너라고 이야기 합니다. 이 뿐만 아니라, BeanFactory에 비해 다양한 편의 기능들을 가지고 있으니 더 무거울 수 있겠죠!
반면, BeanFactory만을 구현한 컨테이너들은 DI 관점만 가지고 있고, 빈을 필요할 때 로딩해주기 때문에 가벼운 경량 컨테이너라고 이야기 합니다.

profile
https://sangwoo0727.github.io/ 기존 블로그 이전 중입니다.

0개의 댓글