Spring 单例创建流程

Posted 看写写

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring 单例创建流程相关的知识,希望对你有一定的参考价值。

所有的代码,都只保留了主干流程,为了阅读方便进行了简化处理,具体以源码为准
这里仅供参考
org.springframework.beans.factory.support.AbstractBeanFactory

类图

单例整体流程

// 通过工厂类,获取对象都是通过这个方法获取的
@Override
public Object getBean(String name) throws BeansException 
   return doGetBean(name, null, null, false);


// 删除了不相干的代理,只保留主干
protected <T> T doGetBean(
      final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
      throws BeansException 

    // Eagerly check singleton cache for manually registered singletons.
    // 第一次检查, 从缓存里面取,如果已经存在直接返回, 这里可以
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null) 
       return;
   
  // Create bean instance.  创建单例
         if (mbd.isSingleton()) 
         
            sharedInstance = getSingleton(beanName, 
              // 使用工厂方法的好处
              // 1, 解偶,创建和使用解偶,使用的地方不需要知道具体的细节
              //   2, 可以根据需要再生成对象,懒生成,而不是每次都生成对象,加快spring启动的速度
              new ObjectFactory<Object>() 
               @Override
               public Object getObject() throws BeansException 
                  try 
                     // 具体创建单例的地方,这例使用就是下面讲解的AbstractAutowireCapableBeanFactory类
                     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 received a temporary reference to the bean.
                     destroySingleton(beanName);
                     throw ex;
                  
               
            );
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
         
   return (T) bean;


// 整体的流程控制,保证单例的特性,防止重复生成对象
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) 
   Assert.notNull(beanName, "'beanName' must not be null");
   // 加锁,二次检查
   synchronized (this.singletonObjects) 
     Object singletonObject = this.singletonObjects.get(beanName);
      if (singletonObject == null) 
          //如果当前单例正在创建中, 如果第二次走到这个地方,就破换了单例的特性,抛出异常
         if (this.singletonsCurrentlyInDestruction) 
            throw new BeanCreationNotAllowedException(beanName,
                  "Singleton bean creation not allowed while singletons of this factory are in destruction " +
                  "(Do not request a bean from a BeanFactory in a destroy method implementation!)");
         
         // 这个地方很重要,保证了单例的特性,防止重复创建对象
         beforeSingletonCreation(beanName);
         // 创建对象
         singletonObject = singletonFactory.getObject();
         // 缓存对象
         addSingleton(beanName, singletonObject);
      
      return (singletonObject != NULL_OBJECT ? singletonObject : null);
   


// 判断一个单例是否在创建中
public boolean isSingletonCurrentlyInCreation(String beanName) 
   return this.singletonsCurrentlyInCreation.contains(beanName);


// 把单例对象的名称,加入到singletonsCurrentlyInCreation, 同步map]中
// 1, 为了后续的判断是否正在创建单例,
// 2, 防止重复创建对象,破换单例的特性
protected void beforeSingletonCreation(String beanName) 
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) 
      throw new BeanCurrentlyInCreationException(beanName);
   

创建单例的细节

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory. doCreateBean


protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)
      throws BeanCreationException 

   // Instantiate the bean.
   BeanWrapper instanceWrapper = null;
   if (mbd.isSingleton()) 
      instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
   
   if (instanceWrapper == null) 
      // 根据构造函数创建对象,如果构造函数有参数,会进行参数的解析,填充
      instanceWrapper = createBeanInstance(beanName, mbd, args);
   
   final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
   Class<?> beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
   mbd.resolvedTargetType = beanType;

   // Allow post-processors to modify the merged bean definition.
   synchronized (mbd.postProcessingLock) 
      if (!mbd.postProcessed) 
         try 
            // mbd合并
            applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
         
         catch (Throwable ex) 
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                  "Post-processing of merged bean definition failed", ex);
         
         mbd.postProcessed = true;
      
   

   // Eagerly cache singletons to be able to resolve circular references
   // even when triggered by lifecycle interfaces like BeanFactoryAware.
   // 单利创建的时候,会先把beanName添加到一个map里面,+ lock,保证单例的特性
   // 只要是单例 所以这里返回true: isSingletonCurrentlyInCreation(beanName) 
   boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
         isSingletonCurrentlyInCreation(beanName));
         // 为了解决循环依赖,单例对象第一次创建完成,会提前发布出去,
         // 使用factory原因的可以进行延迟 生成代理对象
         // 因为循环依赖属于小概率事件,所以注册一个factory,当真的存在循环依赖的时候
         // 再生成真正的对象(spring AOP机制会在这里生成代理对象比较耗时),个人理解所以懒处理的形式,加快速度
   if (earlySingletonExposure) 
      if (logger.isDebugEnabled()) 
         logger.debug("Eagerly caching bean '" + beanName +
               "' to allow for resolving potential circular references");
      
      addSingletonFactory(beanName, new ObjectFactory<Object>() 
         @Override
         public Object getObject() throws BeansException 
              // Srping AOP在这里进行增强,提前生成代理对象
            return getEarlyBeanReference(beanName, mbd, bean);
         
      );
   

   // Initialize the bean instance.
   Object exposedObject = bean;
   try 
      // 填充参数, @Resource, @Autowired 都是在这里进行处理
      populateBean(beanName, mbd, instanceWrapper);
      if (exposedObject != null) 
         // 初始化对象
         exposedObject = initializeBean(beanName, exposedObject, mbd);
      
   
   catch (Throwable ex) 
      if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) 
         throw (BeanCreationException) ex;
      
      else 
         throw new BeanCreationException(
               mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
      
   
   // 如果提前发布了对象
   if (earlySingletonExposure) 
      // 如果提前发布了对象,但是进行了Spring AOP增强,生成了新的对象,这里需要获取最新的对象,
      // 注意这里的参数是false,不能生成新的对象,只能从缓存里面取
      Object earlySingletonReference = getSingleton(beanName, false);
      if (earlySingletonReference != null) 
         if (exposedObject == bean) 
            // 体会为最新生成的对象比如 spring AOP代理对象,保证其单例特性,
            // 如果这里不进行处理会导致循环依赖的对象和当前的对象不一致,破换了单例的特性
            exposedObject = earlySingletonReference;
         
         else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) 
            String[] dependentBeans = getDependentBeans(beanName);
            Set<String> actualDependentBeans = new LinkedHashSet<String>(dependentBeans.length);
            for (String dependentBean : dependentBeans) 
               if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) 
                  actualDependentBeans.add(dependentBean);
               
            
            if (!actualDependentBeans.isEmpty()) 
               throw new BeanCurrentlyInCreationException(beanName,
                     "Bean with name '" + beanName + "' has been injected into other beans [" +
                     StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
                     "] in its raw version as part of a circular reference, but has eventually been " +
                     "wrapped. This means that said other beans do not use the final version of the " +
                     "bean. This is often the result of over-eager type matching - consider using " +
                     "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
            
         
      
   

   // Register bean as disposable.
   try 
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   
   catch (BeanDefinitionValidationException ex) 
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   

   return exposedObject;
```

## Spring AOP如何解决,循环依赖的问题,同时保证单例特性
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator
类是AOP增强的主流程入口

```bash
// spring 解决单例循环依赖的时候,会提前注册一个BeanFactory,这里会提前生成代理类
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException 
   Object cacheKey = getCacheKey(bean.getClass(), beanName);
   // 写入这个map的原因,是为了保证单例,这里提前生成了代理类(因为循环依赖),
   // A->B->A , 这种情况下,在创建B的时候,会调用这里提前生成A的代理类,
   // 这个时候B里面的对A的引用已经是新的代理类了,但是A本身的还在初始化的过程中还没完成
   // 需要完成A的初始化,但是还不能重新生成新的代理类否则就不是单例了,所以这里记录
   // 在postProcessAfterInitialization的时候,对比引用,如果一样,就不重新生成代理类了
   // 同时这个方法只会被调用一次,因为单例对象生成过成中会加锁,而且进行缓存,保证创建完成之后
   // 只会从缓存里面取。同时最终A初始化完成之后,会把最终返回的引用对象体会为这里生成的代理对象,保证单例
   this.earlyProxyReferences.put(cacheKey, bean);
   // 生成代理类的具体实现
   return wrapIfNecessary(bean, beanName, cacheKey);

// 正常的非循环依赖的对象,都从这里进行AOP的增强
// 这里的循环依赖指的是单例循环依赖(非构造函数依赖)
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException 
   if (bean != null) 
      Object cacheKey = getCacheKey(bean.getClass(), beanName);
      // 1, 如果是循环依赖则remove返回的bean ,和 当前是bean地址一样,这里是false,直接结束
      // 2, 非循环依赖,那这里remove返回的是null,而bean不为空是先决条件,所以这里返回 true,进行类的增强,生成代理类
      if (this.earlyProxyReferences.remove(cacheKey) != bean) 
         // 生成代理类的具体实现
         return wrapIfNecessary(bean, beanName, cacheKey);
      
   
   return bean;


以上是关于Spring 单例创建流程的主要内容,如果未能解决你的问题,请参考以下文章

java单利模式设计

关于单利模式的几种实现方式

Spring源码剖析-单利Bean的实例化

Spring 单例创建流程

Spring 单例创建流程

Spring 单例创建流程