스프링 빈들의 생명 주기를 관리하고 IoC와 DI를 해주는 컨테이너
실제 코드에서의 스프링 컨테이너는 BeanFactory
또는 ApplicationContext
를 뜻 한다.
스프링 컨테이너의 근간이 되는 최상위 인터페이스로 getBean()과 같은 Bean을 조회하는 기본적인 메서드들이 정의되어 있다.
BeanFactory
를 상속받아 만든 인터페이스로 Bean을 조회하는 기능 이외에 추가적으로 부가 기능들을 제공한다.
부가 기능을 간단하게 살펴보자면
메시지 소스를 활용한 국제화 기능
- MessageSource를 상속받아 기능 구현
- 예를 들어, 접속하는 지역에 따라 언어를 다르게 출력할 수 있게 지원
환경변수
- EnvironmentCapable을 상속받아 기능 구현
- 로컬, 개발, 운영 등의 환경을 구분하여 처리할 수 있게 지원
애플리케이션 이벤트
- ApplicationEventPublisher를 상속받아 기능 구현
- 이벤트를 발행하고 구독하는 모델을 편리하게 지원
편리한 리소스 조회
- ResourceLoader를 상속받아 기능 구현
- 파일, 클래스패스, 외부 등에서 리소스를 편리하게 조회할 수 있도록 지원
ApplicationContext
가 제공하는 부가기능 때문에 BeanFactory
는 실제로 거의 사용하지 않는다.
앞서, 스프링 컨테이너가 곧 ApplicationContext
라고 했으므로 ApplicationContext
의 구현체를 생성하면 된다.
단, 생성할 때 설정 정보를 넘겨주어야 한다.
구현체로는 여러 가지가 있는데 그 중 주로 쓰이는 것은 두 가지 정도가 있다.
AnnotationConfigApplicationContext
자바 클래스 파일로 작성된 설정 정보를 받을 수 있다.
GenericXmlApplicationContext
XML 파일로 작성된 설정 정보를 받을 수 있다.
구현체 목록을 살펴보면 Groovy로 작성된 파일을 읽을 수 있는 구현체도 있는 등 꽤 많다.
스프링에 대한 이해도가 높다면 커스텀 클래스를 작성하여 원하는 형태의 파일을 설정 정보로 받을 수 있도록 구현하는 것도 가능해 보인다.
BeanDefinition
이라는 인터페이스가 그 역할을 해주고 있다.
다른 말로는 빈 설정 메타정보라고 한다.
각각의 Bean마다 하나씩 메타 정보가 생성된다.
AnnotaionConfigApplicationContext
내부 코드를 살펴보면 AnnotationBeanDefinitionReader
를 사용하고 있는데, 이 클래스가 설정 정보 파일을 읽고 BeanDefinition
을 생성한다.
다른 구현체에도 마찬가지로 이렇게 설정 정보 파일을 읽어들이는 Reader가 존재한다.
BeanDefinition
을 직접 생성해서 컨테이너에 등록할 수도 있지만 실무에서는 그럴 일이 거의 없기 때문에 깊은 이해보다는 어떠한 메커니즘으로 돌아가는 지에 대해 이해만 해도 충분하다.