跳至主要內容

8.开启 Bean 的加载

Java突击队大约 36 分钟

8.开启 Bean 的加载

该系列文章是本人在学习 Spring 的过程中总结下来的,里面涉及到相关源码,可能对读者不太友好,请结合我的源码注释 Spring 源码分析 GitHub 地址open in new window 进行阅读

Spring 版本:5.1.14.RELEASE

开始阅读这一系列文章之前,建议先查看《深入了解 Spring IoC(面试题)》open in new window这一篇文章

该系列其他文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》open in new window

开启 Bean 的加载

前面的一些列文章对面向资源(XML、Properties)面向注解定义的 Bean 是如何被解析成 BeanDefinition(Bean 的“前身”),并保存至 BeanDefinitionRegistry 注册中心里面,实际也是通过 ConcurrentHashMap 进行保存。

Spring 底层 IoC 容器 DefaultListableBeanFactory,实现了 BeanFactory 和 BeanDefinitionRegistry 接口,这个时候它处于“就绪状态”,当我们显示或者隐式地调用 getBean(...) 方法时,会触发加载 Bean 阶段,获取对应的 Bean。在该方法中,如果是单例模式会先从缓存中获取,已有则直接返回,没有则根据 BeanDefinition 开始初始化这个 Bean。

BeanFactory 体系结构

先来看看 BeanFactory 接口的继承关系

 

简单描述这些接口:

  • org.springframework.beans.factory.BeanFactory,Spring IoC 容器最基础的接口,提供依赖查找单个 Bean 的功能
  • org.springframework.beans.factory.ListableBeanFactory,继承 BeanFactory 接口,提供依赖查找多个 Bean 的功能
  • org.springframework.beans.factory.HierarchicalBeanFactory,继承 BeanFactory 接口,提供获取父 BeanFactory 的功能,具有层次性
  • org.springframework.beans.factory.config.ConfigurableBeanFactory,继承 HierarchicalBeanFactory 接口,提供可操作内部相关组件的功能,具有可配置性
  • org.springframework.beans.factory.config.AutowireCapableBeanFactory,继承 BeanFactory 接口,提供可注入的功能,支持依赖注入
  • org.springframework.beans.factory.config.ConfigurableListableBeanFactory,继承上面所有接口,综合所有特性,还提供可提前初始化所有单例 Bean 的功能

通过这些接口的名称可以大致了解其用意,接下来我们来看看它们的实现类的继承关系

 

简单描述这些实现类:

  • org.springframework.beans.factory.support.AbstractBeanFactory 抽象类,实现 ConfigurableBeanFactory 接口,基础实现类,Bean 的创建过程交由子类实现
  • org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory 抽象类,继承 AbstractBeanFactory,实现 AutowireCapableBeanFactory 接口,完成 Bean 的创建
  • org.springframework.beans.factory.support.DefaultListableBeanFactory,Spring 底层 IoC 容器,依赖注入的底层实现

其他的接口和类和 BeanDefinition 注册中心,别名注册中心,单例 Bean 注册中心相关;右下角的 ApplicationContext 与 Spring 应用上下文有关,它的整个体系这里不做展述,在后面的文章进行分析

AbstractBeanFactory

org.springframework.beans.factory.support.AbstractBeanFactory 抽象类,实现 ConfigurableBeanFactory 接口,BeanFactory 的基础实现类,提供依赖查找方法,可获取 Bean 对象,接下来我们来看看依赖查找的实现

getBean 方法

getBean(String name) 方法,根据名称获取 Bean,当然还有许多重载方法,如下:

@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);
}

public <T> T getBean(String name, @Nullable Class<T> requiredType, @Nullable Object... args)
        throws BeansException {
    return doGetBean(name, requiredType, args, false);
}

最终都会调用 doGetBean(...) 这个方法

当我们显示或者隐式地调用这个方法时,会触发 Bean 的加载;你是否会有疑问,我们使用 Spring 的过程中并不会调用这个方法去获取 Bean,那这个方法会被谁调用呢?在 ConfigurableListableBeanFactory 接口中提供提前初始化所有单例 Bean 的功能,在 Spring 应用上下文(ApplicationContext)刷新阶段会提前初始化所有的单例 Bean,这个提前初始化也是调用 getBean 这个方法,这部分内容在后续分析 Spring 应用上下文的生命周期会讲到

【核心】doGetBean 方法

doGetBean(final String name, @Nullable final Class<T> requiredType, @Nullable final Object[] args, boolean typeCheckOnly) 方法,获取一个 Bean,方法如下:

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
        @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {

    // `<1>` 获取 beanName
    // 因为入参 name 可能是别名,也可能是 FactoryBean 类型 Bean 的名称(& 开头,需要去除)
    // 所以需要获取真实的 beanName
    final String beanName = transformedBeanName(name);
    Object bean;

    // `<2>` 先从缓存(仅缓存单例 Bean )中获取 Bean 对象,这里缓存指的是 3 个 Map
    // 缓存中也可能是正在初始化的 Bean,可以避免**循环依赖注入**引起的问题
    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    // `<3>` 若从缓存中获取到对应的 Bean,且 args 参数为空
    if (sharedInstance != null && args == null) {
        if (logger.isTraceEnabled()) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +
                        "' that is not fully initialized yet - a consequence of a circular reference");
            }
            else {
                logger.trace("Returning cached instance of singleton bean '" + beanName + "'");
            }
        }
        // `<3.1>` 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
        // 否则,调用 FactoryBean#getObject() 获取目标对象
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    // 缓存中没有对应的 Bean,则开启 Bean 的加载
    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        // <4> 如果**非单例模式**下的 Bean 正在创建,这里又开始创建,表明存在循环依赖,则直接抛出异常
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // <5> 如果从当前容器中没有找到对应的 BeanDefinition,则从父容器中加载(如果存在父容器)
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
            // Not found -> check parent.
            // `<5.1>` 获取 beanName,因为可能是别名,则进行处理
            // 和第 1 步不同,不需要对 & 进行处理,因为进入父容器重新依赖查找
            String nameToLookup = originalBeanName(name);
            // <5.2> 若为 AbstractBeanFactory 类型,委托父容器的 doGetBean 方法进行处理
            // 否则,就是非 Spring IoC 容器,根据参数调用相应的 getBean(...)方法
            if (parentBeanFactory instanceof AbstractBeanFactory) {
                return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
            }
            else if (args != null) {
                return (T) parentBeanFactory.getBean(nameToLookup, args);
            }
            else if (requiredType != null) {
                return parentBeanFactory.getBean(nameToLookup, requiredType);
            }
            else {
                return (T) parentBeanFactory.getBean(nameToLookup);
            }
        }

        // `<6>` 如果不是仅仅做类型检查,则表示需要创建 Bean,将 beanName 标记为已创建过
        if (!typeCheckOnly) {
            markBeanAsCreated(beanName);
        }

        try {
            // `<7>` 从容器中获取 beanName 对应的的 RootBeanDefinition(合并后)
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 检查是否为抽象类
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            // `<8>` 获取当前正在创建的 Bean 所依赖对象集合(depends-on 配置的依赖)
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // <8.1> 检测是否存在循环依赖,存在则抛出异常
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // `<8.2>` 将 beanName 与 dep 之间依赖的关系进行缓存
                    registerDependentBean(dep, beanName);
                    try {
                        // `<8.3>` 先创建好依赖的 Bean(重新调用 getBean(...) 方法)
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // Create bean instance.
            // <9> 开始创建 Bean,不同模式创建方式不同
            if (mbd.isSingleton()) { // <9.1> 单例模式
                /*
                 * <9.1.1> 创建 Bean,成功创建则进行缓存,并移除缓存的早期对象
                 * 创建过程实际调用的下面这个 createBean(...) 方法
                 */
                sharedInstance = getSingleton(beanName,
                        // ObjectFactory 实现类
                        () -> {
                            try {
                                // **【核心】** 创建 Bean
                                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.
                                // 如果创建过程出现异常,则显式地从缓存中删除当前 Bean 相关信息
                                // 在单例模式下为了解决循环依赖,创建过程会缓存早期对象,这里需要进行删除
                                destroySingleton(beanName);
                                throw ex;
                            }
                });
                // `<9.1.2>` 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
                // 否则,调用 FactoryBean#getObject() 获取目标对象
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            // <9.2> 原型模式
            else if (mbd.isPrototype()) {
                // It's a prototype -> create a new instance.
                Object prototypeInstance = null;
                try {
                    // `<9.2.1>` 将 beanName 标记为原型模式正在创建
                    beforePrototypeCreation(beanName);
                    // <9.2.2> **【核心】** 创建 Bean
                    prototypeInstance = createBean(beanName, mbd, args);
                }
                finally {
                    // `<9.2.3>` 将 beanName 标记为不在创建中,照应第 9.2.1 步
                    afterPrototypeCreation(beanName);
                }
                // `<9.2.4>` 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
                // 否则,调用 FactoryBean#getObject() 获取目标对象
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }
            // <9.3> 其他模式
            else {
                // `<9.3.1>` 获取该模式的 Scope 对象 scope,不存在则抛出异常
                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 {
                    // `<9.3.1>` 从 scope 中获取 beanName 对应的对象(看你的具体实现),不存在则执行**原型模式**的四个步骤进行创建
                    Object scopedInstance = scope.get(beanName, () -> {
                        // 将 beanName 标记为原型模式正在创建
                        beforePrototypeCreation(beanName);
                        try {
                            // **【核心】** 创建 Bean
                            return createBean(beanName, mbd, args);
                        }
                        finally {
                            // 将 beanName 标记为不在创建中,照应上一步
                            afterPrototypeCreation(beanName);
                        }
                    });
                    // 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
                    // 否则,调用 FactoryBean#getObject() 获取目标对象
                    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;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    // `<10>` 如果入参 requiredType 不为空,并且 Bean 不是该类型,则需要进行类型转换
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // `<10.1>` 通过类型转换机制,将 Bean 转换成 requiredType 类型
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            // <10.2> 转换后的 Bean 为空则抛出异常
            if (convertedBean == null) {
                // 转换失败,抛出 BeanNotOfRequiredTypeException 异常
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            // <10.3> 返回类型转换后的 Bean 对象
            return convertedBean;
        }
        catch (TypeMismatchException ex) {
            if (logger.isTraceEnabled()) {
                logger.trace("Failed to convert bean '" + name + "' to required type '" +
                        ClassUtils.getQualifiedName(requiredType) + "'", ex);
            }
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
    }
    // <11> 返回获取到的 Bean
    return (T) bean;
}

这个方法的处理过程有点长,如下:

1、 获取beanName,因为入参name可能是别名,也可能是FactoryBean类型Bean的名称(&开头,需要去除),所以需要获取真实的beanName
2、 先从缓存(仅缓存单例Bean)中获取Bean对象,这里缓存指的是3个Map;缓存中也可能是正在初始化的Bean,可以避免循环依赖注入引起的问题;
3、 若从缓存中获取到对应的Bean,且args参数为空;

1、 **【同】**调用getObjectForBeanInstance(ObjectbeanInstance,Stringname,StringbeanName,@NullableRootBeanDefinitionmbd)方法;

    获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回,否则,调用 FactoryBean\#getObject() 获取目标对象

缓存中没有对应的 Bean,则开启 Bean 的加载

1、 如果非单例模式下的Bean正在创建,这里又开始创建,表明存在循环依赖,则直接抛出异常;
2、 如果从当前容器中没有找到对应的BeanDefinition,则从父容器中加载(如果存在父容器);

1、 获取beanName,因为可能是别名,则进行处理,和第1步不同,不需要对&进行处理,因为进入父容器重新依赖查找;
2、 若为AbstractBeanFactory类型,委托父容器的doGetBean方法进行处理;否则,就是非SpringIoC容器,根据参数调用相应的getBean(...)方法;
3、 如果不是仅仅做类型检查,则表示需要创建Bean,将beanName标记为已创建过,在后面的循环依赖检查中会使用到;
4、 从容器中获取beanName对应的的RootBeanDefinition(合并后),调用getMergedLocalBeanDefinition(StringbeanName)方法;
5、 获取当前正在创建的Bean所依赖对象集合(depends-on配置的依赖);

1、 检测是否存在循环依赖,存在则抛出异常;
2、beanNamedep之间依赖的关系进行缓存;
3、 先创建好依赖的Bean(重新调用getBean(...)方法);


1、 开始创建Bean,不同模式创建方式不同;

1、 单例模式

1.  创建 Bean,成功创建则进行缓存,并移除缓存的早期对象,调用 `getSingleton(String beanName, ObjectFactory<?> singletonFactory)` 方法
    
        **【核心】**入参的 ObjectFactory 实现类就是调用的 AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[]) 方法
2.  **【同】** 和上面的 `3.1` 相同操作

2、 原型模式

1.  将 `beanName` 标记为**非单例模式**正在创建
    2.  **【核心】** 创建 Bean,调用 AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[]) 方法
3.  将 `beanName` 标记为不在创建中,照应第 `9.2.1` 步
4.  **【同】** 和上面的 `3.1` 相同操作

3、 其他模式

1.  获取该模式的 Scope 对象 `scope`,不存在则抛出异常
2.  从 `scope` 中获取 `beanName` 对应的对象(看你的具体实现),不存在则执行**原型模式**的四个步骤进行创建

1、 如果入参requiredType不为空,并且Bean不是该类型,则需要进行类型转换;

1、 通过类型转换机制,将Bean转换成requiredType类型;
2、 转换后的Bean为空则抛出异常;
3、 返回类型转换后的Bean对象;
2、 返回获取到的Bean;


概括:

  • 可以看到这个方法加载 Bean 的过程中,会先从缓存中获取单例模式的 Bean;
  • 不管是从缓存中获取的还是新创建的,都会进行处理,如果是 FactoryBean 类型则调用其 getObject() 获取目标对象;
  • BeanFactory 可能有父容器,如果当前容器找不到 BeanDefinition 则会尝试让父容器创建;
  • 创建 Bean 的任务交由 AbstractAutowireCapableBeanFactory 去完成;
  • 如果获取到的 Bean 不是我们想要类型,会通过类型转换机制转换成目标类型

接下来依次分析上述过程的相关步骤(doGetBean(...)

1. 获取 beanName

对应代码段:

// AbstractBeanFactory.java
final String beanName = transformedBeanName(name);

因为入参 name 可能是别名,也可能是 FactoryBean 类型 Bean 的名称(& 开头,需要去除),所以需要进行一番转换,如下:

// AbstractBeanFactory.java
protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}
// BeanFactoryUtils.java
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }
    // 获取 name 对应的 beanName,
    // 不为 null 则返回 transformedBeanNameCache 缓存中对应的 beanName,
    // 为 null 则对 name 进行处理,将前缀 '&' 去除,直至没有 '&',然后放入 transformedBeanNameCache 缓存中,并返回处理后的 beanName
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}
// SimpleAliasRegistry.java
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    // 循环,从 aliasMap 中,获取到最终的 beanName
    do {
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    }
    while (resolvedName != null);
    return canonicalName;
}

过程并不复杂,先将前缀 & 去除(如果存在),如果是别名则获取对应的 beanName

定义了一个 FactoryBean 类型的 Bean,名称为 user,通过 user 获取 Bean,获取到的是 FactoryBean#getObject() 返回的对象(只会被调用一次)

通过 &user 获取 Bean,获取到的是 FactoryBean 本身这个对象

2. 从缓存中获取单例 Bean

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
Object sharedInstance = getSingleton(beanName);

单例模式的 Bean 被创建后会缓存,为了避免循环依赖注入,在创建过程会临时缓存正在创建的 Bean(早期 Bean),在后续文章会讲到,从缓存中获取对象过程如下:

// DefaultSingletonBeanRegistry.java

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

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // `<1>` **【一级 Map】**从单例缓存 singletonObjects 中获取 beanName 对应的 Bean
    Object singletonObject = this.singletonObjects.get(beanName);
    // <2> 如果**一级 Map**中不存在,且当前 beanName 正在创建
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // `<2.1>` 对 singletonObjects 加锁
        synchronized (this.singletonObjects) {
            // `<2.2>` **【二级 Map】**从 earlySingletonObjects 集合中获取,里面会保存从 **三级 Map** 获取到的正在初始化的 Bean
            singletonObject = this.earlySingletonObjects.get(beanName);
            // <2.3> 如果**二级 Map** 中不存在,且允许提前创建
            if (singletonObject == null && allowEarlyReference) {
                // `<2.3.1>` **【三级 Map】**从 singletonFactories 中获取对应的 ObjectFactory 实现类
                ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                // 如果从**三级 Map** 中存在对应的对象,则进行下面的处理
                if (singletonFactory != null) {
                    // <2.3.2> 调用 ObjectFactory#getOject() 方法,获取目标 Bean 对象(早期半成品)
                    singletonObject = singletonFactory.getObject();
                    // <2.3.3> 将目标对象放入**二级 Map**
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    // `<2.3.4>` 从**三级 Map**移除 beanName
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    // <3> 返回从缓存中获取的对象
    return singletonObject;
}

过程如下:

1、 【一级Map】从单例缓存singletonObjects中获取beanName对应的Bean;
2、 如果
一级Map
中不存在,且当前beanName正在创建;

1、singletonObjects加锁;
2、 【二级Map】earlySingletonObjects集合中获取,里面会保存从三级Map获取到的正在初始化的Bean;
3、 如果二级Map中不存在,且允许提前创建;

1.  **【三级 Map】**从 `singletonFactories` 中获取对应的 ObjectFactory 实现类,如果从**三级 Map** 中存在对应的对象,则进行下面的处理
    2.  调用 ObjectFactory\#getOject() 方法,获取目标 Bean 对象(早期半成品)
3.  将目标对象放入**二级 Map**
4.  从**三级 Map**移除 beanName

3、 返回从缓存中获取的对象;

这个过程对应《深入了解 Spring IoC(面试题)》open in new window中的BeanFactory 是如何处理循环依赖问题

3. FactoryBean 的处理

一般情况下,Spring 通过反射机制利用 Bean 的 beanClass 属性指定实现类来实例化 Bean。某些情况下,Bean 的实例化过程比较复杂,如果按照传统的方式,则需要提供大量的配置信息,配置方式的灵活性有限,这时采用编码的方式可能会得到一个简单的方案。Spring 为此提供了一个 FactoryBean 的工厂 Bean 接口,用户可以通过实现该接口定制实例化 Bean 的逻辑。

FactoryBean 接口对于 Spring 框架本身也非常重要,其内部就提供了大量 FactoryBean 的实现。它们隐藏了实例化过程中一些复杂细节,给上层应用带来了便利。

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);

不管是从缓存中获取的还是新创建的,都会调用这个方法进行处理,如果是 FactoryBean 类型则调用其 getObject() 获取目标对象

getObjectForBeanInstance 方法

// AbstractBeanFactory.java
protected Object getObjectForBeanInstance( Object beanInstance, String name, String beanName, 
                                          @Nullable RootBeanDefinition mbd) {
    // Don't let calling code try to dereference the factory if the bean isn't a factory.
    // `<1>` 若 name 以 & 开头,说明想要获取 FactoryBean,则校验其**正确性**
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        // <1.1> 如果是 NullBean 空对象,则直接返回
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // <1.2> 如果不是 FactoryBean 类型,则抛出异常
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
    }

    // Now we have the bean instance, which may be a normal bean or a FactoryBean.
    // If it's a FactoryBean, we use it to create a bean instance, unless the caller actually wants a reference to the factory.
    // 到这里我们就有了一个 Bean,可能是一个正常的 Bean,也可能是一个 FactoryBean
    // 如果是 FactoryBean,则需要通过其 getObject() 方法获取目标对象

    // `<2>` 如果 beanInstance 不是 FactoryBean 类型,不需要再处理则直接返回
    // 或者(表示是 FactoryBean 类型) name 以 & 开头,表示你想要获取实际 FactoryBean 对象,则直接返回
    // 还不符合条件的话,表示是 FactoryBean,需要获取 getObject() 返回目标对象
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    // `<3>` 如果入参没有传 BeanDefinition,则从 factoryBeanObjectCache 缓存中获取对应的 Bean 对象
	// 入参传了 BeanDefinition 表示这个 Bean 是刚创建的,不走缓存,需要调用其 getObject() 方法获取目标对象
	// factoryBeanObjectCache:FactoryBean#getObject() 调用一次后返回的目标对象缓存在这里
    if (mbd == null) {
        object = getCachedObjectForFactoryBean(beanName);
    }
    // `<4>` 若第 3 步获取的对象为空,则需要调用 FactoryBean#getObject() 获得对象
    if (object == null) {
        // Return bean instance from factory.
        // `<4.1>` 将 beanInstance 转换成 FactoryBean 类型
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        // <4.2> 如果入参没有传 BeanDefinition 并且当前容器存在对应的 BeanDefinition
        if (mbd == null && containsBeanDefinition(beanName)) {
            // 获取对应的 RootBeanDefinition(合并后)
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        // 是否是用户定义的(不是 Spring 创建解析出来的)
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // `<4.3>` **【核心】**通过 FactoryBean 获得目标对象,单例模式会缓存在 factoryBeanObjectCache 中
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

过程如下:

1、name&开头,说明想要获取FactoryBean,则校验其正确性

1、 如果是NullBean空对象,则直接返回;
2、 如果不是FactoryBean类型,则抛出异常;
2、 如果beanInstance不是FactoryBean类型,不需要再处理则直接返回;或者(表示是FactoryBean类型)name&开头,表示你想要获取实际FactoryBean对象,则直接返回;还不符合条件的话,表示是FactoryBean,需要获取getObject()返回目标对象,往下处理
3、 如果入参没有传BeanDefinition,则从factoryBeanObjectCache缓存中获取对应的Bean对象,如下:;

// FactoryBeanRegistrySupport.java
protected Object getCachedObjectForFactoryBean(String beanName) {
    return this.factoryBeanObjectCache.get(beanName);
}

factoryBeanObjectCache:FactoryBean\#getObject() 调用一次后返回的目标对象缓存在这里

入参传了 BeanDefinition 表示这个 Bean 是刚创建的,不走缓存,需要调用其 getObject() 方法获取目标对象
4. 若第 3 步获取的对象为空,则需要调用 FactoryBean#getObject() 获得对象

1、beanInstance转换成FactoryBean类型;
2、 如果入参没有传BeanDefinition并且当前容器存在对应的BeanDefinition,则获取对应的RootBeanDefinition(合并后);
3、 **【核心】**通过FactoryBean获得目标对象,单例模式会缓存在factoryBeanObjectCache中,调用getObjectFromFactoryBean(FactoryBean<?>,String,boolean)方法;

getObjectFromFactoryBean 方法

getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) 方法,获取 FactoryBean 的目标对象,方法如下:

// FactoryBeanRegistrySupport.java
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    // `<1>` factory 为单例模式,且单例 Bean 缓存中存在 beanName 对应的 FactoryBean 对象
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) { // <1.1> 获取单例锁,保证安全
            // `<1.2>` 从 factoryBeanObjectCache 缓存中获取 FactoryBean#getObject() 创建的目标对象
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                // `<1.3>` 则根据 factory 获取目标对象,调用 FactoryBean#getObject() 方法
                object = doGetObjectFromFactoryBean(factory, beanName);
                // Only post-process and store if not put there already during getObject() call above
                // (e.g. because of circular reference processing triggered by custom getBean calls)
                // <1.4> 这里再进行一次校验,看是否在缓存中存在 FactoryBean 创建的目标对象,如果有则优先从缓存中获取
                // 保证 FactoryBean#getObject() 只能被调用一次
                // 没有的话,则对刚获取到的目标对象进行接下来的处理
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                } else {
                    // <1.5> 是否需要后续处理,这个 FactoryBean 的前身 BeanDefinition 是否由 Spring 解析出来的,通常情况下都是
                    if (shouldPostProcess) {
                        // <1.5.1> 若该 FactoryBean 处于创建中,则直接返回这个目标对象,不进行接下来的处理过程
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        // `<1.5.2>` 前置处理,将 beanName 标志为正在创建
                        beforeSingletonCreation(beanName);
                        try {
                            // <1.5.3> 对通过 FactoryBean 获取的目标对象进行后置处理
                            // 遍历所有的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的处理)
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                    "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            // `<1.5.4>` 后置处理,将 beanName 标志为不在创建中
                            afterSingletonCreation(beanName);
                        }
                    }
                    // `<1.6>` 如果缓存中存在 beanName 对应的 FactoryBean 对象
                    // 上面不是判断了吗?也可能在上面的处理过程会有所变化,所以这里在做一层判断
                    // 目的:缓存 FactoryBean 创建的目标对象,则需要保证 FactoryBean 本身这个对象存在缓存中
                    if (containsSingleton(beanName)) {
                        // `<1.6.1>` 将这个 FactoryBean 创建的目标对象保存至 factoryBeanObjectCache
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            // <1.7> 返回 FactoryBean 创建的目标对象
            return object;
        }
    }
    // `<2>` factory 非单例模式,或单例 Bean 缓存中不存在 beanName 对应的 FactoryBean 对象
    else {
        // `<2.1>` 则根据 factory 获取目标对象,调用 FactoryBean#getObject() 方法
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        // <2.2> 是否需要后续处理,这个 FactoryBean 的前身 BeanDefinition 是否由 Spring 解析出来的,通常情况下都是
        if (shouldPostProcess) {
            try {
                // <2.2.1> 对通过 FactoryBean 获取的目标对象进行后置处理
                // 遍历所有的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的处理)
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        // <2.3> 返回 FactoryBean 创建的目标对象,非单例模式不会进行缓存
        return object;
    }
}

过程如下:

1、 factory为单例模式,且单例Bean缓存中存在beanName对应的FactoryBean对象;

1、 获取单例锁,保证安全;
2. 从 factoryBeanObjectCache 缓存中获取 FactoryBean#getObject() 创建的目标对象
3. 则根据 factory 获取目标对象,调用 FactoryBean#getObject() 方法(反射机制)
4. 这里再进行一次校验(第 1.2 已经判断过),看是否在缓存中存在 FactoryBean 创建的目标对象,如果有则优先从缓存中获取,保证 FactoryBean#getObject() 只能被调用一次;没有的话,则对刚获取到的目标对象进行接下来的处理
5、 是否需要后续处理,这个FactoryBean的BeanDefinition是否由Spring解析出来的,通常情况下都是;

1.  若该 FactoryBean 处于创建中,则直接返回这个目标对象,不进行接下来的处理过程
2.  前置处理,将 `beanName` 标志为正在创建
3.  对通过 FactoryBean 获取的目标对象进行后置处理,遍历所有的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的处理)
4.  后置处理,将 `beanName` 标志为不在创建中
5.  如果缓存中存在 `beanName` 对应的 FactoryBean 对象,上面不是判断了吗(第 `1` 步判断过)?
    
    也可能在上面的处理过程会有所变化,所以这里在做一层判断,目的:缓存 FactoryBean 创建的目标对象,则需要保证 FactoryBean 本身这个对象存在缓存中
    
    1.  将这个 FactoryBean 创建的目标对象保存至 `factoryBeanObjectCache`
6.  返回 FactoryBean 创建的目标对象

2、 factory非单例模式,或单例Bean缓存中不存在beanName对应的FactoryBean对象;

1.  则根据 factory 获取目标对象,调用 FactoryBean\#getObject() 方法(反射机制)

2、 是否需要后续处理,这个FactoryBean的BeanDefinition是否由Spring解析出来的,通常情况下都是;

1.  对通过 FactoryBean 获取的目标对象进行后置处理,遍历所有的 BeanPostProcessor 的 postProcessAfterInitialization 方法(初始化的处理)

3、 返回FactoryBean创建的目标对象,非单例模式不会进行缓存;

概括:调用 FactoryBean#getObject() 获取目标对象,单例模式会缓存起来;过程中 Sping 考虑到各种情况,例如保证单例模式下 FactoryBean#getObject() 只调用一次,是否需要进行后置处理。

4. 非单例模式依赖检查

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
if (isPrototypeCurrentlyInCreation(beanName)) {
    throw new BeanCurrentlyInCreationException(beanName);
}
protected boolean isPrototypeCurrentlyInCreation(String beanName) {
    Object curVal = this.prototypesCurrentlyInCreation.get();
    return (curVal != null && (curVal.equals(beanName) // 相等
            || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
}

prototypesCurrentlyInCreation 中保存非单例模式下正在创建的 Bean 的名称,这里又重新创建,表示出现循环依赖,则直接抛出异常

Spring 对于非单例模式的 Bean 无法进行相关缓存,也就无法处理循环依赖的情况,选择了直接抛出异常

5. BeanFactory 层次性加载 Bean 策略

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
BeanFactory parentBeanFactory = getParentBeanFactory();
// <5> 如果从当前容器中没有找到对应的 BeanDefinition,则从父容器中加载(如果存在父容器)
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
    // Not found -> check parent.
    // `<5.1>` 获取 beanName,因为可能是别名,则进行处理
    // 和第 1 步不同,不需要对 & 进行处理,因为进入父容器重新依赖查找
    String nameToLookup = originalBeanName(name);
    // <5.2> 若为 AbstractBeanFactory 类型,委托父容器的 doGetBean 方法进行处理
    // 否则,就是非 Spring IoC 容器,根据参数调用相应的 getBean(...)方法
    if (parentBeanFactory instanceof AbstractBeanFactory) {
        return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);
    }
    else if (args != null) {
        return (T) parentBeanFactory.getBean(nameToLookup, args);
    }
    else if (requiredType != null) {
        return parentBeanFactory.getBean(nameToLookup, requiredType);
    }
    else {
        return (T) parentBeanFactory.getBean(nameToLookup);
    }
}

如果当前 BeanFactory 没有对应的 BeanDefinition,也就无法创建 Bean,但是如果存在 BeanFactory,则将接下来的操作交由 BeanFactory,找不到会层层找上去,如果所有 BeanFactory 都找不到对应的 BeanDefinition 最终会抛出异常。

6. 将 beanName 标记为已创建

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
// `<6>` 如果不是仅仅做类型检查,则表示需要创建 Bean,将 beanName 标记为已创建过
if (!typeCheckOnly) {
    markBeanAsCreated(beanName);
}

如果不是仅仅做类型检查,则调用 markBeanAsCreated(String beanName) 方法,如下:

// AbstractBeanFactory.java
protected void markBeanAsCreated(String beanName) {
    // 没有创建
    if (!this.alreadyCreated.contains(beanName)) {
        // 加上全局锁
        synchronized (this.mergedBeanDefinitions) {
            // 再次检查一次:DCL 双检查模式
            if (!this.alreadyCreated.contains(beanName)) {
                // Let the bean definition get re-merged now that we're actually creating
                // the bean... just in case some of its metadata changed in the meantime.
                // 从 mergedBeanDefinitions 中删除 beanName,并在下次访问时重新创建它
                clearMergedBeanDefinition(beanName);
                // 添加到已创建 bean 集合中
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

将这个beanName 保存在 alreadyCreated 集合中(SetFromMap),在后面的循环依赖检查中会使用到

7. 获取 RootBeanDefinition

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
// `<7>` 从容器中获取 beanName 对应的的 RootBeanDefinition(合并后)
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// 检查是否为抽象类
checkMergedBeanDefinition(mbd, beanName, args);

因为我们定义的 Bean 大多数都被 Spring 解析成 GenericBeanDefinition 类型,具有父子关系,则需要获取最终的 BeanDefinition;如果存在父子关系,则会进行一系列的合并,转换成 RootBeanDefinition 对象,调用 getMergedLocalBeanDefinition(String beanName) 方法,如下:

// AbstractBeanFactory.java
protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
    // Quick check on the concurrent map first, with minimal locking.
    // 从 mergedBeanDefinitions 缓存中获取合并后的 RootBeanDefinition,存在则直接返回
    RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
    if (mbd != null) {
        return mbd;
    }
    // 获取 BeanDefinition 并转换成,如果存在父子关系则进行合并
    return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
}

protected RootBeanDefinition getMergedBeanDefinition(String beanName, BeanDefinition bd)
        throws BeanDefinitionStoreException {
    return getMergedBeanDefinition(beanName, bd, null);
}

protected RootBeanDefinition getMergedBeanDefinition(
        String beanName, BeanDefinition bd, @Nullable BeanDefinition containingBd)
        throws BeanDefinitionStoreException {

    // 加锁
    synchronized (this.mergedBeanDefinitions) {
        RootBeanDefinition mbd = null;

        // Check with full lock now in order to enforce the same merged instance.
        if (containingBd == null) {
            mbd = this.mergedBeanDefinitions.get(beanName);
        }

        if (mbd == null) {
            // 如果没有父类则直接转换成 RootBeanDefinition 对象
            if (bd.getParentName() == null) {
                // Use copy of given root bean definition.
                if (bd instanceof RootBeanDefinition) {
                    mbd = ((RootBeanDefinition) bd).cloneBeanDefinition();
                }
                else {
                    mbd = new RootBeanDefinition(bd);
                }
            }
            // 有父类则进行合并
            else {
                // Child bean definition: needs to be merged with parent.
                BeanDefinition pbd;
                try {
                    // 获取父类的对应的 BeanDefinition 对象
                    String parentBeanName = transformedBeanName(bd.getParentName());
                    if (!beanName.equals(parentBeanName)) {
                        pbd = getMergedBeanDefinition(parentBeanName);
                    }
                    else {
                        BeanFactory parent = getParentBeanFactory();
                        if (parent instanceof ConfigurableBeanFactory) {
                            pbd = ((ConfigurableBeanFactory) parent).getMergedBeanDefinition(parentBeanName);
                        }
                        else {
                            throw new NoSuchBeanDefinitionException(parentBeanName,
                                    "Parent name '" + parentBeanName + "' is equal to bean name '" + beanName +
                                    "': cannot be resolved without an AbstractBeanFactory parent");
                        }
                    }
                }
                catch (NoSuchBeanDefinitionException ex) {
                    throw new BeanDefinitionStoreException(bd.getResourceDescription(), beanName,
                            "Could not resolve parent bean definition '" + bd.getParentName() + "'", ex);
                }
                // Deep copy with overridden values.
                mbd = new RootBeanDefinition(pbd);
                // 父子合并
                mbd.overrideFrom(bd);
            }

            // Set default singleton scope, if not configured before.
            if (!StringUtils.hasLength(mbd.getScope())) {
                mbd.setScope(RootBeanDefinition.SCOPE_SINGLETON);
            }

            // A bean contained in a non-singleton bean cannot be a singleton itself.
            // Let's correct this on the fly here, since this might be the result of
            // parent-child merging for the outer bean, in which case the original inner bean
            // definition will not have inherited the merged outer bean's singleton status.
            if (containingBd != null && !containingBd.isSingleton() && mbd.isSingleton()) {
                mbd.setScope(containingBd.getScope());
            }

            // Cache the merged bean definition for the time being
            // (it might still get re-merged later on in order to pick up metadata changes)
            if (containingBd == null && isCacheBeanMetadata()) {
                // 放入缓存中
                this.mergedBeanDefinitions.put(beanName, mbd);
            }
        }

        return mbd;
    }
}

过程大致如下:

1、mergedBeanDefinitions缓存中获取合并后的RootBeanDefinition,存在则直接返回,不存在则进行后面的操作;
2、 获取合并后的RootBeanDefinition对象,逻辑并不复杂,将一些属性进行合并;这里对于BeanDefinition的获取也存在层次性查找策略;注意,如果一个单例BeanDefinition包含在非单例BeanDefinition,那么会变成非单例Bean;

后续还会对合并后的 RootBeanDefinition 对象进行检查,如果是抽象的,则抛出异常

8. 依赖 Bean 的处理

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
// Guarantee initialization of beans that the current bean depends on.
// `<8>` 获取当前正在创建的 Bean 所依赖对象集合(depends-on 配置的依赖)
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
    for (String dep : dependsOn) {
        // <8.1> 检测是否存在循环依赖,存在则抛出异常
        if (isDependent(beanName, dep)) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
        }
        // `<8.2>` 将 beanName 与 dep 之间依赖的关系进行缓存
        registerDependentBean(dep, beanName);
        try {
            // `<8.3>` 先创建好依赖的 Bean(重新调用 getBean(...) 方法)
            getBean(dep);
        }
        catch (NoSuchBeanDefinitionException ex) {
            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
        }
    }
}

  • 每个 Bean 不一定是单独工作的,可以通过 depends-on 配置依赖的 Bean,其他 Bean 也可以依赖它
  • 对于依赖的 Bean,会优先加载,所以在 Spring 的加载顺序中,在初始化某个 Bean 的时候,首先会初始化这个 Bean 的依赖

isDependent 方法

在初始化依赖的 Bean 之前,会调用 isDependent(String beanName, String dependentBeanName) 方法,判断是否出现循环依赖,方法如下:

DefaultSingletonBeanRegistry.java
protected boolean isDependent(String beanName, String dependentBeanName) {
    synchronized (this.dependentBeanMap) {
        return isDependent(beanName, dependentBeanName, null);
    }
}

private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
    // `<1>` alreadySeen 中已经检测过该 beanName 则直接返回 false
    if (alreadySeen != null && alreadySeen.contains(beanName)) {
        return false;
    }
    // `<2>` 获取最终的 beanName,因为可能是别名,需要进行相关处理
    String canonicalName = canonicalName(beanName);
    // `<3>` 从 dependentBeanMap 中获取依赖 beanName 的 Bean 集合
    Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
    // `<4>` 没有 Bean 依赖该 beanName,也就不存在循环依赖,返回 false
    if (dependentBeans == null) {
        return false;
    }
    // `<5>` 依赖 beanName 的 Bean 们包含 dependentBeanName,表示出现循环依赖,返回 true
    if (dependentBeans.contains(dependentBeanName)) {
        // beanName 与 dependentBeanName 相互依赖
        return true;
    }
    // `<6>` 对依赖该 beanName 的 Bean 们进行检查,看它们是否与 dependentBeanName 存在依赖,递归处理
    for (String transitiveDependency : dependentBeans) {
        if (alreadySeen == null) {
            alreadySeen = new HashSet<>();
        }
        alreadySeen.add(beanName);
        if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
            return true;
        }
    }
    return false;
}

过程大致如下:

1、 alreadySeen中已经检测过该beanName则直接返回false
2、 获取最终的beanName,因为可能是别名,需要进行相关处理;
3、dependentBeanMap中获取依赖beanName的Bean集合;
4、 没有Bean依赖该beanName,也就不存在循环依赖,返回false
5、 依赖beanName的Bean们包含dependentBeanName,表示出现循环依赖,返回true
6、 对依赖该beanName的Bean们进行检查,看它们是否与dependentBeanName存在依赖,递归处理;

判断是否出现循环依赖的过程有点绕,需要花点时间理解一下。例如:现在检查 A ->(依赖)B,看是否出现循环依赖,我获取到依赖 A 的所有 Bean,看 B 是否依赖这里面的 Bean,如果出现 A -> B -> C -> A,那就出现循环依赖了。如果出现循环依赖,则会抛出异常,所以我们说 Spring 处理了单例 Bean 的循环依赖注入比较好一点。

registerDependentBean 方法

beanNamedepbeanName 的依赖)之间依赖的关系进行缓存,调用 registerDependentBean(String beanName, String dependentBeanName) 方法,如下:

DefaultSingletonBeanRegistry.java
public void registerDependentBean(String beanName, String dependentBeanName) {
    String canonicalName = canonicalName(beanName);

    // 对应关系:beanName -> 依赖 beanName 的集合
    synchronized (this.dependentBeanMap) {
        Set<String> dependentBeans = this.dependentBeanMap.computeIfAbsent(canonicalName, 
                                                                           k -> new LinkedHashSet<>(8));
        if (!dependentBeans.add(dependentBeanName)) {
            return;
        }
    }

    // 对应关系:beanName - > beanName 的依赖的集合
    synchronized (this.dependenciesForBeanMap) {
        Set<String> dependenciesForBean = this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, 
                                                                                      k -> new LinkedHashSet<>(8));
        dependenciesForBean.add(canonicalName);
    }
}

将两者的依赖关系保存起来,目的是在 isDependent 方法中判断是否出现循环依赖

getBean 方法

加载 beanName 依赖的 Bean,同样是调用 AbstractBeanFactory#getBean(String dep) 方法,也就是本文开头讲的这个方法

9. 不同作用域的 Bean 的创建

Spring 的作用域划分为三种:单例模式、原型模式、其他模式,会依次进行判断,然后进行创建,创建过程都是一样的,主要是存储范围不一样

  • 单例模式:一个 BeanFactory 有且仅有一个实例
  • 原型模式:每次依赖查找和依赖注入生成新 Bean 对象
  • 其他模式,例如 request 作用域会将 Bean 存储在 ServletRequest 上下文中;session 作用域会将 Bean 存储在 HttpSession 中;application 作用域会将 Bean 存储在 ServletContext 中

单例模式

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
if (mbd.isSingleton()) { // <9.1> 单例模式
    /*
     * <9.1.1> 创建 Bean,成功创建则进行缓存,并移除缓存的早期对象
     * 创建过程实际调用的下面这个 createBean(...) 方法
     */
    sharedInstance = getSingleton(beanName,
            // ObjectFactory 实现类
            () -> {
                try {
                    // **【核心】** 创建 Bean
                    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.
                    // 如果创建过程出现异常,则显式地从缓存中删除当前 Bean 相关信息
                    // 在单例模式下为了解决循环依赖,创建过程会缓存早期对象,这里需要进行删除
                    destroySingleton(beanName);
                    throw ex;
                }
    });
    // `<9.1.2>` 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
    // 否则,调用 FactoryBean#getObject() 获取目标对象
    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}

如果是单例模式,创建过程大致如下:

  1. 调用 DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法

    创建 Bean,成功创建则进行缓存,并移除缓存的早期对象,创建过程实际调用的下面这个 AbstractAutowireCapableBeanFactory#createBean(...) 方法
    2、 FactoryBean的处理,在前面3.FactoryBean的处理中已经分析过;

getSingleton 方法

DefaultSingletonBeanRegistry#getSingleton(String beanName, ObjectFactory<?> singletonFactory) 方法,单例模式下获取单例 Bean,如下:

// DefaultSingletonBeanRegistry.java
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    // 全局加锁
    synchronized (this.singletonObjects) {
        // `<1>` 从 singletonObjects 单例 Bean 的缓存中获取 Bean(再检查一遍),存在则直接返回,否则开始创建
        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 + "'");
            }
            // `<2>` 将 beanName 标记为单例模式正在创建
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                /**
                 * <3> 创建 Bean,实际调用 
                 * {@link AbstractAutowireCapableBeanFactory#createBean(String, RootBeanDefinition, Object[])} 方法
                 */
                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;
                }
                // `<4>` 将 beanName 标记为不在创建中,照应第 2 步
                afterSingletonCreation(beanName);
            }
            // `<5>` 如果这里是新创建的单例模式 Bean,则在 singletonObjects 中进行缓存(无序),移除缓存的早期对象
            // 并在 registeredSingletons 中保存 beanName,保证注册顺序
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

过程大致如下:

1、singletonObjects单例Bean的缓存中获取Bean(再检查一遍),存在则直接返回,否则开始创建;
2、beanName标记为单例模式正在创建;
3. **【核心】**创建 Bean,实际调用 AbstractAutowireCapableBeanFactory#createBean(...) 方法
4、beanName标记为不在创建中,照应第2步;
5、 如果这里是新创建的单例模式Bean,则在singletonObjects中进行缓存(无序),移除缓存的早期对象,并在registeredSingletons中保存beanName,保证注册顺序;

createBean 方法

AbstractAutowireCapableBeanFactory#createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) 方法,创建 Bean,整个过程大致如下:

1、 Bean的实例化;
2、 属性赋值(包括依赖注入);
3、 Aware接口回调;
4、 调用初始化方法;

上面涉及到 Bean 生命周期的大部分阶段,将会在后续的文章中依次分析

原型模式

对应代码段:

// AbstractBeanFactory.java
// <9.2> 原型模式
else if (mbd.isPrototype()) {
    // It's a prototype -> create a new instance.
    Object prototypeInstance = null;
    try {
        // `<9.2.1>` 将 beanName 标记为**非单例模式**正在创建
        beforePrototypeCreation(beanName);
        // <9.2.2> **【核心】** 创建 Bean
        prototypeInstance = createBean(beanName, mbd, args);
    }
    finally {
        // `<9.2.3>` 将 beanName 标记为不在创建中,照应第 9.2.1 步
        afterPrototypeCreation(beanName);
    }
    // `<9.2.4>` 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
    // 否则,调用 FactoryBean#getObject() 获取目标对象
    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
}

过程大致如下:

1、beanName标记为非单例模式正在创建;
2. 【核心】创建 Bean 也是调用 AbstractAutowireCapableBeanFactory#createBean(...) 方法,这里没有缓存,每次加载 Bean 都会创建一个对象
3、beanName标记为不在创建中,照应第1步;
4、 FactoryBean的处理,在前面
3.FactoryBean的处理
中已经分析过;

其他模式

对应代码段:

// AbstractBeanFactory.java
// <9.3> 其他模式
else {
    // `<9.3.1>` 获取该模式的 Scope 对象 scope,不存在则抛出异常
    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 {
        // `<9.3.2>` 从 scope 中获取 beanName 对应的对象(看你的具体实现),不存在则执行**原型模式**的四个步骤进行创建
        Object scopedInstance = scope.get(beanName, () -> {
            // 将 beanName 标记为**非单例模式**式正在创建
            beforePrototypeCreation(beanName);
            try {
                // **【核心】** 创建 Bean
                return createBean(beanName, mbd, args);
            }
            finally {
                // 将 beanName 标记为不在创建中,照应上一步
                afterPrototypeCreation(beanName);
            }
        });
        // 获取 Bean 的目标对象,scopedInstance 非 FactoryBean 类型直接返回
        // 否则,调用 FactoryBean#getObject() 获取目标对象
        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);
    }
}

过程如下:

1、 获取该模式的Scope对象scope,不存在则抛出异常;
2、scope中获取beanName对应的对象(看你的具体实现),不存在则执行原型模式的四个步骤进行创建;

想要自定义一个作用域,可以实现 org.springframework.beans.factory.config.Scope 接口,并往 Spring 应用上下文注册即可

10. 类型转换

对应代码段:

// AbstractBeanFactory#doGetBean(...) 方法
// `<10>` 如果入参 requiredType 不为空,并且 Bean 不是该类型,则需要进行类型转换
if (requiredType != null && !requiredType.isInstance(bean)) {
    try {
        // `<10.1>` 通过类型转换机制,将 Bean 转换成 requiredType 类型
        T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
        // <10.2> 转换后的 Bean 为空则抛出异常
        if (convertedBean == null) {
            throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
        }
        // <10.3> 返回类型转换后的 Bean 对象
        return convertedBean;
    }
    catch (TypeMismatchException ex) {
        if (logger.isTraceEnabled()) {
            logger.trace("Failed to convert bean '" + name + "' to required type '" +
                    ClassUtils.getQualifiedName(requiredType) + "'", ex);
        }
        throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
    }
}

如果入参 requiredType 不为空,并且 Bean 不是该类型,则需要进行类型转换,过程如下:

1、 通过类型转换机制,将Bean转换成requiredType类型,对Spring的类型转换机制感兴趣的小伙伴可以自己研究,参考org.springframework.core.convert.support.DefaultConversionService
2、 转换后的Bean为空则抛出异常;
3、 返回类型转换后的Bean对象;

总结

本文对BeanFactory 接口的体系结构进行了分析,得知 DefaultListableBeanFactory 是 BeanFactory 的最底层实现,也就是 Spring 的底层 IoC 容器。接着分析了 AbstractBeanFactorygetBean(...) 方法,当我们显示或者隐式地调用这个方法时,会触发 Bean 的加载。上面所有小节对 Bean 的加载过程进行了分析,我已经有序地在每个小节面前添加了序号,这些序号对应着加载过程中的顺序。

不同作用域的 Bean 的创建,底层都会调用 AbstractAutowireCapableBeanFactorycreateBean(...)方法进行创建,创建 Bean 的过程涉及到 Bean 生命周期的大部分阶段,例如实例化阶段、属性赋值阶段、Aware 接口回调阶段、初始化阶段都是在这个方法中完成的,整个创建过程将在后续的文章进行分析。

版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址:open in new window