深入理解Spring系列之六:bean初始化

weixin_33830216發表於2016-11-07

《深入理解Spring系列之四:BeanDefinition裝載前奏曲》中提到,對於非延遲單例bean的初始化在finishBeanFactoryInitialization(beanFactory)中完成。進入這個方法,程式碼如下。

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    // Initialize conversion service for this context.
    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));
    }
    // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
    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.
    beanFactory.freezeConfiguration();
    // Instantiate all remaining (non-lazy-init) singletons.
    beanFactory.preInstantiateSingletons();
}

關注最後一行程式碼,

beanFactory.preInstantiateSingletons()完成初始化所有非延遲的單例bean,進入這個方法的具體實現,程式碼如下。
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 beanNames = new ArrayList(this.beanDefinitionNames);
    // Trigger initialization of all non-lazy singletonbeans...
    for (String beanName : beanNames) {
      RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
      if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
        if (isFactoryBean(beanName)) {
          final FactoryBean factory = (FactoryBean) getBean(FACTORY_BEAN_PREFIX + beanName);
          boolean isEagerInit;
          if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
            isEagerInit = AccessController.doPrivileged(new PrivilegedAction() {
              @Override
              public Boolean run() {
                return ((SmartFactoryBean) factory).isEagerInit();
              }
            }, getAccessControlContext());
          }else {
            isEagerInit = (factory instanceof SmartFactoryBean &&
                ((SmartFactoryBean) factory).isEagerInit());
          }
if (isEagerInit) {
            getBean(beanName);
          }
        }else {
          getBean(beanName);
        }
      }
    }
    // Trigger post-initialization callback for all applicable beans...
    for (String beanName : beanNames) {
      Object singletonInstance = getSingleton(beanName);
      if (singletonInstance instanceof SmartInitializingSingleton) {
        final SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
        if (System.getSecurityManager() != null) {
          AccessController.doPrivileged(new PrivilegedAction() {
            @Override
            public Object run() {
              smartSingleton.afterSingletonsInstantiated();
              return null;
            }
          }, getAccessControlContext());
        }else {
smartSingleton.afterSingletonsInstantiated();
        }
      }
    }
}

從上面的程式碼中看到,只會對非延遲單例bean進行初始化,scope為其它值的bean會在使用到的時候進行初始化,如prototype。這裡關注getBean方法,這個方法看著很眼熟,其實就是《深入理解Spring系列之一:開篇》示例程式碼中用到的getBean,Spring對這個方法做了重複使用。getBean方法的具體實現在doGetBean方法中,這個方法的程式碼很長就不貼程式碼了。在doGetBean中,首先會初始化其依賴的bean,然後進行自身的初始化,這個方法裡關注如下的程式碼段。

 // Create bean instance.
        if (mbd.isSingleton()) {
          sharedInstance = getSingleton(beanName, new ObjectFactory() {
            @Override
            public Object getObject() throws BeansException {
              try {
                return createBean(beanName, mbd, args);
              }
              catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that receiveda temporary reference to the bean.
                destroySingleton(beanName);
                throw ex;
              }
            }
          });
          bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }

這段程式碼完成了單例bean的初始化,追蹤程式碼進入doCreateBean方法中,在這個方法中進行bean例項的建立、屬性填充、將bean例項加入單例bean例項的快取中。doCreateBean方法中有如下程式碼段。

if (instanceWrapper == null) {
    instanceWrapper = createBeanInstance(beanName, mbd, args);
}

createBeanInstance方法裡完成bean例項的建立,具體過程可繼續追蹤程式碼檢視,其實就是使用反射進行例項物件的建立。

相關文章