Spring應用上下文生命週期

Gouden發表於2021-02-14

Spring應用上下文生命週期整體分成四個階段

  • ConfigurableApplicationContext#refresh,載入或者重新整理持久化配置
  • ConfigurableApplicationContext#start,啟動應用上下文
  • ConfigurableApplicationContext#stop,停止應用上下文
  • ConfigurableApplicationContext#close,關閉應用上下文,釋放鎖定資源

實際上refresh執行完成後Spring應用上下文從廣義上來說已經啟動了,start回撥用LifeCycleProcessors的start方法,可以理解refresh處理Spring應用上下文啟動需要的東西,start相當於是一個擴充套件,close和stop是和refresh和close類似的逆向操作。

因此Spring應用上下文生命週期重頭戲是refresh和close兩個方法對應的實現。

refresh-重新整理應用上下文

整個refresh階段程式碼如下所示:

從程式碼可以看出,refresh整體分為以下幾個階段:

  • 準備重新整理階段: prepareRefresh
  • BeanFactory建立階段: obtainFreshBeanFactory
  • BeanFactory準備階段: prepareBeanFactory
  • BeanFactory後置處理階段: postProcessBeanFactory、invokeBeanFactoryPostProcessors
  • BeanFactory註冊BeanPostProcessor階段: registerBeanPostProcessors
  • 初始化內建Bean: initMessageSource、initApplicationEventMulticaster
  • Spring應用上下文重新整理階段: onRefresh
  • Spring事件監聽器註冊階段: registerListener
  • BeanFactory初始化完成階段: finishBeanFactoryInitialization
  • Spring應用上下文重新整理完成階段: finishRefresh

準備重新整理階段

prepareRefresh方法註釋如下所示,可以看出,這個方法主要做了三件事來準備上下文重新整理:

  • 設定啟動時間
  • 設定啟用標
  • 執行任何初始化屬性來源

    protected void prepareRefresh() {
        //設定啟動時間、啟用標
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);

        if (logger.isDebugEnabled()) {
            if (logger.isTraceEnabled()) {
                logger.trace("Refreshing " + this);
            }
            else {
                logger.debug("Refreshing " + getDisplayName());
            }
        }

        //初始化屬性源,擴充套件用
        initPropertySources();

        //校驗必要屬性
        getEnvironment().validateRequiredProperties();

        //建立儲存早期applicationListeners容器
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }

        //建立儲存早期applicationEvents容器,儲存早期Spring Application事件,用於後面applicationEventMulticaster釋出事件用
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }

BeanFactory建立階段

在AbstractRefreshableApplicationContext的refreshBeanFactory實現裡,會對這個應用上下文的底層BeanFactory做一個重新整理,如果之前有BeanFactory,會先停止,再初始化一個新的BeanFactory

    protected final void refreshBeanFactory() throws BeansException {
     //如果有BeanFactory,先關掉這個BeanFactory  
if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try {
       //建立新的BeanFactory DefaultListableBeanFactory beanFactory
= createBeanFactory();
       //設定BeanFactory的id beanFactory.setSerializationId(getId());
       //設定是否允許BeanDefinition覆蓋、是否允許迴圈依賴 customizeBeanFactory(beanFactory);
       //載入BeanDefinition loadBeanDefinitions(beanFactory);
       //設定新的BeanFactory為當前應用上下文IoC容器
synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }

BeanFactory準備階段

配置容器上下文特徵,例如上下文的ClassLoader和後置處理器。

    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        //設定容器使用的類載入器: ClassLoader,預設是執行緒上下文類設定的載入器
        beanFactory.setBeanClassLoader(getClassLoader());
     //設定Bean表示式處理器,指定bean definition中的表達是值的解析策略 beanFactory.setBeanExpressionResolver(
new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
     //新增PropertyEditorRegistrar實現,儲存ResourceLoader和PropertyResolver beanFactory.addPropertyEditorRegistrar(
new ResourceEditorRegistrar(this, getEnvironment())); //新增BeanPostProcessor實現,用於處理ApplicationContext的Aware回撥 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
     //忽略指定介面作為依賴注入介面 beanFactory.ignoreDependencyInterface(EnvironmentAware.
class); beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); beanFactory.ignoreDependencyInterface(MessageSourceAware.class); beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); //註冊ResolvableDependency,這部分可以被依賴注入但不能被依賴查詢 beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this); //註冊ApplicationListener探測器,如果一個Bean實現了ApplicationListener介面會被當作ApplicationListener註冊到Publisher beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); //註冊動態織入後置處理器 if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } //註冊環境Bean單例物件 if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); } if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); } if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); } }

BeanFactory後置處理階段

postProcessBeanFactory和invokeBeanFactoryPostProcessors都是Spring提供的擴充套件方式。

postProcessBeanFactory在AbstractApplicationContext裡沒有實際實現,postProcessBeanFactory註釋如下:

 可以看出這時Spring應用上下文內部BeanFactory已經標準初始化完成,這時所有Bean的BeanDefinition已經被載入進來,但是還沒有被例項化,這時允許繼承類註冊特殊的BeanPostProcessors等內容。

invokeBeanFactoryPostProcessors方法註釋如下:

 這個方法會例項化並且執行所有被註冊的BeanFactoryPostProcessor的Bean,如果給定顯示順序,按顯示順序執行,invokeBeanFactoryPostProcessors程式碼如下:

    protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
     //處理BeanFactoryPostProcessors,這裡細節挺多的,要按一定順序執行BeanDefinitionRegistryPostProcessor#postProcessBeanDefinitionRegistry和BeanFactoryPostProcessor#postProcessBeanFactory PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
//新增LoadTimeWeaverAwareProcessor if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); } }

BeanFactory註冊BeanPostProcessor

registerBeanPostProcessors方法註釋如下:

 這個方法的作用就是例項化並且註冊所有BeanPostProcessor的Bean,會按給定順序註冊。

這裡註冊的順序是:

  • 先註冊實現PriorityOrdered的BeanPostProcessor的Bean
  • 再註冊實現Ordered的BeanPostProcessor的Bean
  • 然後註冊普通的BeanPostProcessor的Bean
  • 後面註冊MergedBeanDefinitionPostProcess的Bean
  • 最後註冊ApplicationListenerDetector的Bean

 初始化內建Bean

初始化內建Bean會初始化兩個Bean: MessageSource和ApplicationEventMulticaster。

這兩個實現比較類似,都是判斷當前BeanFactory(不判斷父BeanFactory)是否包含對應Bean,如果不包含,就建立並且用registerSingleton方法註冊到BeanFactory。

Spring應用上下文重新整理階段

onRefresh方法註釋如下所示:

  onRefresh方法是個可以被子類覆蓋的模板方法,可以在例項化單例前初始化特殊的Bean。

Spring事件監聽器註冊階段

registerListeners方法註釋如下所示:

  registerListeners方法會把實現ApplicationListener的Bean和非Bean物件註冊到ApplicationEventMulticaster。

registerListeners方法程式碼如下:

    protected void registerListeners() {
        //註冊非Bean的ApplicationListener實現類的物件
        for (ApplicationListener<?> listener : getApplicationListeners()) {
            getApplicationEventMulticaster().addApplicationListener(listener);
        }

        //註冊ApplicationListener實現類對應的Bean
        String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
        for (String listenerBeanName : listenerBeanNames) {
            getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
        }

        //傳送早期ApplicationEvent事件
        Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
        this.earlyApplicationEvents = null;
        if (earlyEventsToProcess != null) {
            for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
                getApplicationEventMulticaster().multicastEvent(earlyEvent);
            }
        }
    }

BeanFactory初始化完成階段

finishBeanFactoryInitialization方法註釋如下所示:

 這個方法會結束Spring應用上下文的BeanFactory的初始化,初始化所有剩餘的單例Bean。

finishBeanFactoryInitialization方法程式碼如下所示:

    protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
        //如果BeanFactory有ConversionService物件,關聯到BeanFactory
        if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
                beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
            beanFactory.setConversionService(
                    beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
        }

        //新增StringValueResolver物件
        if (!beanFactory.hasEmbeddedValueResolver()) {
            beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
        }

        //依賴查詢LoadTimeWeaverAware的Bean
        String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
        for (String weaverAwareName : weaverAwareNames) {
            getBean(weaverAwareName);
        }

        //BeanFactory臨時ClassLoader置為null
        beanFactory.setTempClassLoader(null);

        //BeanFactory凍結配置
        beanFactory.freezeConfiguration();

        //例項化所有不是懶載入的單例物件
        beanFactory.preInstantiateSingletons();
    }

Spring應用上下文重新整理完成階段

finishRefresh方法註釋如下所示:

  finishRefresh方法結束Spring應用上下文重新整理,呼叫LifecycleProcessor#onRefresh方法並且傳送ContextRefreshedEvent。

finishRefresh方法程式碼如下所示:

    protected void finishRefresh() {
        //清除ResourceLoader快取
        clearResourceCaches();

        //初始化LifecycleProcessor物件
        initLifecycleProcessor();

        //呼叫LifecycleProcessor#onRefresh方法
        getLifecycleProcessor().onRefresh();

        //釋出Spring應用上下文已重新整理事件
        publishEvent(new ContextRefreshedEvent(this));

        //向MBeanServer託管Live Bean
        LiveBeansView.registerApplicationContext(this);
    }

start-啟動應用上下文

start方法程式碼如下所示:

    public void start() {
     //啟動LifecycleProcessor getLifecycleProcessor().start();
     //釋出應用上下文啟動事件 publishEvent(
new ContextStartedEvent(this)); }

stop-停止應用上下文

stop方法程式碼如下所示:

    public void stop() {
     //停止LifecycleProcessor getLifecycleProcessor().stop();
     //釋出應用上下文停止事件 publishEvent(
new ContextStoppedEvent(this)); }

close-關閉應用上下文

    protected void doClose() {
        //檢查啟用標
        if (this.active.get() && this.closed.compareAndSet(false, true)) {
            if (logger.isDebugEnabled()) {
                logger.debug("Closing " + this);
            }
        //Live Bean登出託管
            LiveBeansView.unregisterApplicationContext(this);

            try {
                //釋出Spring應用上下文已關閉事件
                publishEvent(new ContextClosedEvent(this));
            }
            catch (Throwable ex) {
                logger.warn("Exception thrown from ApplicationListener handling ContextClosedEvent", ex);
            }

            //關閉LifecycleProcessor
            if (this.lifecycleProcessor != null) {
                try {
                    this.lifecycleProcessor.onClose();
                }
                catch (Throwable ex) {
                    logger.warn("Exception thrown from LifecycleProcessor on context close", ex);
                }
            }

            //銷燬Spring Bean
            destroyBeans();

            //關閉BeanFactory
            closeBeanFactory();

            //回撥onClose
            onClose();

            //重置本地監聽者
            if (this.earlyApplicationListeners != null) {
                this.applicationListeners.clear();
                this.applicationListeners.addAll(this.earlyApplicationListeners);
            }

            //啟用標設定為沒啟用
            this.active.set(false);
        }
    }

相關文章