如果在缓存中不存在已经加载的单例Bean,就需要从头开始bean的加载过程。Spring中使用getSingleton的重载方法实现bean的加载过程。

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        synchronized (this.singletonObjects) {
            //先检查对应的bean是否被加载过
            Object singletonObject = this.singletonObjects.get(beanName);
            //如果没有加载过,则开始进行单例bean的初始化加载
            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!)");
                }
                if (logger.isDebugEnabled()) {
                    logger.debug("Creating shared instance of singleton bean '" + beanName + "'");
                }
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    //初始化bean
                    singletonObject = singletonFactory.getObject();
                    newSingleton = true;
                }
                catch (IllegalStateException ex) {
                    // Has the singleton object implicitly appeared in the meantime ->
                    // if yes, proceed with it since the exception indicates that state.
                    singletonObject = this.singletonObjects.get(beanName);
                    if (singletonObject == null) {
                        throw ex;
                    }
                }
                catch (BeanCreationException ex) {
                    if (recordSuppressedExceptions) {
                        for (Exception suppressedException : this.suppressedExceptions) {
                            ex.addRelatedCause(suppressedException);
                        }
                    }
                    throw ex;
                }
                finally {
                    if (recordSuppressedExceptions) {
                        this.suppressedExceptions = null;
                    }
                    afterSingletonCreation(beanName);
                }
                if (newSingleton) {
                    //加入缓存
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }

getSingleton方法在单例创建的前后做一些准备和处理的操作。而真正获取单例bean是有singletonFactory.getObject()实现。

getSingleton的主要逻辑

(1)检查缓存中是否已经加载过。

(2)如果没有加载,则记录beanName的正在加载状态

(3)加载单例前记录加载状态

protected void beforeSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
      throw new BeanCurrentlyInCreationException(beanName);
   }
}

通过this.singletonsCurrentlyInCreation.add(beanName)将当前正要创建的bean记录在缓存中,为后续循环依赖提供检测。

(4)调用singletonFactory.getObject()实例化bean

if (mbd.isSingleton()) {
   sharedInstance = getSingleton(beanName, () -> {
      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 received a temporary reference to the bean.
         destroySingleton(beanName);
         throw ex;
      }
   });
   beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

创建单例bean的逻辑是函数式接口ObjectFactory的逻辑中的

(5)加载单例后的处理方法调用

protected void afterSingletonCreation(String beanName) {
   if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
      throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
   }
}

当bean加载结束后需要移除缓存中对该bean的正在加载状态的记录。

(6)将结果记录在缓存中,删除加载bean过程中所记录的各种辅助状态

protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

(7)返回单例bean

一、准备创建bean

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        if (logger.isTraceEnabled()) {
            logger.trace("Creating instance of bean '" + beanName + "'");
        }
        RootBeanDefinition mbdToUse = mbd;
     
        //锁定class,根据设置的class属性或者根据className来解析Class
        Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
        if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
            mbdToUse = new RootBeanDefinition(mbd);
            mbdToUse.setBeanClass(resolvedClass);
        }

        // Prepare method overrides.
        try {
            mbdToUse.prepareMethodOverrides();
        }
        catch (BeanDefinitionValidationException ex) {
            throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                    beanName, "Validation of method overrides failed", ex);
        }

        try {
            //给BeanPostProcessors一个机会来返回代理来替代真正的实例
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {
                return bean;
            }
        }
        catch (Throwable ex) {
            throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                    "BeanPostProcessor before instantiation of bean failed", ex);
        }

        try {
            Object beanInstance = doCreateBean(beanName, mbdToUse, args);
            if (logger.isTraceEnabled()) {
                logger.trace("Finished creating instance of bean '" + beanName + "'");
            }
            return beanInstance;
        }
        catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
            // A previously detected exception with proper bean creation context already,
            // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
            throw ex;
        }
        catch (Throwable ex) {
            throw new BeanCreationException(
                    mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
        }
    }

1、代码逻辑

(1)根据设置的class属性或者根据className来解析Class

(2)对override属性进行标记和验证

在Spring配置中存在lookup-method和replace-method,这两个配置的加载统一放在BeanDefinition中的methodOverrides属性里。此处的override属性就是处理这两个配置的。

(3)应用初始化前的后置处理器,解析指定bean是否存在初始化前的短路操作。

(4)创建bean。

2、处理override属性

public void prepareMethodOverrides() throws BeanDefinitionValidationException {
   // Check that lookup methods exist and determine their overloaded status.
   if (hasMethodOverrides()) {
      getMethodOverrides().getOverrides().forEach(this::prepareMethodOverride);
   }
}
protected void prepareMethodOverride(MethodOverride mo) throws BeanDefinitionValidationException {
   //获取对应类中对应方法名的个数
   int count = ClassUtils.getMethodCountForName(getBeanClass(), mo.getMethodName());
   if (count == 0) {
      throw new BeanDefinitionValidationException(
            "Invalid method override: no method with name '" + mo.getMethodName() +
            "' on class [" + getBeanClassName() + "]");
   }
   else if (count == 1) {
      //标记methodoverrides暂未被覆盖,避免参数类型检查的开销
      mo.setOverloaded(false);
   }
}

这里的override属性其实就是BeanDefinition中的methodOverrides属性,methodOverrides属性会在bean实例化时动态的为当前bean生成代理并使用对应的拦截器为bean做增强。

这里主要的override属性验证是用来处理类中的方法匹配,如果一个类中有若干个重载方法,那么在函数调用及增强的时候含需要根据参数类型进行匹配,来最终确认当前调用的是哪一个函数。如果当前类中方法只有一个,那么不存在重载方法,这样在后面调用的时候,可以直接使用找到的方法,而不需要进行方法的参数验证。

3、实例化的前置处理

在调用doCreate方法创建bean的实例前调用resolveBeforeInstantiation方法对BeanDefinition中的属性做前置处理。这也是给创建bean前后提供的可扩展的一种体现。同时,前置操作可以实现短路判断。

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
   Object bean = null;
   if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
      // Make sure bean class is actually resolved at this point.
      if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
         Class<?> targetType = determineTargetType(beanName, mbd);
         if (targetType != null) {
            bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
            if (bean != null) {
               bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
            }
         }
      }
      mbd.beforeInstantiationResolved = (bean != null);
   }
   return bean;
}

(1)applyBeanPostProcessorsBeforeInstantiation(实例化前的后置处理)

bean在实例化前,给子类修改BeanDefinition的机会,当程序经过这个方法后,bean可能已经不是之前的bean了,或许成为一个经过处理的代理bean,可能是通过cglib生成的,也可以是通过其他方式生成的。

protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
   for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
      //由子类覆写postProcessBeforeInstantiation
      Object result = bp.postProcessBeforeInstantiation(beanClass, beanName);
      if (result != null) {
         return result;
      }
   }
   return null;
}
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
   return null;
}

(2)applyBeanPostProcessorsAfterInitialization(实例化后的后置处理器)

从缓存中获取单例bean的时候提到,Spring中的规则是在bean初始化后尽可能保证将注册的后置处理器的postProcessorsAfterInitialization方法应用到该bean中,因为如果返回bean不为空,那么便不会再次经历普通的bean的创建过程,所以只能在这里应用后只处理器的postProcessorsAfterInitialization方法。

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
      throws BeansException {

   Object result = existingBean;
   for (BeanPostProcessor processor : getBeanPostProcessors()) {
      //由子类覆写postProcessAfterInitialization
      Object current = processor.postProcessAfterInitialization(result, beanName);
      if (current == null) {
         return result;
      }
      result = current;
   }
   return result;
}
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
   return bean;
}

二、创建bean

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {

        // Instantiate the bean.
        BeanWrapper instanceWrapper = null;
        if (mbd.isSingleton()) {
            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
        }
        if (instanceWrapper == null) {
            //根据指定bean使用对应的策略创建新的实例,如工厂方法,构造函数自动注入
            instanceWrapper = createBeanInstance(beanName, mbd, args);
        }
        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;
            }
        }

        //是否需要提早曝光:单例&允许循环依赖&当前bean正在创建中,检测循环依赖
        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
                isSingletonCurrentlyInCreation(beanName));
        if (earlySingletonExposure) {
            if (logger.isTraceEnabled()) {
                logger.trace("Eagerly caching bean '" + beanName +
                        "' to allow for resolving potential circular references");
            }
            //为避免后期循环依赖,可以在bean初始化完成前将创建实例的ObjectFactory加入工厂,aop
            //在这里将advice动态织入bean中
            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
        }

        // Initialize the bean instance.
        Object exposedObject = bean;
        try {
            //对bean进行填充,将各个属性值注入,其中可能存在依赖其他bean的属性,则递归初始依赖bean。
            populateBean(beanName, mbd, instanceWrapper);
            //调用初始化方法,如init-method
            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);
            //earlySingletonReference只有检测到有循环依赖的情况下才不会为空
            if (earlySingletonReference != null) {
                //exposedObject没有在初始化方法中被改变,也就是没有被增强
                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);
                        }
                    }
                    //因为bean创建后其所依赖的bean一定是已经创建的,actualDependentBeans不为空
                    //则表示当前bean创建后其依赖的的bean却没有全部创建完成,说明出现循环依赖
                    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;
    }

1、doCreateBean的整体思路

(1)如果是单例,则先清除缓存

(2)实例化bean,将BeanDefinition转换为BeanWrapper

        a)如果存在工厂方法则使用工厂方法进行初始化

        b)一个类有多个构造函数,每个构造函数都有不同的参数,所以需要根据参数锁定构造函数并进行初始化。

        c)如果既不存在工厂方法也不存在有参数的构造函数,则使用默认的构造函数进行bean的实例化。

(3)MergedBeanDefinitionPostProcessor的应用,bean合并后的处理,Autowired注解正是通过此方法实现诸如类型的预解析。

(4)依赖处理

在Spring中会有循环依赖的问题,例如,当A有B属性时,而B中有A属性时就会构成一个循环依赖,此时如果A和B都是单例,那么在Spring中的处理方式就是当创建B的时候,涉及自动注入A的步骤时,并不是直接去再次创建A,而是通过放入的缓存池的ObjectFactory来创建实例。

(5)属性填充

将所有属性填充到bean实例中。

(6)循环依赖检查

spring解决循环依赖只对单例有效,而对于prototype的bean,spring没有好的解决办法,唯一要做的就是抛出异常。在循环检查步骤里会检查已经加载的bean是否已经出现循环依赖,并判断是否要抛出异常。

(7)注册DisposableBean

如果配置了destroy-method,这里需要注册以便在销毁时调用。

(8)完成创建并返回

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐