[Spring] Spring에서 Bean은 어떤 자료구조로 관리될까요?
0. 들어가기 전에
영한님 강의를 듣다가 스프링 컨테이너가 어떻게 빈을 관리하는지 궁금해져서 찾아보게 되었습니다. 스프링 빈을 관리하는 개념인 IoC Container부터 설명하고, 어떤 자료구조를 사용하는지 알아보겠습니다.
1. IoC Container란?
순수 자바 객체(POJO)와 메타데이터들을 이용해 빈을 생성하고, 관리하는 컨테이너
IoC 컨테이너는 스프링 컨테이너라고도 불리며 빈의 생명주기를 관리하고, DI를 하는 역할을 맡고 있다.
DI 글에서 이야기했듯이 DI는 외부에서 의존성을 주입해 주는 것이다. 이 역할을 또 다른 말로 IoC(Inversion of Control)라고도 한다.
스프링 컨테이너는 Configuration Metadata(스프링 컨테이너가 구성 및 인스턴스화하게 하는 정보)와 자바 코드를 통해 빈을 생성한다.
스프링 컨테이너에 Metadata를 알려주는 방법은 다음의 3가지 방법이 있다.
- XML-based Configuration
- Java-based Configuration
- Annotation-based Configuration
사용하는 방법은 다른 글에서 설명하기로 하고, 흔히 알고 있는 스프링 컨테이너인 ApplicationContext에 대해서 알아보자.
2. ApplicationContext
ApplicationContext
는 BeanFactory
를 상속받은 인터페이스이다. BeanFactory
는 스프링 빈 컨테이너의 최상위에 위치하는 클래스이면서 빈을 구성하고 getBean()
를 통해 빈을 조회할 수 있다.
ApplicationContext
는 BeanFactory
를 상속받기 때문에 다형성으로 BeanFactory의 기능을 사용할 수 있다. 추가로 상속받는 인터페이스들이 많기 때문에 ResourceLoader
에서 리소스 조회 기능, MessageSource
에서 메시지 국제화 기능, ApplicationEventPublisher
에서 이벤트 관련 처리 기능, EnviromentCapable
에서 환경변수 관련 기능 등을 포함한다.
3. 스프링 컨테이너에서 Bean 관리 방법
스프링을 학습을 하는 사람들은 대부분 영한님의 강의를 들어보았을 것이고, 들을 예정일 것이다. 강의에서 보면 스프링은 아래와 같은 형식으로 빈을 관리한다고 했다.
'딱 봐도 Map처럼 관리할 것 같지 않나?'라는 생각이 들었다면 여러분의 생각이 맞다. 하지만 눈으로 직접 보고 싶어서 내부 구현을 찾아 보았다(빈 등록 과정은 너무 복잡해서 확인하지 못했다.).
일단 우리가 사용하는 @ComponentScan
을 사용하면, 스프링 컨테이너로 AnnotationConfigServletWebApplicationContext
구현체를 사용하게 된다.
public class AnnotationConfigServletWebApplicationContext extends GenericWebApplicationContext
implements AnnotationConfigRegistry {
// 매우 복잡한 구현
}
이 부모 객체에서 타고타고 올라가면 GenericApplicationContext
클래스가 나오게 되는데, 여기에서 DefaultListableBeanFactory
클래스를 인스턴스 변수로 가지고 있다.
public class GenericApplicationContext extends AbstractApplicationContext implements BeanDefinitionRegistry {
private final DefaultListableBeanFactory beanFactory;
// 매우 복잡한 구현
}
DefaultListableBeanFactory
를 뜯어보면 안에서 beanDefinitionMap
을 볼 수가 있다.
@SuppressWarnings("serial")
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory
implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
/** Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
}
스프링은 Multi-thread에 안전을 보장하기 위해 ConcurrentHashMap으로 bean을 관리한다는 것을 확인할 수 있다. 영한님이 설명해준 그림대로 빈 이름과 빈 정보를 맵으로 관리한다는 것을 확인할 수 있다.
4. 결론
Sprning은 빈을 관리하기 위해 ConcurrentHashMap
을 사용하고 있으며 key에는 빈 이름, value에는 빈 정보 객체를 담아두고 있다.
※ 참조
'FRAMEWORK > [SPRING]' 카테고리의 다른 글
[Spring] HandlerMethodArgumentResolver 동작 원리 (0) | 2023.05.07 |
---|---|
[Spring] DispatcherServlet이란? (0) | 2023.04.27 |
[Spring] Spring에서 DI하는 3가지 방법 (1) | 2023.04.21 |
[Spring] RestAssured로 API 테스트 진행하기 (1) | 2023.04.13 |
[Spring] Spring ArgumentResolver란? (0) | 2022.08.10 |