헤르메스 LIFE

[Spring] ApplicationContext의 초기화 과정 본문

Spring Framework

[Spring] ApplicationContext의 초기화 과정

헤르메스의날개 2012. 5. 22. 10:36
728x90

원문 : http://jjaeko.tistory.com/19


지금 까지 Spring의 기본에 대해서 글을 썻습니다.
아마도 이 글은 지금까지의 글에 대한 증거(?)가 될 수도 있겠네요
ApplicationContext의 초기화 과정을 보면 이전 글들에서 다뤘던
LifeCycle, MessageSource, BeanPostProcess에 대한 증거들을 보실 수 있습니다.
워낙 잘 짜여진 소스라 그리 어렵진 않습니다.

ApplicationContext의 구현체중 하나인 ClassPathXmlApplicationContext을 생성 하면 아래의 마지막으로
실행되는 생성자는 다음과 같습니다.

  1. public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent)  
  2.            throws BeansException {  
  3.   
  4.        super(parent);  
  5.        this.configLocations = StringUtils.trimArrayElements(configLocations);  
  6.        if (refresh) {  
  7.            refresh();  
  8.        }  
  9. }  

refresh 인자가 false라면 초기화 하지 않을 것이고 초기화 되지 않은 상태에서 어떠한 요청을 하게 되면
IllegalStateException 가 던져 집니다. refresh 인자가 true일 경우 refresh() 메소드가 호출 됩니다.
refresh() 메소드에서 하는 일이 초기화의 전부 입니다. 

다음은 refresh() 메소드의 구현내용 입니다.
  1. public void refresh() throws BeansException, IllegalStateException {  
  2.        synchronized (this.startupShutdownMonitor) {  
  3.            prepareRefresh();  
  4.            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();  
  5.            prepareBeanFactory(beanFactory);  
  6.            try {  
  7.                postProcessBeanFactory(beanFactory);  
  8.                invokeBeanFactoryPostProcessors(beanFactory);  
  9.                registerBeanPostProcessors(beanFactory);  
  10.                initMessageSource();  
  11.                initApplicationEventMulticaster();  
  12.                initLifecycleDependentBeans();  
  13.                onRefresh();  
  14.                registerListeners();  
  15.                finishBeanFactoryInitialization(beanFactory);  
  16.                finishRefresh();  
  17.            }  
  18.            catch (BeansException ex) {  
  19.                beanFactory.destroySingletons();  
  20.                cancelRefresh(ex);  
  21.                throw ex;  
  22.            }  
  23.        }  
  24. }  

순서 대로 알아 보도록 하겠습니다.
prepareRefresh()
-멤버 필드인 active를 true로 설정 합니다. 활성화 됐다는 뜻이죠

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()
-내부에서 쓰이는 BeanFactory를 refresh 합니다.

prepareBeanFactory(beanFactory)
-beanFactory를 사용 가능한 상태로 준비 합니다. 이 메소드에서는 beanFactory에 PropertyEditor와
ClassLoader, BeanPostProcessor 들이 등록 되어 집니다.

postProcessBeanFactory(beanFactory)
-템플릿 메소드입니다. 자식 클래스의 재정의에 따라 행동이 변합니다.
ApplicationContext에서는 아무 작업을 하지 않습니다만 WebApplicationContext 에서는
Web Scope가 등록 되어 집니다.

invokeBeanFactoryPostProcessors(beanFactory)
-등록된 bean들 중에 BeanFactoryPostProcessor인 것을 찾아 생성하고 실행 합니다. 생성 순서는 XML에 정의된 순서 겠지만 메소드 호출은 PriorityOrdered, Ordered, Non-Ordered 순으로 수행 됩니다.

registerBeanPostProcessors(beanFactory)
-먼저 BeanPostProcessorChecker를 생성하여 beanFactory에 등록 합니다.
(BeanPostProcessorChecker가 하는 역할은 bean 생성시 로그 메세지를 출력하는 것입니다.)
이후에 등록된 bean들 중에 BeanPostProcessor인 것을 찾아 생성한 후 beanFactory에 등록 합니다.
등록 순서는 PriorityOrdered, Ordered, Non-Ordered 입니다.

initMessageSource()
-등록된 bean들 중에 id가 messageSource인 것을 찾아 생성한 후 MessageSource로 캐스팅 하여 내부 프로퍼티인 messageSource에 할당 합니다. 타입체크 없이 무조건 캐스팅 하므로 주의가 필요한 부분입니다.
만약 발견되지 않는다면 DelegatingMessageSource를 생성하여 할당 합니다.
(DelegatingMessageSource는 추측인데 단지 Message가 없는 위임용 객체 같습니다.)

initApplicationEventMulticaster()
-등록된 bean들 중에 id가 applicationEventMulticaster인 것을 찾아 생성한 후 ApplicationEventMulticaster로 캐스팅 하여 내부 프로퍼티인 applicationEventMulticaster에 할당 합니다.
이것 역시 타입체크없이 바로 캐스팅 하므로 주의가 필요 합니다. 만약 발견되지 않는다면
SimpleApplicationEventMulticaster를 생성하여 할당 합니다.

initLifecycleDependentBeans()
-등록된 bean들 중에 타입이 LifeCycle인 것을 찾아 해당 bean이 의존하는 다른 bean이 존재한다면
해당 bean과 의존하는 bean의 id를 묶은 의존성 정보를 등록 시킵니다. 이 부분은 잘 모르겠습니다.

onRefresh()
-템플릿 메소드입니다. 자식 클래스의 재정의에 따라 행동이 변합니다.
ApplicationContext에서는 아무 작업을 하지 않습니다만 WebApplicationContext에서는 themeSource를
설정 합니다.

registerListeners()
-등록된 bean들 중에 타입이 ApplicationListener인 것을 찾아 생성한 후 리스너로 등록 시킵니다.

finishBeanFactoryInitialization(beanFactory)
-지금 까지의 과정에서 포함되지 않은 일반적인 bean(Singleton, non-lazy-init)을 생성되고 의존성이 삽입 됩니다. 생성 과정에서 LifeCycle 인터페이스들을 구현 했다면 해당 메소드가 호출되고 등록된 BeanPostProcessor를 거치게 됩니다. Spring에는 기본적으로 ApplicationContextAwareProcessor가 등록 되어 있으므로 이곳도 거치게 됩니다.

finishRefresh()
-모든 과정이 끝났습니다. 마지막으로 위 과정에서 등록된 ApplicationListener들에게 초기화가 끝났다는 
신호인 ContextRefreshedEvent를 전파 합니다.

728x90