Spring源码学习笔记(2)——Bean的加载

时间:2022-07-24
本文章向大家介绍Spring源码学习笔记(2)——Bean的加载,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Spring源码学习笔记(2)——Bean的加载

一. Bean加载的核心流程

  1. 前面大概分析了Spring读取解析配置文件,并加载BeanDefinition的过程。本节详细整理下Bean的加载过程。首先贴上核心代码
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
//提取对应的beanName
   final String beanName = transformedBeanName(name);
   Object bean;

   //首先检查缓存中或者实例工厂中是否有对应的的实例,因为在创建Singleton Bean的时候可能存在依赖注入的情况,而在创建依赖时,为了避免循环依赖,Spring创建Bean的原则是不等Bean创建完成,就会将创建Bean的ObjectFactory提早曝光,也就是将ObjectFactory加入到缓存中,一旦下一个Bean创建时需要依赖上一个Bean,就直接使用ObjectFactory

   //直接尝试从缓存获取或者从singletonFactories中ObjectFactory获取
   Object sharedInstance = getSingleton(beanName);
   if (sharedInstance != null && args == null) {
       if (logger.isDebugEnabled()) {
           if (isSingletonCurrentlyInCreation(beanName)) {
               logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
                            "' that is not fully initialized yet - a consequence of a circular reference");
           }
           else {
               logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
           }
       }

       //返回创建的实例,如果是FactoryBean,则返回FactoryBean的getObject()方法创建的Bean
       bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
   }

   else {
       //只有Singleton的Bean才解决循环依赖的问题,Prototype的Bean会抛出下面的异常
       if (isPrototypeCurrentlyInCreation(beanName)) {
           throw new BeanCurrentlyInCreationException(beanName);
       }

       //如果beanDefinitionMap中也就是已加载的Bean中不存在beanName,则递归地从parentBeanFactory中查找
       BeanFactory parentBeanFactory = getParentBeanFactory();
       if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
           // Not found -> check parent.
           String nameToLookup = originalBeanName(name);
           if (parentBeanFactory instanceof AbstractBeanFactory) {
               return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                   nameToLookup, requiredType, args, typeCheckOnly);
           }
           else if (args != null) {
               // Delegation to parent with explicit args.
               return (T) parentBeanFactory.getBean(nameToLookup, args);
           }
           else {
               // No args -> delegate to standard getBean method.
               return parentBeanFactory.getBean(nameToLookup, requiredType);
           }
       }

       //如果是要加载Bean,而不仅仅是做类型检查,则需要记录
       if (!typeCheckOnly) {
           markBeanAsCreated(beanName);
       }

       try {
           //将存储XML配置文件的GenericBeanDefinition转换成RootBeanDefinition,如果指定beanName是子Bean的话,同时会合并父Bean的相关属性
           final RootBeanDefinition本身
               //Singleton模式的实例化mbd = getMergedLocalBeanDefinition(beanName);
           checkMergedBeanDefinition(mbd, beanName, args);

           //如果存在依赖,则递归实例化依赖的Bean
           String[] dependsOn = mbd.getDependsOn();
           if (dependsOn != null) {
               for (String dep : dependsOn) {
                   if (isDependent(beanName, dep)) {
                       throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                       "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                   }
                   //缓存依赖调用
                   registerDependentBean(dep, beanName);
                   getBean(dep);
               }
           }

           //实例化所有依赖的Bean后,开始实例化RootBeanDefinition本身
           //Singleton模式的实例化
           if (mbd.isSingleton()) {
               sharedInstance = getSingleton(beanName, () -> {
                   try {
                       return createBean(beanName, mbd, args);
                   }
                   catch (BeansException ex) {
                       destroySingleton(beanName);
                       throw ex;
                   }
               });
               bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
           }

           //Prototype模式的实例化
           else if (mbd.isPrototype()) {
               Object prototypeInstance = null;
               try {
                   beforePrototypeCreation(beanName);
                   prototypeInstance = createBean(beanName, mbd, args);
               }
               finally {
                   afterPrototypeCreation(beanName);
               }
               bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
           }

           //自定义Scope模式的实例化
           else {
               String scopeName = mbd.getScope();
               final Scope scope = this.scopes.get(scopeName);
               if (scope == null) {
                   throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
               }
               try {
                   Object scopedInstance = scope.get(beanName, () -> {
                       beforePrototypeCreation(beanName);
                       try {
                           return createBean(beanName, mbd, args);
                       }
                       finally {
                           afterPrototypeCreation(beanName);
                       }
                   });
                   bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
               }
               catch (IllegalStateException ex) {
                   throw new BeanCreationException(beanName,
                                                   "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                                   "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                                   ex);
               }
           }
       }
       catch (BeansException ex) {
           cleanupAfterBeanCreationFailure(beanName);
           throw ex;
       }
   }

   //检查需要的类型是否符合Bean的实际类型
   if (requiredType != null && !requiredType.isInstance(bean)) {
       try {
           T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
           if (convertedBean == null) {
               throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
           }
           return convertedBean;
       }
       catch (TypeMismatchException ex) {
           if (logger.isDebugEnabled()) {
               logger.debug("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
           }
           throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
       }
   }
   return (T) bean;
}
  1. 当我们使用applicationContext.getBean(“beanName”)方法从容器中获取bean时,就会走到AbstractBeanFactory的doGetBean()方法,这是Spring容器加载bean的核心方法。下面对其核心流程进行介绍。

二. 提取实际的beanName

  1. 根据传入的name提取实际的beanName
protected String transformedBeanName(String name) {
   return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
  1. 这里有两种情况:
    1. 传入的参数时FactoryBean的名称,会以&开头,这时需要调用BeanFactoryUtils 的方法解析,去除&返回FactoryBean的name;
public static String transformedBeanName(String name) {
  Assert.notNull(name, "'name' must not be null");
  String beanName = name;
  while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
      beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
  }
  return beanName;
}
public String canonicalName(String name) {
  String canonicalName = name;
  // Handle aliasing...
  String resolvedName;
  do {
      resolvedName = this.aliasMap.get(canonicalName);
      if (resolvedName != null) {
          canonicalName = resolvedName;
      }
  }
  while (resolvedName != null);
  return canonicalName;
}
@Override
@Nullable
public Object getSingleton(String beanName) {
  //设置true表示允许早期依赖
  return getSingleton(beanName, true);
}
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
  //如果缓存中存在实例,则直接返回
  Object singletonObject = this.singletonObjects.get(beanName);
  if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {

      //如果缓存中实例为空,则先锁singletonObjects缓存,进行后续处理
      synchronized (this.singletonObjects缓存,进行后续处理) {
          singletonObject = this.earlySingletonObjects.get(beanName);
          //如果此Bean之前正在被加载,则不处理
          if (singletonObject == null && allowEarlyReference) {
              //当某些方法需要提前初始化时,会调用addSingletonFactory方法将其对应的ObjectFactory保存在singletonFactories中,也即保存其初始化策略
              ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
              //如果存在预先初始化的ObjectFactory,则调用getObject()方法实例化Bean,并记录在缓存中。earlySingletonObjects与singletonFactories互斥
              if (singletonFactory != null) {
                  singletonObject = singletonFactory.getObject();
                  this.earlySingletonObjects.put(beanName, singletonObject);
                  this.singletonFactories.remove(beanName);
              }
          }
      }
  }
  return singletonObject;
}
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable 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.getWrappedInstance();
        Class<?> beanType = instanceWrapper.getWrappedClass();
        if (beanType != NullBean.class) {
            mbd.resolvedTargetType = beanType;
        }

        // Allow post-processors to modify the merged bean definition.
        synchronized (mbd.postProcessingLock) {
            if (!mbd.postProcessed) {
                try {
                    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.
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isDebugEnabled()) {
                logger.debug("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            populateBean(beanName, mbd, instanceWrapper);
            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) {
            Object earlySingletonReference = getSingleton(beanName, false);
            if (earlySingletonReference != null) {
                if (exposedObject == bean) {
                    exposedObject = earlySingletonReference;
                }
                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    String[] dependentBeans = getDependentBeans(beanName);
                    Set<String> actualDependentBeans = new LinkedHashSet<>(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 " +
                                "'getBeanNamesOfType' 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;
    }