Spring源碼閱讀之初始化"非懶加載bean"實例-第1篇

在經歷了前面BeanDefinition定義和BeanPostProcessor的準備工作完成之後,終於到了千呼萬喚始出來的bean實例初始化了,也就是平時想用哪個類對應的實例直接從BeanFactory要的對象時怎麼被創建出來的?由於這塊邏輯比較複雜,還涉及到"循環依賴"等等一系列問題,所以我會在接下來利用兩三篇文章來逐一說明。你們準備好一次搞定bean實例初始化的流程了嗎?關於測試用例我們還是沿用UserService

說明一下,關於以下幾個方法,不是我們關注的重點,暫時先不討論,後面有時間我們在來介紹

  • initMessageSource():初始化國際化相關

  • initApplicationEventMulticaster():初始化事件分發器

  • onRefresh():初始化特殊的bean實例,無任何實現,預留出來的擴展點

  • registerListeners():註冊監聽器


  1. 關於BeanDefinition的幾點提前說明

  • GenericBeanDefinition:配置爲xml文件被解析爲這個BeanDefinition定義

  • ScannedGenericBeanDefinition:由註解聲明的被解析成這個BeanDefinition

  • 在bean實例化開始我們會遇到一個叫mergedBeanDefinition的bean定義,由於BeanDefinition會存在如下情況:

  1. BeanDefinition存在父BeanDefinition

  2. BeanDefinition不存在父BeanDefinition且本身是一個RootBeanDefinition

  3. BeanDefinition不是一個RootBeanDefinition,而是一個自定義的BeanDefinition

所以在bean實例化開始把這些情況統一命名爲mergedBeanDefinition。


  1. 看看finishBeanFactoryInitialization()的具體實現。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
      // Initialize conversion service for this context.
      // Step1:初始化當前上下文的轉換器
      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));
      }

      // Register a default embedded value resolver if no bean post-processor
      // (such as a PropertyPlaceholderConfigurer bean) registered any before:
      // at this point, primarily for resolution in annotation attribute values.
      // Step2:如果BeanFactory沒有內嵌值解析器,則添加一個默認的值解析器,這個解析器的作用是將註解裏面配的類似 ${} 替換成真正的值
      if (!beanFactory.hasEmbeddedValueResolver()) {
          beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
      }

      // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
      // Step3:初始化LoadTimeWeaverAware bean實例
      String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
      for (String weaverAwareName : weaverAwareNames) {
          getBean(weaverAwareName);
      }

      // Stop using the temporary ClassLoader for type matching.
      beanFactory.setTempClassLoader(null);

      // Allow for caching all bean definition metadata, not expecting further changes.
      // Step4:凍結BeanDefinition定義,因爲之後就是開始創建BeanDefinition對應的實例了
      beanFactory.freezeConfiguration();

      // Instantiate all remaining (non-lazy-init) singletons.
      // Step5:重點,實例化所有剩餘的非懶加載的單例Bean實例
      beanFactory.preInstantiateSingletons();
}

  1. 來看下beanFactory.preInstantiateSingletons()的具體實現。

public void preInstantiateSingletons() throws BeansException {
      if (this.logger.isDebugEnabled()) {
          this.logger.debug("Pre-instantiating singletons in " + this);
      }

      // Iterate over a copy to allow for init methods which in turn register new bean definitions.
      // While this may not be part of the regular factory bootstrap, it does otherwise work fine.
      List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

      // Trigger initialization of all non-lazy singleton beans...
      // Step1:遍歷當前BeanFactory裏面的所有beanName
      for (String beanName : beanNames) {
          // Step1.1:根據beanName獲取對應的MergedBeanDefinition定義。
          RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
          // Step1.2:bd不是抽象的 && bd是單例的 && bd是非懶加載的
          if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
              // Step1.2.1:根據當前beanName判斷對應的bean實例是否是一個FactoryBean。
              if (isFactoryBean(beanName)) {
                  // Step1.2.1.1:帶上前綴獲取FactoryBean
                  Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
                  // Step1.2.1.2:獲取到的bean是一個FactoryBean
                  if (bean instanceof FactoryBean) {
                      final FactoryBean<?> factory = (FactoryBean<?>) bean;
                      boolean isEagerInit;
                      if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
                          isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
                                          ((SmartFactoryBean<?>) factory)::isEagerInit,
                                  getAccessControlContext());
                      }
                      else {
                          isEagerInit = (factory instanceof SmartFactoryBean &&
                                  ((SmartFactoryBean<?>) factory).isEagerInit());
                      }
                      // Step1.2.1.3:需要提前加載,根據beanName獲取對應的bean實例並將其註冊到BeanFactory裏面。
                      if (isEagerInit) {
                          getBean(beanName);
                      }
                  }
              }
              //1.2.2:非FactoryBean,則直接獲取對應的bean實例並將其註冊到BeanFactory裏面。
              else {
                  getBean(beanName);
              }
          }
      }

      // Trigger post-initialization callback for all applicable beans...
      // Step2:遍歷beanName獲取對應的bean實例。
      for (String beanName : beanNames) {
          Object singletonInstance = getSingleton(beanName);
          // Step2.1:如果當前實例實現了SmartInitializingSingleton,則可以調用其實現的afterSingletonsInstantiated方法,可以在這個方法中做一些事情。
          if (singletonInstance instanceof SmartInitializingSingleton) {
              final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
              // Step2.1.1:是否需要安全檢測
              if (System.getSecurityManager() != null) {
                  AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
                      smartSingleton.afterSingletonsInstantiated();
                      return null;
                  }, getAccessControlContext());
              }
              else {
                  smartSingleton.afterSingletonsInstantiated();
              }
          }
      }
}

  1. 基於以上的實現,我們先來看看如果根據beanName獲取到對應的MergedBeanDefinition定義的。

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
      // Quick check on the concurrent map first, with minimal locking.
      // Step1:存MergedBeanDefinitions緩存獲取對應的BeanDefinition定義,快速返回BeanDefinition定義,這種類似的緩存在Sprin後面的源碼也會大量用到,我們在文末總結一下今天見到的本地緩存
      RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
      if (mbd != null) {
          return mbd;
      }
      // Step2:首先根據beanName獲取到對應的BeanDefinition定義,然後在根據BeanDefinition和beanName獲取到RootBeanDefinition。
      return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}
public BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException {
      // Step1:從beanDefinitionMap獲取對應的BeanDefinition,這裏存放的就是我們在 obtainFreshBeanFactory() 方法裏面創建出來的BeanDefinition定義,理論上這裏肯定可以獲取得到對應的BeanDefinition,如果取不到就拋出異常。
      BeanDefinition bd = this.beanDefinitionMap.get(beanName);
      
      if (bd == null) {
          if (this.logger.isTraceEnabled()) {
              this.logger.trace("No bean named '" + beanName + "' found in " + this);
          }
          throw new NoSuchBeanDefinitionException(beanName);
      }
      return bd;
}

  1. 根據beanNameBeanDefinition獲取對應的RootBeanDefinition定義

// 拿到了beanName和對應的BeanDefinition定義,我們來看看是怎麼獲取到對應的RootBeanDefinition定義的。
protected RootBeanDefinition getMergedBeanDefinition(
			String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
			throws BeanDefinitionStoreException {

    synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        // Step1:從緩存中獲取對應的RootBeanDefinition定義。
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }
        // Step2:本地緩存中不存在。
        if (mbd == null) {
            // Step2.1:判斷當前BeanDefinition是否存在父BeanDefinition,如果不存在父BeanDefinition。
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                // Step2.1.1:實現了RootBeanDefinition接口,則拿BeanDefinition克隆一個RootBeanDefinition
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    // Step2.1.2:直接使用當前BeanDefinition創建一個對應的RootBeanDefinition定義。
                    mbd = new RootBeanDefinition(bd);
                }
            }
            else {
                // Child bean definition: needs to be merged with parent.
                // Step2.2:存在父BeanDefinition,獲取父BeanDefinition對應的名字
                BeanDefinition pbd;
                try {
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    // Step2.3:判斷當前BeanName和父BeanName不同,則根據父beanName獲取父BeanDefinition定義
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        // Step2.4:獲取父BeanFactory,如果父BeanFactory實現了ConfigurableBeanFactory接口,使用父BeanFactory獲取父BeanDefinition
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(parentBeanName,
                                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                // Step2.3:使用父BeanDefinition創建一個RootBeanDefinition定義,然後將當前BeanDefinition(子BeanDefinition)的屬性覆蓋上去。
                mbd = new RootBeanDefinition(pbd);
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            // Step2.4:設置scope屬性,默認的都是單例的。
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            // Step2.5:對外部傳進來的BeanDefinition設置scope屬性。
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
            // Step2.6:將創建出來的RootBeanDefinition定義回種到本地緩存裏面。
            if (containingBd == null && isCacheBeanMetadata()) {
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }
        // Step3:返回創建好的RootBeanDefinition定義。
        return mbd;
    }
}

  1. 獲取當前BeanDefinition對應的父BeanDefinition對應的beanName

// 接着看看根據父beanName獲取對應的名字
protected String transformedBeanName(String name) {
    // BeanFactoryUtils.transformedBeanName這個操作就是將FactoryBean的前綴去掉。
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 從別名map裏面獲取對應的beanName,返回別名對應的真實beanName。
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

  1. 拿到了父beanName,根據父beanName獲取對應的BeanDefinition定義。

public BeanDefinition getMergedBeanDefinition(String name) throws BeansException {
      // Step1. 獲取別名對應的真實beanName。
    String beanName = transformedBeanName(name);

    // Efficiently check whether bean definition exists in this factory.
    // Step2:如果當前的BeanFactory不存在BeanDefinition定義 && 父BeanFactory實現了ConfigurableBeanFactory,則從父BeanFactory裏面獲取對應的RootBeanDefinition定義。
    if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
        return ((ConfigurableBeanFactory) getParentBeanFactory()).getMergedBeanDefinition(beanName);
    }
    // Resolve merged bean definition locally.
    // Step3:沒取到,則新創建。
    return getMergedLocalBeanDefinition(beanName);
}

protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
      // Quick check on the concurrent map first, with minimal locking.
      // Step1:從mergedBeanDefinitions緩存優先獲取,取到則直接返回。
      RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
      if (mbd != null) {
          return mbd;
      }
      // Step2:如果沒有取到,則根據當前的beanName獲取對應的beanDefinition定義,然後在遞歸調用getMergedBeanDefinition()方法獲取對應的RootBeanDefinition定義。
      return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

  1. 以上內容稍微繞點,仔細看兩遍應該也比較好懂,總結一下就是如果當前BeanDefinition存在父BeanDefinition,則先獲取到父BeanDefinition,然後在將當前BeanDefinition的屬性覆蓋到父BeanDefinition上,然後創建對應的RootBeanDefinition返回。到此我們得到了RootBeanDefinition定義,接下來看看beanName對應的實例是否是FactoryBean

public boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException {
      // Step1:獲取真實的beanName
      String beanName = transformedBeanName(name);
      // Step2:獲取beanName對應的bean實例
      Object beanInstance = getSingleton(beanName, false);
      // Step3:如果獲取到了對應的bean實例,則直接判斷其是否實現了FactoryBean接口,如果是則認爲是FactoryBean。
      if (beanInstance != null) {
          return (beanInstance instanceof FactoryBean);
      }

      // No singleton instance found -> check bean definition.
      // Step4:如果當前BeanFactory裏面不存在對應的bean實例,則從父BeanFactory裏面獲取。
      if (!containsBeanDefinition(beanName) && getParentBeanFactory() instanceof ConfigurableBeanFactory) {
          // No bean definition found in this factory -> delegate to parent.
          return ((ConfigurableBeanFactory) getParentBeanFactory()).isFactoryBean(name);
      }
      // Step5:當前BeanFactory存在,則選獲取對應RootBeanDefinition定義,獲取對應的beanType,根據beanType判斷是否是一個FactoryBean。
      return isFactoryBean(beanName, getMergedLocalBeanDefinition(beanName));
}

  1. 接着來看看getSingleton()是怎麼獲取beanName對應的bean實例的。

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
      // Step1:從singletonObjects緩存中獲取對象
      Object singletonObject = this.singletonObjects.get(beanName);
      // Step2:如果從緩存中沒取到 && beanName對應的bean實例正在創建中
      if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
          synchronized (this.singletonObjects) {
              // Step2.1:從earlySingletonObjects緩存中獲取對應的bean實例
              singletonObject = this.earlySingletonObjects.get(beanName);
              // Step2.2:從緩存中沒有取到 && allowEarlyReference爲true
              if (singletonObject == null && allowEarlyReference) {
                  // Step2.2.1:從singletonFactories緩存中獲取bean實例,如果能獲取到,將bean實例回種到前兩個緩存中,然後將bean實例返回。
                  ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                  if (singletonFactory != null) {
                      singletonObject = singletonFactory.getObject();
                      this.earlySingletonObjects.put(beanName, singletonObject);
                      this.singletonFactories.remove(beanName);
                  }
              }
          }
      }
      // Step3:返回bean實例
      return singletonObject;
}

  1. 再來看看isFactoryBean()是怎麼預測beanType是否是FactoryBean的。

protected boolean isFactoryBean(String beanName, RootBeanDefinition mbd) {
      // Step1:根據beanName和RootBeanDefinition獲取一個bean類型。
      Class<?> beanType = predictBeanType(beanName, mbd, FactoryBean.class);
      // Step2:如果有對應的bean類型 && 如果bean類型是通過FactoryBean分配的,則認爲是一個FactoryBean。isAssignableFrom調用的是一個native方法。
      return (beanType != null && FactoryBean.class.isAssignableFrom(beanType));
}

總結

來總結一下本篇文章裏面遇到的幾個本地緩存。

  • beanDefinitionMap:存放BeanDefinition定義

  • mergedBeanDefinitions:存放RootBeanDefinition定義

  • singletonObjects:存放bean實例,相當於bean實例的一級緩存

  • earlySingletonObjects:存放bean實例,相當於bean實例的二級緩存

  • singletonFactories:存放bean實例對應的BeanFactory,通過BeanFactory創建相應的bean實例,相當於bean實例的三級緩存

  • singletonsCurrentlyInCreation:存放當前正在創建的bean實例

到此,我們遍歷了每個beanName拿到了對應的RootBeanDefinition定義,然後判斷了beanName對應的bean實例是否是一個FactoryBean。下一篇文章來分析根據beanName獲取對應的bean實例。

歡飲關注我,一起學習

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章