spring源碼解析beanFactory建立

前言web

本文轉自「天河聊技術」微信公衆號spring

今天的主要內容是spring上下文刷新相關源碼解析設計模式

 

正文緩存

跟蹤到這個類微信

org.springframework.web.context.ContextLoader#configureAndRefreshWebApplicationContext這行代碼併發

//     上下文刷新
      wac.refresh();

找到org.springframework.context.ConfigurableApplicationContext#refresh這個接口的一個抽象實現org.springframework.context.support.AbstractApplicationContext#refreshide

@Override
   public void refresh() throws BeansException, IllegalStateException {
//    門面模式,刷新和銷燬上下文必須是同步的,這裏加了一個鎖
      synchronized (this.startupShutdownMonitor) {
         // Prepare this context for refreshing.準備這個上下文來刷新。
//       上下文刷新的前置工做
         prepareRefresh();

         // Tell the subclass to refresh the internal bean factory.初始化內部beanFactory TODO 天河
         ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

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

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

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

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

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

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

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

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

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

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

         catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
               logger.warn("Exception encountered during context initialization - " +
                     "cancelling refresh attempt: " + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            destroyBeans();

            // Reset 'active' flag.
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
         }

         finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            resetCommonCaches();
         }
      }
   }

總體看下,這個方法採用了門面設計模式,代碼看起來跟整潔,邏輯很清晰。post

刷新和銷燬上下文必須是同步的,這裏加了一個鎖ui

synchronized (this.startupShutdownMonitor) {

上下文刷新的前置工做this

prepareRefresh();

跟蹤到這個方法

org.springframework.context.support.AbstractApplicationContext#prepareRefresh spring上下文刷新以前的一些前置工做,主要是相關屬性的解析

protected void prepareRefresh() {
      this.startupDate = System.currentTimeMillis();
      this.closed.set(false);
      this.active.set(true);

      if (logger.isInfoEnabled()) {
         logger.info("Refreshing " + this);
      }

      // Initialize any placeholder property sources in the context environment 解析佔位符
      initPropertySources();

      // Validate that all properties marked as required are resolvable
      // see ConfigurablePropertyResolver#setRequiredProperties
//    驗證Required的屬性
      getEnvironment().validateRequiredProperties();

      // Allow for the collection of early ApplicationEvents,
      // to be published once the multicaster is available...
      this.earlyApplicationEvents = new LinkedHashSet<>();
   }

返回到這個方法org.springframework.context.support.AbstractApplicationContext#refresh

這一行代碼

ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

建立beanFactory。

org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory跟蹤到這個方法

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//    刷新beanFactory
      refreshBeanFactory();
      ConfigurableListableBeanFactory beanFactory = getBeanFactory();
      if (logger.isDebugEnabled()) {
         logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
      }
      return beanFactory;
   }

刷新beanFactory

refreshBeanFactory();

跟蹤到這個方法org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory 實現了上下文底層的beanFactory刷新,若是以前有beanFactory就關閉並再初始化一個beanFactory。

@Override
   protected final void refreshBeanFactory() throws BeansException {
//    若是存在beanFactory
      if (hasBeanFactory()) {
//       銷燬bean
         destroyBeans();
         closeBeanFactory();
      }
      try {
         DefaultListableBeanFactory beanFactory = createBeanFactory();
         beanFactory.setSerializationId(getId());
         customizeBeanFactory(beanFactory);
         loadBeanDefinitions(beanFactory);
         synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
         }
      }
      catch (IOException ex) {
         throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
      }
   }

判斷是否存在beanFactory

if (hasBeanFactory()) {
//       銷燬bean
         destroyBeans();
         closeBeanFactory();
      }

跟蹤到這個方法

org.springframework.context.support.AbstractApplicationContext#destroyBeans 銷燬單例的bean

protected void destroyBeans() {
//    獲取beanFactory,並銷燬單例的bean TODO 銷燬bean
      getBeanFactory().destroySingletons();
   }

找到這個方法

org.springframework.beans.factory.support.DefaultListableBeanFactory#destroySingletons

@Override
   public void destroySingletons() {
      super.destroySingletons();
//    清除記錄的單例beanName的緩存
      this.manualSingletonNames.clear();
      clearByTypeCache();
   }

第一行代碼調用了父類的這個方法

org.springframework.beans.factory.support.FactoryBeanRegistrySupport#destroySingletons

@Override
   public void destroySingletons() {
      super.destroySingletons();
//    清空beanFactory緩存
      this.factoryBeanObjectCache.clear();
   }

第一行代碼又調用了父類的這個方法

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingletons

public void destroySingletons() {
      if (logger.isDebugEnabled()) {
         logger.debug("Destroying singletons in " + this);
      }
//    這裏使用ConcurrentHashMap本地緩存單例的bean實例,訪問次數比較多,提搞併發量
      synchronized (this.singletonObjects) {
         this.singletonsCurrentlyInDestruction = true;
      }

      String[] disposableBeanNames;
//    這裏是用LinkedHashMap本地緩存銷燬的bean實例
      synchronized (this.disposableBeans) {
         disposableBeanNames = StringUtils.toStringArray(this.disposableBeans.keySet());
      }
      for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
//       銷燬單例的bean
         destroySingleton(disposableBeanNames[i]);
      }

      this.containedBeanMap.clear();
      this.dependentBeanMap.clear();
      this.dependenciesForBeanMap.clear();

//    同步清空緩存
      synchronized (this.singletonObjects) {
         this.singletonObjects.clear();
         this.singletonFactories.clear();
         this.earlySingletonObjects.clear();
         this.registeredSingletons.clear();
         this.singletonsCurrentlyInDestruction = false;
      }
   }

找到這行代碼

destroySingleton(disposableBeanNames[i]);

進入到這個方法

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#destroySingleton

public void destroySingleton(String beanName) {
      // Remove a registered singleton of the given name, if any.刪除單例的bean,從本地緩存中刪除
      removeSingleton(beanName);

      // Destroy the corresponding DisposableBean instance.
      DisposableBean disposableBean;
      synchronized (this.disposableBeans) {
//       從本地緩存中刪除
         disposableBean = (DisposableBean) this.disposableBeans.remove(beanName);
      }
//    bean銷燬的邏輯
      destroyBean(beanName, disposableBean);
   }

最後

本次介紹到這裏,以上內容僅供參考。下次bean銷燬的源碼解析。

相關文章
相關標籤/搜索