나만보는페이지

[Spring] ApplicationContext refresh 과정 본문

spring

[Spring] ApplicationContext refresh 과정

pplenty 2020. 3. 24. 22:23

boot-2.1.3(spring 5.1.5) 기준으로 작성하였다.
스프링부트에서는 어플리케이션 타입에(Servlet/Reactive) 따라 다른 applicationContext 구현체 를 만든다.
아래 내용은 Servlet 타입 기준으로 작성하였다.
타입에따른구현체

ApplicationContext refresh()

Spring 의 ApplicationContext 가 refresh 될 때, 어떤 과정을 거치는지 알아보자.
refresh() 는 ConfigurableApplicationContext 인터페이스의 함수이다. BeanFactory 의 초기화가 이 부분에서 진행되고, Bean 이 등록되는 과정 등이 포함되어 있다.
함수 주석을 보면, XML 파일, 프로퍼티 파일 관계형 DB 등의 설정을 갱신 또는 불러오는 함수라고 설명 되어있다.

Load or refresh the persistent representation of the configuration,
which might an XML file, properties file, or relational database schema.

AbstractApplicationContext refresh()

주석을 유심히 살펴보자.

public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing. 
        prepareRefresh(); //...........................................................(1)

        // Tell the subclass to refresh the internal bean factory.
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); //.....(2)

        // Prepare the bean factory for use in this context.
        prepareBeanFactory(beanFactory); //............................................(3)

        try {
            // Allows post-processing of the bean factory in context subclasses.
            postProcessBeanFactory(beanFactory); //....................................(4)

            // Invoke factory processors registered as beans in the context.
            invokeBeanFactoryPostProcessors(beanFactory); //...........................(5)

            // Register bean processors that intercept bean creation.
            registerBeanPostProcessors(beanFactory); //................................(6)

            // Initialize message source for this context.
            initMessageSource(); //....................................................(7)

            // Initialize event multicaster for this context.
            initApplicationEventMulticaster(); //......................................(8)

            // Initialize other special beans in specific context subclasses.
            onRefresh(); //............................................................(9)

            // Check for listener beans and register them.
            registerListeners(); //....................................................(10)

            // Instantiate all remaining (non-lazy-init) singletons.
            finishBeanFactoryInitialization(beanFactory); //...........................(11)

            // Last step: publish corresponding event.
            finishRefresh(); //........................................................(12)
        }

        catch (BeansException ex) {
            // ...

        }

        finally {
            // ...
        }
    }
}

(1) prepareRefresh()

  • context 를 refresh 하기 위한 준비.
  • 현재 시간을 기록하고, context 의 상태 값을 true 로 수정한다.
  • 구현체에 따라 빈 정의 스캐너의 캐시를 초기화 하기도 한다.

prepareRefresh

(2) obtainFreshBeanFactory()

  • 빈 팩토리를 준비한다.
  • GenericApplicationContext 기준, 생성자에서 직접 new DefaultListableBeanFactory() 빈 팩토리를 생성한다.

obtainFreshBeanFactory

(3) prepareBeanFactory(beanFactory)

  • 클래스로더를 세팅하고, beanPostProcessor 를 등록한다.
  • 의존성 주입을 무시할 인터페이스들을 등록한다.(*Aware.class)


(4) postProcessBeanFactory(beanFactory)

  • template method 로 구현체에 따른다. (AnnotationConfigServletWebServerApplicationContext)
  • beanPostProcessor 를 등록하고, 빈 팩토리에 WebApplicationContext 에 관련된 스코프를 등록한다.(request, session 등)

postProcessBeanFactory

(5) invokeBeanFactoryPostProcessors(beanFactory)

  • 빈으로 등록되어 있는 beanFactoryPostProcessor 들을 실행한다.
  • ConfigurationClassPostProcessor 를 통해 재귀적으로 ConfigClass 의 빈 정의와, 기타 빈 정의를 로딩한다.

invokeBeanFactoryPostProcessors

(6) registerBeanPostProcessors(beanFactory)

  • 빈 생성을 가로채는 빈 프로세서들을 등록한다.
  • BeanPostProcessorChecker 를 생성하여 등록한다.
  • PriorityOrdered, Ordered, non-ordered 순으로 등록되고, Ordered 가 같은 경우 order(int 형) 멤버 변수에 의해 결정된다.
  • internal BeanPostProcessors 를 다시 등록하고, ApplicationListenerDetector 등록한다.

registerBeanPostProcessors

(7) initMessageSource()

  • message source 빈 등록한다.(DelegatingMessageSource)

initMessageSource

(8) initApplicationEventMulticaster()

  • multicaster 빈 등록한다.(SimpleApplicationEventMulticaster)

initApplicationEventMulticaster

(9) onRefresh()

  • template method 로 구현체에 따른다.
  • themeSource = ResourceBundleThemeSource 로 세팅(GenericWebApplicationContext)
  • WebServerFactory 를 통해 Tomcat Server 객체를 만들고 설정 값들을 세팅한다.(ServletWebServerApplicationContext)

onRefresh1

onRefresh2

(10) registerListeners()

  • EventMultiCaster 에 리스너들을 등록한다.
    registerListeners

(11) finishBeanFactoryInitialization(beanFactory)

  • 빈 팩토리의 설정과 definition 들을 프리징하고, 남은 싱글톤 빈들을 모두 인스턴스로 등록한다.
  • RequestMappingHandlerMapping 빈이 초기화 될 때 Handler 가 로드 된다. (RequestMappingHandlerMapping 빈 초기화 과정을 나중에 자세히..)

finishBeanFactoryInitialization

(12) finishRefresh()

  • 마지막 이벤트를 발행하고, 등록 되어 있는 이벤트 리스너를 별도 스레드로 execute 한다.(multicastEvent)
  • Tomcat Server 를 시작한다.

finishRefresh1

finishRefresh2


Comments