死磕Spring之IoC篇 - 开启 Bean 的加载

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

Spring 版本:5.1.14.RELEASEjava

开始阅读这一系列文章以前,建议先查看《深刻了解 Spring IoC(面试题)》这一篇文章git

该系列其余文章请查看:《死磕 Spring 之 IoC 篇 - 文章导读》github

开启 Bean 的加载

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

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

BeanFactory 体系结构

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

简单描述这些接口:安全

  • org.springframework.beans.factory.BeanFactory,Spring IoC 容器最基础的接口,提供依赖查找单个 Bean 的功能session

  • org.springframework.beans.factory.ListableBeanFactory,继承 BeanFactory 接口,提供依赖查找多个 Bean 的功能app

  • 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(Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) 方法

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


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

  1. 若是非单例模式下的 Bean 正在建立,这里又开始建立,代表存在循环依赖,则直接抛出异常

  2. 若是从当前容器中没有找到对应的 BeanDefinition,则从父容器中加载(若是存在父容器)

    1. 获取 beanName,由于多是别名,则进行处理,和第 1 步不一样,不须要对 & 进行处理,由于进入父容器从新依赖查找
    2. 若为 AbstractBeanFactory 类型,委托父容器的 doGetBean 方法进行处理;不然,就是非 Spring IoC 容器,根据参数调用相应的 getBean(...)方法
  3. 若是不是仅仅作类型检查,则表示须要建立 Bean,将 beanName 标记为已建立过,在后面的循环依赖检查中会使用到

  4. 从容器中获取 beanName 对应的的 RootBeanDefinition(合并后),调用 getMergedLocalBeanDefinition(String beanName) 方法

  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(面试题)》中的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 接口回调阶段、初始化阶段都是在这个方法中完成的,整个建立过程将在后续的文章进行分析。

相关文章
相关标签/搜索