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

《深入理解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 ***: 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实例的创建,具体过程可继续追踪代码查看,其实就是使用反射进行实例对象的创建。

全部评论
我自己来抢沙发!!!
点赞 回复 分享
发布于 2017-08-15 11:33
非常棒。支持
点赞 回复 分享
发布于 2017-08-15 13:15

相关推荐

头像
11-18 16:08
福州大学 Java
影流之主:干10年不被裁,我就能拿别人一年的钱了,日子有盼头了
点赞 评论 收藏
分享
1 收藏 评论
分享
牛客网
牛客企业服务