Spring源码解析——加载Bean

Bean加载过程

Bean加载的功能实现远比bean的解析要复杂的多了,对于加载bean的功能,在Spring中调用方式为:

/**
 * <p>
 * 此抽象基类为 {@link org.springframework.beans.factory.BeanFactory} 的实现提供了
 * {@link org.springframework.beans.factory.config.ConfigurableBeanFactory} SPI 的全部功能。
 * 它不假设可列举的 bean 工厂:因此也可作为从后端资源获取 bean 定义(其中 bean 定义访问是昂贵的操作)的 bean 工厂实现的基类。
 * </p>
 *
 * <p>
 * 该类提供 singleton 缓存(通过其基类
 * {@link org.springframework.beans.factory.support.DefaultSingletonBeanRegistry})、
 * 单例/原型确定、{@link org.springframework.beans.factory.FactoryBean} 处理、别名、bean 定义合并用于子 bean 定义、
 * 以及 bean 销毁(通过实现
 * {@link org.springframework.beans.factory.DisposableBean} 接口和自定义销毁方法)。
 * 此外,它还可以管理 bean 工厂层次结构(在未知 bean 的情况下委托给父 bean 工厂),通过实现
 * {@link org.springframework.beans.factory.HierarchicalBeanFactory} 接口。
 * </p>
 *
 * <p>
 * 子类需要实现的主要模板方法是
 * {@link #getBeanDefinition} 和 {@link #createBean},用于获取给定 bean 名称的 bean 定义和根据给定的 bean 定义创建 bean 实例。
 * 在
 * {@link DefaultListableBeanFactory} 和 {@link AbstractAutowireCapableBeanFactory} 中可以找到这些操作的默认实现。
 * </p>
 */
public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport implements ConfigurableBeanFactory {
	//---------------------------------------------------------------------
	// 实现 BeanFactory 接口
	//---------------------------------------------------------------------

	@Override
	public Object getBean(String name) throws BeansException {
	    return doGetBean(name, null, null, false);
	}

	@Override
	public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
	    return doGetBean(name, requiredType, null, false);
	}

	@Override
	public Object getBean(String name, Object... args) throws BeansException {
	    return doGetBean(name, null, args, false);
	}

	/**
	 * 返回指定 bean 的一个实例,该实例可以是共享的或独立的。
	 *
	 * @param name bean 的名称
	 * @param requiredType 要检索的 bean 的所需类型
	 * @param args 在使用显式参数创建 bean 实例时使用的参数
	 * (仅在创建新实例时应用,而不是检索现有实例时)
	 * @return bean 的实例
	 * @throws BeansException 如果无法创建 bean
	 */
	public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
	        throws BeansException {

	    return doGetBean(name, requiredType, args, false);
	}

getBean函数会调用doGetBean函数获取Bean实例,这个函数是一个BeanFactory中的方法,用于获取指定的bean实例。它可以接受bean的名称、所需的类型、参数和一个类型检查标志。根据参数的不同,它可能从缓存中返回实例、创建一个新的实例或者委托给父BeanFactory来获取实例。最后,它会适配bean实例并返回。如果发生异常,将抛出BeansException异常。代码如下:

/**
 * 返回一个实例,该实例可以是共享的或独立的,具体取决于传入的参数。
 * 
 * @param name 要获取的bean的名称
 * @param requiredType 需要的bean的类型
 * @param args 创建一个使用显式参数的bean实例时使用的参数
 * @param typeCheckOnly 是否获取bean实例进行类型检查,而不是实际使用
 * @return 生成的bean实例
 * @throws BeansException 如果无法创建bean,则抛出BeansException异常
 */
@SuppressWarnings("unchecked")
protected <T> T doGetBean(
        String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)
        throws BeansException {
    // 提取对应的beanName
    String beanName = transformedBeanName(name);
    Object beanInstance;

    /**
    * 检查缓存中或者实例工厂中是否有对应的实现
    * 为什么首先会使用这段代码呢?因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的
    * 时候为了避免循环依赖,Spring创建bean的原则是不等bean创建完成就会将创建bean的ObjectFactory
    * 加入到缓存中,这样其他Bean在创建时如果依赖这个Bean,就直接使用ObjectFactory
    */

    // 检查共享缓存中手动注册的单例bean
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("返回被提前缓存的单例bean实例,该实例尚未完全初始化 - 作为循环引用的结果");
            }
            else {
                logger.trace("返回被缓存的单例bean实例");
            }
        }
        // 返回对应的实例,有时候存在诸如BeanFactory的情况并不是直接返回实例本身
        // 而是返回指定方法返回的实例
        beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {
        // 只有在单例情况才会尝试解决循环依赖,原型模式情况下,如果存在A中有B的属性,B中有A的
        // 属性,那么当依赖注入的时候,就会产生A还未创建完成的时候,因为对于B的创建再次返回创
        // 建A,造成循环依赖,即isPrototypeCurrentlyInCreation(beanName)为true。
        // 如果我们在创建这个bean实例时已经创建了,那么很可能是循环引用。
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // 检查bean定义是否存在于当前工厂中。如果工厂不为空,且IOC容器里面不包含这个bean
        //一般来说只要配置正确是不会走这里的,这里是针对在bean标签中引用了其他bean,但其他bean并没有实例化
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 未找到 - 在父工厂中进行检查。
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory abf) {
                return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // 将其传递给父工厂并使用显式参数创建新的实例。
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // 没有参数 - 通过标准getBean方法进行委托。
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // 如果不是仅仅做类型检查则是创建bean,这里要进行记录
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        
        StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate")
                .tag("beanName", name);
        try {
            if (requiredType != null) {
                beanCreation.tag("beanType", requiredType::toString);
            }

            // 将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition,
            // 如果指定BeanName是子Bean的话同时会合并父类的相关属性
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            checkMergedBeanDefinition(mbd, beanName, args);

            // 保证当前bean所依赖的bean的初始化。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // isDependent用于判断指定的依赖bean是否已被注册为给定bean的依赖,
                    // 或者是否依赖于给定bean的任何传递依赖。
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "循环依赖关系 - '" + beanName + "' 与 '" + dep + "'");
                    }
                    // 缓存依赖调用
                    registerDependentBean(dep, beanName);
                    try {
                        // 获取依赖的Bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' 依赖缺失的bean '" + dep + "'", ex);
                    }
                }
            }

            // 创建bean实例。
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // 显式地从单例缓存中删除实例 - 可能会被创建过程中的循环引用分辨率所放置。
                        // 同时删除任何接收临时引用的bean实例。
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // 这是一个prototype - 创建一个新的实例。
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    throw new IllegalStateException("未定义bean的scope名字:'" + beanName + "'");
                }
                Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("未注册scope名字:'" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new ScopeNotActiveException(beanName, scopeName, ex);
                }
            }
        }
        catch (BeansException ex) {
            beanCreation.tag("exception", ex.getClass().toString());
            beanCreation.tag("message", String.valueOf(ex.getMessage()));
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
        finally {
            beanCreation.end();
            if (!isCacheBeanMetadata()) {
                clearMergedBeanDefinition(beanName);
            }
        }
    }

    return adaptBeanInstance(name, beanInstance, requiredType);
}

从上面的代码可以看出来bean的加载经历了一个相当复杂的过程,其中涉及各种各样的处理。对于加载过程涉及transformedBeanName

1、转换对应beanName

transformedBeanName传入的参数可能是别名、也可能是FactoryBean,所以需要进一步的解析,这些解析内容包括如下内容:

  • 去除FactoryBean的修饰符,也就是如果name="&&aa",那么首先去除&而使name="aa"。
  • 取指定alias所表示的最终beanName,例如别名A指向名称为B的bean则返回B;若别名A指向别名B,别名B又指向名称为C的bean则返回C。
2、尝试从缓存中加载单例

单例在Spring的同一个容器内只会被创建一次,后续再获取bean,就直接从单例缓存中获取了。当然这里也只是尝试从缓存中加载,如果加载不成功则再次尝试从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等Bean创建完成就会将创建Bean的ObjectFactory提前加入到缓存中,一旦下一个bean创建的时候需要依赖上一个bean,则直接使用ObjectFactory。

3、Bean的实例化

如果从缓存中得到了bean的原始状态,则需要对bean进行实例化。这里必须要强调一下,缓存中记录的只是原始的bean状态,并不一定是我们最终想要的bean。

4、原型模式的依赖检查

只有在单例模式下才会尝试解决循环依赖,如果存在A中有B的属性,B中有A的属性,那么当依赖注入的时候,就会产生A还未创建完成的时候,因为对于B的创建再次返回创建A,造成循环依赖,即isPrototypeCurrentlyInCreation(beanName)为true。代码如下:

5、检测parentBeanFactory

其中containsBeanDefinition是在检测如果当前加载的XML配置文件中不包含beanName所对应的配置,就只能到parentBeanFactory去尝试下了,然后再去递归的调用getBean方法,代码如下:

        // 检查bean定义是否存在于当前工厂中。
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // 未找到 - 在父工厂中进行检查。
            String nameToLookup = originalBeanName(name);
            if (parentBeanFactory instanceof AbstractBeanFactory abf) {
                return abf.doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                // 将其传递给父工厂并使用显式参数创建新的实例。
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                // 没有参数 - 通过标准getBean方法进行委托。
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }
6、将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition

因为从XML配置文件中读取到的bean信息是存储到GernericBeanDefinition中的,但是所有的bean后续处理都是针对于RootBeanDefinition的,所以这里需要一个转换,转换的同时如果父类bean不为空的话,则会一并合并父类的属性。代码如下:

				RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
				checkMergedBeanDefinition(mbd, beanName, args);
7、寻找依赖

因为bean的初始化过程中很可能会用到某些属性,而某些属性很可能是动态配置的,并且配置成依赖于其他bean,那么这个时候就有必要先加载依赖的bean,所以,在Spring的加载顺序中,在初始化某一个bean的时候首先初始化这个bean所对应的依赖。代码如下:

            // 保证当前bean所依赖的bean的初始化。
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // isDependent用于判断指定的依赖bean是否已被注册为给定bean的依赖,
                    // 或者是否依赖于给定bean的任何传递依赖。
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "循环依赖关系 - '" + beanName + "' 与 '" + dep + "'");
                    }
                    // 缓存依赖调用
                    registerDependentBean(dep, beanName);
                    try {
                        // 获取依赖的Bean
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' 依赖缺失的bean '" + dep + "'", ex);
                    }
                }
            }
8、针对不同的scope进行bean的创建

在Spring中存在着不同的scope,其中默认的是singleton,但是还有些其他的配置,诸如prototype、request之类的,在这个步骤中,Spring会根据不同的配置进行不同的初始化策略。代码如下:

            // 创建bean实例。
            if (mbd.isSingleton()) {
                sharedInstance = getSingleton(beanName, () -> {
                    try {
                        return createBean(beanName, mbd, args);
                    }
                    catch (BeansException ex) {
                        // 显式地从单例缓存中删除实例 - 可能会被创建过程中的循环引用分辨率所放置。
                        // 同时删除任何接收临时引用的bean实例。
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                // 这是一个prototype - 创建一个新的实例。
                Object prototypeInstance = null;
                try {
                    beforePrototypeCreation(beanName);
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    afterPrototypeCreation(beanName);
                }
                beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    throw new IllegalStateException("未定义bean的scope名字:'" + beanName + "'");
                }
                Scope scope = this.scopes.get(scopeName);
                if (scope == null) {
                    throw new IllegalStateException("未注册scope名字:'" + scopeName + "'");
                }
                try {
                    Object scopedInstance = scope.get(beanName, () -> {
                        beforePrototypeCreation(beanName);
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            afterPrototypeCreation(beanName);
                        }
                    });
                    beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                }
                catch (IllegalStateException ex) {
                    throw new ScopeNotActiveException(beanName, scopeName, ex);
                }
            }
9、类型转换

通常对该方法的调用参数requiredType是为空的,但是可能存在这样的情况,返回的bean其实是个String,但是requiredType却是Integer的类型,那么这时候本步骤就会起作用了,它的功能就是将返回的bean转换为requiredType所指定的类型。代码如下:

return adaptBeanInstance(name, beanInstance, requiredType);

FactoryBean的使用

一般情况下,Spring通过反射机制利用Bean的class属性指定实现类来实例化Bean。Spring提供了一个FactoryBean的工厂类接口,用户可以通过实现该接口定制化Bean的逻辑。代码逻辑如下:

/**
 * 接口FactoryBean是用来在`{BeanFactory}`中创建对象的工厂,它本身也是一个工厂。
 * 如果一个bean实现了这个接口,它就会被用作对象工厂,而不是直接被用作bean实例。
 * 这个接口用于支持单例和原型的设计模式。如果这个FactoryBean在调用时还没有完全初始化(例如因为它涉及到一个循环引用),则抛出相应的FactoryBeanNotInitializedException异常。
 * 从Spring 2.0开始,FactoryBeans可以返回null对象,工厂将考虑这是一个正常值并使用它,而不再抛出FactoryBeanNotInitializedException。
 * FactoryBean实现现在被鼓励适当地自己抛出FactoryBeanNotInitializedException。
 * 返回bean的实例(可以是null)并可能抛出异常。在初始化过程中,不要依赖于创建的对象状态;
 * 如果可用,仍然可以使用该状态。
 */
public interface FactoryBean<T> {
	/**
	 * 一个属性的名称,可以被设置在一个 {@link org.springframework.beans.factory.config.BeanDefinition} 上
	 * 以便于工厂bean可以信号化当他们的对象类型无法从工厂bean类中推断出来的时候。
	 * @since 5.2
	 */
	String OBJECT_TYPE_ATTRIBUTE = "factoryBeanObjectType";

    /**
     * 返回bean的类型,如果不可用则返回null。
     * 用于在装配期间检查特定类型的bean是否可用,例如在自动装配期间。
     * 在创建一个单例对象时,此方法应尽可能避免创建单例对象;它应该提前估计类型。
     * 对于原型,返回一个有意义的类型也是可取的。
     * 此方法可以在FactoryBean被完全初始化之前调用。
     * 它不能依赖于初始化期间创建的状态;如果可用,仍然可以使用该状态。
     * 自动装配将简单地忽略返回null的FactoryBeans;
     * 因此,建议正确实现此方法,使用FactoryBean的当前状态。
     * @return bean的类型,或者如果在调用时不可用,则为null
     * @see ListableBeanFactory#getBeansOfType
     */
    Class<?> getObjectType();

    /**
      * 返回一个对象(可以是null),可能会抛出异常。
      * @return 新创建的对象(可以是null)
      * @throws Exception 在创建对象时发生错误
      */
    @Nullable
    T getObject() throws Exception;

    /**
      * 是由这个工厂创建的对象单例吗?也就是说,`{getObject()}`始终返回同一个对象(可以缓存的引用)吗?
      * <p>**注意:**如果FactoryBean指示持有单例对象,则从`{getObject()}`返回的对象
      * 可能会被拥有者的BeanFactory缓存。
      * 因此,只有在FactoryBean始终显示地返回相同引用时才返回`{true}`。
      * FactoryBean自身的单例状态通常由拥有者提供的BeanFactory提供。
      * 通常,它必须在那边定义为单例。
      * <p>**注意:**如果此方法返回`{false}`,并不一定表示返回的对象是独立的实例。
      * `SmartFactoryBean`接口的扩展实现可以显式地指示独立实例。
      * 未实现此扩展接口的plain `FactoryBean`实现如果`{isSingleton()}`实现返回`{false}`
      * 则简单地假设返回独立实例。
      * <p>默认实现返回`{true}`,因为`{FactoryBean}`通常管理一个单例实例。
      * @return 如果暴露的对象是单例,则返回`{true}`
      * @see #getObject()
      * @see SmartFactoryBean#isPrototype()
      */
    default boolean isSingleton() {
        return true;
    }

}

缓存中获取单例Bean

单例在Spring的同一个容器内只会被创建一次,后续再获取Bean直接从单例缓存中获取,当然这里也只是尝试加载,首先尝试从缓存中加载,然后再次尝试从singletonFactories中加载。因为在创建单例的时候会存在依赖注入的情况,而在创建依赖的时候为了避免循环依赖,在Spring中创建bean的原则是不等Bean创建完成就会将创建Bean的ObjectFactory提前加入到缓存中,一旦下一个bean创建的时候需要依赖上一个bean,则直接使用ObjectFactory。代码如下:

	@Override
	@Nullable
	public Object getSingleton(String beanName) {
		return getSingleton(beanName, true);
	}

	/**
	 * 返回注册在给定名称下的原始单例对象。
	 * <p>检查已经实例化的单例对象,并且还允许引用当前正在创建的单例对象(解决循环引用)。
	 * @param beanName 要查找的bean的名称
	 * @param allowEarlyReference 是否允许创建早期引用
	 * @return 注册的单例对象,如果未找到则返回null
	 */
	@Nullable
	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
	    // 快速检查是否存在实例而不获取完整的单例锁
	    Object singletonObject = this.singletonObjects.get(beanName);
	    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
	        singletonObject = this.earlySingletonObjects.get(beanName);
	        if (singletonObject == null && allowEarlyReference) {
	            synchronized (this.singletonObjects) {
	                // 在完整单例锁内一致创建早期引用
	                singletonObject = this.singletonObjects.get(beanName);
	                if (singletonObject == null) {
	                    singletonObject = this.earlySingletonObjects.get(beanName);
	                    if (singletonObject == null) {
	                        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
	                        if (singletonFactory != null) {
	                            singletonObject = singletonFactory.getObject();
	                            this.earlySingletonObjects.put(beanName, singletonObject);
	                            this.singletonFactories.remove(beanName);
	                        }
	                    }
	                }
	            }
	        }
	    }
	    return singletonObject;
	}

这个方法首先尝试从singletonObjects里面获取实例,如果取不到再从earlySingletonObjects里面获取,如果还取不到则尝试从singletonFactories获取ObjectFactory,然后再调用这个ObjectFactory的getObject()函数来创建bean,并放到earlySingletonObjects中,并从singletonFactories中remove这个ObjectFactory,而对于后续的所有内存操作都只为了循环依赖检测时候使用,也就是allowEarlyReference为true的时候才会使用。

getSingleton函数还可以根据指定的bean名称和ObjectFactory获取Bean实例,这个方法首先尝试从singletonObjects里面获取实例,如果取不到再调用这个ObjectFactory的getObject()函数来创建bean。代码如下:

	/**
	 * 返回注册在给定名称下的原始单例对象,如果尚未注册,则创建并注册一个新的对象。
	 * @param beanName 贝恩对象的名称
	 * @param singletonFactory 用于在需要时延迟创建单例对象的ObjectFactory对象
	 * @return 注册的单例对象
	 */
	public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
	    Assert.notNull(beanName, "Bean name 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!)");
	            }
	            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 {
	                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;
	    }
	}

从Bean的实例中获取对象

在getBean方法中,getObjectForBeanInstance是个高频率使用的方法,无论是从缓存中获取Bean还是根据不同的scope策略加载Bean。总之,我们得到Bean的实例后要做的第一步就是调用这个方法来检测一下正确性,其实就是用于检测当前Bean是否是FactoryBean类型的Bean,如果是那么需要调用该Bean对应的FactoryBean实例中的getObject()作为返回值。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#getObjectForBeanInstance代码如下:

	/**
	 * 重写此方法以在程序matically在{@link Supplier}回调期间获取进一步的bean时将当前创建的bean注册为dependent。
	 * @since 5.0
	 * @see #obtainFromSupplier
	 */
	@Override
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		String currentlyCreatedBean = this.currentlyCreatedBean.get();
		if (currentlyCreatedBean != null) {
			registerDependentBean(beanName, currentlyCreatedBean);
		}

		return super.getObjectForBeanInstance(beanInstance, name, beanName, mbd);
	}

基类org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance源码如下:

	/**
	 * 获取给定bean实例的对象,该对象可以是bean实例本身或者是FactoryBean创建的对象。
	 * @param beanInstance 共享的bean实例
	 * @param name 可能包含工厂引用前缀的名称
	 * @param beanName 规范的bean名称
	 * @param mbd 合并后的bean定义
	 * @return 要公开的bean对象
	 */
	protected Object getObjectForBeanInstance(
			Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {

		// 如果指定的name是工厂相关(以&为前缀)且beanInstance又不是FactoryBean类型则验证不通过。
		if (BeanFactoryUtils.isFactoryDereference(name)) {
			if (beanInstance instanceof NullBean) {
				return beanInstance;
			}
			if (!(beanInstance instanceof FactoryBean)) {
				throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
			}
			if (mbd != null) {
				mbd.isFactoryBean = true;
			}
			return beanInstance;
		}

		// 现在我们有了bean实例,它可能是一个普通bean或FactoryBean。
		// 如果它是FactoryBean,我们使用它来创建一个bean实例,除非调用者实际上想要一个工厂引用。
		if (!(beanInstance instanceof FactoryBean<?> factoryBean)) {
			return beanInstance;
		}

		Object object = null;
		if (mbd != null) {
			mbd.isFactoryBean = true;
		}
		else {
            // 尝试从缓存中加载Bean
			object = getCachedObjectForFactoryBean(beanName);
		}
		if (object == null) {
			// 从工厂返回bean实例。
			// 如果工厂是单例,则缓存FactoryBean获取的实例。
			if (mbd == null && containsBeanDefinition(beanName)) {
				mbd = getMergedLocalBeanDefinition(beanName);
			}
            // 是否是用户定义的而不是引用程序本身定义的
			boolean synthetic = (mbd != null && mbd.isSynthetic());
			object = getObjectFromFactoryBean(factoryBean, beanName, !synthetic);
		}
		return object;
	}

上述代码最终将从Factory解析Bean的工作委托给getObjectFromFactoryBean。该函数从给定的FactoryBean中获取对象。如果FactoryBean是单例且已经存在缓存中,则直接返回。否则,它会调用FactoryBean的getObject()方法来获取对象,并根据需要进行后处理。如果存在循环依赖,则可能会在获取对象期间重复获取对象,所以需要检查并处理这种情况。最后,根据是否为单例对象,在缓存中存储对象。

	/**
	 * 从给定的FactoryBean获取对象
	 * @param factory FactoryBean实例
	 * @param beanName Bean的名称
	 * @param shouldPostProcess 是否对Bean进行后处理
	 * @return 从FactoryBean中获取的对象
	 * @throws BeanCreationException 如果FactoryBean对象创建失败
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
	    if (factory.isSingleton() && containsSingleton(beanName)) {
	        synchronized (getSingletonMutex()) {
	            Object object = this.factoryBeanObjectCache.get(beanName);
	            if (object == null) {
	                object = doGetObjectFromFactoryBean(factory, beanName);
	                // 只有在上面的getObject()调用中没有放入时才进行后处理和存储
	                // (例如,因为自定义getBean调用触发的循环引用处理)
	                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
	                if (alreadyThere != null) {
	                    object = alreadyThere;
	                }
	                else {
	                    if (shouldPostProcess) {
	                        if (isSingletonCurrentlyInCreation(beanName)) {
	                            // 临时返回未后处理的单例对象,尚未存储...
	                            return object;
	                        }
	                        beforeSingletonCreation(beanName);
	                        try {
	                            object = postProcessObjectFromFactoryBean(object, beanName);
	                        }
	                        catch (Throwable ex) {
	                            throw new BeanCreationException(beanName,
	                                    "FactoryBean的单例对象的后处理失败", ex);
	                        }
	                        finally {
	                            afterSingletonCreation(beanName);
	                        }
	                    }
	                    if (containsSingleton(beanName)) {
	                        this.factoryBeanObjectCache.put(beanName, object);
	                    }
	                }
	            }
	            return object;
	        }
	    }
	    else {
	        Object object = doGetObjectFromFactoryBean(factory, beanName);
	        if (shouldPostProcess) {
	            try {
	                object = postProcessObjectFromFactoryBean(object, beanName);
	            }
	            catch (Throwable ex) {
	                throw new BeanCreationException(beanName, "FactoryBean对象的后处理失败", ex);
	            }
	        }
	        return object;
	    }
	}

其中doGetObjectFromFactoryBean函数用于从给定的FactoryBean中获取对象。它首先尝试调用FactoryBean.getObject()方法获取对象,如果抛出FactoryBeanNotInitializedException异常,则抛出BeanCurrentlyInCreationException异常;如果抛出其他异常,则抛出BeanCreationException异常。如果获取的对象为null,则判断是否FactoryBean正在创建中,如果是,则抛出BeanCurrentlyInCreationException异常;否则,创建一个NullBean对象并返回。

	/**
	 * 从给定的FactoryBean获取要暴露的对象。
	 *
	 * @param factory FactoryBean实例
	 * @param beanName 被引用对象的名称
	 * @return 从FactoryBean获取的对象
	 * @throws BeanCreationException 如果FactoryBean对象创建失败
	 * @see org.springframework.beans.factory.FactoryBean#getObject()
	 */
	private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
	    Object object;
	    try {
	        object = factory.getObject();
	    }
	    catch (FactoryBeanNotInitializedException ex) {
	        throw new BeanCurrentlyInCreationException(beanName, ex.toString());
	    }
	    catch (Throwable ex) {
	        throw new BeanCreationException(beanName, "FactoryBean在对象创建时抛出了异常", ex);
	    }

	    // 对于尚未完全初始化的FactoryBean,不接受一个null值:
	    // 许多FactoryBean只是在getObject时返回null。
	    if (object == null) {
	        if (isSingletonCurrentlyInCreation(beanName)) {
	            throw new BeanCurrentlyInCreationException(
	                    beanName, "正在创建中的FactoryBean从getObject返回了null");
	        }
	        object = new NullBean();
	    }
	    return object;
	}

getObjectFromFactoryBean函数在调用doGetObjectFromFactoryBean获取到Bean后会调用postProcessObjectFromFactoryBean进行进一步的操作。

	/**
	 * 对注册的BeanPostProcessors中的每个BeanPostProcessor应用`postProcessAfterInitialization`回调方法,
	 * 给它们一个机会来处理从FactoryBeans获取的对象(例如,自动代理)。
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	@SuppressWarnings("deprecation")
	@Override
	protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
	    return applyBeanPostProcessorsAfterInitialization(object, beanName);
	}

	/**
	 * 应用初始化后对bean进行后处理
	 *
	 * @param existingBean 存在的bean对象
	 * @param beanName bean名称
	 * @return 后处理结果
	 * @throws BeansException 如果在后处理过程中出现异常,抛出BeansException异常
	 * @since 6.1
	 */
	@Deprecated(since = "6.1")
	@Override
	public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
	    Object result = existingBean;
	    for (BeanPostProcessor processor : getBeanPostProcessors()) {
	        Object current = processor.postProcessAfterInitialization(result, beanName);
	        if (current == null) {
	            return result;
	        }
	        result = current;
	    }
	    return result;
	}

回到getObjectFromFactoryBean函数中,其在单例模式下,会调用postProcessObjectFromFactoryBean前后会分别调用beforeSingletonCreation和afterSingletonCreation,部分源码如下:

		beforeSingletonCreation(beanName);
		try {
			object = postProcessObjectFromFactoryBean(object, beanName);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName,
				"Post-processing of FactoryBean's singleton object failed", ex);
		}
		finally {
			afterSingletonCreation(beanName);
		}

beforeSingletonCreation函数的逻辑很简单,主要是记录加载状态,即通过singletonsCurrentlyInCreation.add(beanName)将当前正在创建的bean记录到缓存中,这样便于对循环依赖进行检测。如果singletonsCurrentlyInCreation已经有了指定的beanName,再添加该beanName就会抛出BeanCurrentlyInCreationException异常错误。

	/**
	 * 在创建单例之前调用的回调方法。
	 * <p>
	 * 默认实现会将该单例注册为正在创建状态。
	 * @param beanName 即将被创建的单例的名称
	 * @see #isSingletonCurrentlyInCreation
	 */
	protected void beforeSingletonCreation(String beanName) {
	    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
	        throw new BeanCurrentlyInCreationException(beanName);
	    }
	}

当bean加载结束后就会调用afterSingletonCreation函数将当前的beanName从singletonsCurrentlyInCreation移除,源码如下:

	/**
	 * 在单例创建后的回调方法。
	 * <p>
	 * 默认实现将该单例标记为不再处于创建状态。
	 * @param beanName 已创建的单例的名称
	 * @see #isSingletonCurrentlyInCreation
	 */
	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的创建,请参考Spring源码解析——创建Bean

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值