美文网首页IT@程序员猿媛程序员java
【Spring 笔记】Bean 加载相关整理

【Spring 笔记】Bean 加载相关整理

作者: 58bc06151329 | 来源:发表于2019-09-24 12:00 被阅读0次

    文前说明

    作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。

    本文仅供学习交流使用,侵权必删。
    不用于商业目的,转载请注明出处。

    1. 概述

    Spring IoC 容器的作用
    • Spring IoC 容器会以某种方式加载 Configuration Metadata,将其解析注册到容器内部,然后会根据这些信息绑定整个系统的对象,最终组装成一个可用的基于轻量级容器的应用系统。
      • 流程分为两个阶段:容器初始化阶段加载 bean 阶段
        • 容器初始化阶段。
          • 步骤 1,通过某种方式加载 Configuration Metadata(主要依据 ResourceResourceLoader 两个体系)。
          • 步骤 2,容器对加载的 Configuration MetaData 进行解析和分析,并将分析的信息组装成 BeanDefinition
          • 步骤 3,将 BeanDefinition 保存注册到相应的 BeanDefinitionRegistry 中。
        • 加载 Bean 阶段。
          • 步骤 1,经过容器初始化阶段后,应用程序中定义的 bean 信息已经全部加载到系统中,当显示或者隐式地调用 BeanFactory#getBean() 方法时,触发加载 Bean 阶段。
          • 步骤 2,容器首先检查所请求的对象是否已经初始化完成,如果没有,则会根据注册的 Bean 信息实例化请求的对象,并为其注册依赖,然后将其返回给请求方。
    • 容器初始化阶段的相关整理可以查看 【Spring 笔记】资源加载策略相关整理【Spring 笔记】BeanDefinition 装载与注册相关整理【Spring 笔记】Bean 解析相关整理

    2. 原理

    2.1 getBean

    • 显示或者隐式地调用 BeanFactory#getBean() 方法,会触发加载 Bean 阶段。
    // AbstractBeanFactory.java
    @Override
    public Object getBean(String name) throws BeansException {
        return doGetBean(name, null, null, false);
    }
    

    doGetBean

    参数 说明
    name 要获取 Bean 的名字
    requiredType 要获取 bean 的类型
    args 创建 Bean 时传递的参数。这个参数仅限于创建 Bean 时使用。
    typeCheckOnly 是否只做类型检查。
    // AbstractBeanFactory.java
    protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        // 1. 返回 bean 名称,剥离工厂引用前缀。
        // 如果 name 是 alias ,则获取对应映射的 beanName 。
        final String beanName = transformedBeanName(name);
        Object bean;
    
        // 从缓存中或者实例工厂中获取 Bean 对象
        // Eagerly check singleton cache for manually registered singletons.
        Object sharedInstance = getSingleton(beanName);
        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 + "'");
                }
            }
            // 2. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        } else {
            // Fail if we're already creating this bean instance:
            // We're assumably within a circular reference.
            // 3. 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }
    
            // 4. 如果容器中没有找到,则从父类容器中加载
            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                String nameToLookup = originalBeanName(name);
                if (parentBeanFactory instanceof AbstractBeanFactory) {
                    return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                            nameToLookup, requiredType, args, typeCheckOnly);
                } else if (args != null) {
                    // Delegation to parent with explicit args.
                    return (T) parentBeanFactory.getBean(nameToLookup, args);
                } else if (requiredType != null) {
                    // No args -> delegate to standard getBean method.
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                } else {
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
    
            // 5. 如果不是仅仅做类型检查则是创建bean,这里需要记录
            if (!typeCheckOnly) {
                markBeanAsCreated(beanName);
            }
    
            try {
                // 6. 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                // 检查给定的合并的 BeanDefinition
                checkMergedBeanDefinition(mbd, beanName, args);
    
                // Guarantee initialization of beans that the current bean depends on.
                // 7. 处理所依赖的 bean
                String[] dependsOn = mbd.getDependsOn();
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        // 若给定的依赖 bean 已经注册为依赖给定的 bean
                        // 循环依赖的情况
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        // 缓存依赖调用
                        registerDependentBean(dep, beanName);
                        try {
                            getBean(dep);
                        } catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }
    
                // 8. bean 实例化
                // Create bean instance.
                if (mbd.isSingleton()) { // 单例模式
                    sharedInstance = getSingleton(beanName, () -> {
                        try {
                            return createBean(beanName, mbd, args);
                        }
                        catch (BeansException ex) {
                            // Explicitly remove instance from singleton cache: It might have been put there
                            // eagerly by the creation process, to allow for circular reference resolution.
                            // Also remove any beans that received a temporary reference to the bean.
                            // 显式从单例缓存中删除 Bean 实例
                            // 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。 TODO 芋艿
                            destroySingleton(beanName);
                            throw ex;
                        }
                    });
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                } else if (mbd.isPrototype()) { // 原型模式
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance;
                    try {
                        beforePrototypeCreation(beanName);
                        prototypeInstance = createBean(beanName, mbd, args);
                    } finally {
                        afterPrototypeCreation(beanName);
                    }
                    bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
                } else {
                    // 从指定的 scope 下创建 bean
                    String scopeName = mbd.getScope();
                    final Scope scope = this.scopes.get(scopeName);
                    if (scope == null) {
                        throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");
                    }try {
                        Object scopedInstance = scope.get(beanName, () -> {
                            beforePrototypeCreation(beanName);
                            try {
                                return createBean(beanName, mbd, args);
                            } finally {
                                afterPrototypeCreation(beanName);
                            }
                        });
                        bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
                    } catch (IllegalStateException ex) {
                        throw new BeanCreationException(beanName,
                                "Scope '" + scopeName + "' is not active for the current thread; consider " +
                                "defining a scoped proxy for this bean if you intend to refer to it from a singleton",
                                ex);
                    }
                }
            } catch (BeansException ex) {
                cleanupAfterBeanCreationFailure(beanName);
                throw ex;
            }
        }
    
        // 9. 检查需要的类型是否符合 bean 的实际类型
        // Check if required type matches the type of the actual bean instance.
        if (requiredType != null && !requiredType.isInstance(bean)) {
            try {
                T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
                if (convertedBean == null) {
                    throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
                }
                return convertedBean;
            } catch (TypeMismatchException ex) {
                if (logger.isTraceEnabled()) {
                    logger.trace("Failed to convert bean '" + name + "' to required type '" +
                            ClassUtils.getQualifiedName(requiredType) + "'", ex);
                }
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
        }
        return (T) bean;
    }
    
    • 方法的调用流程。
      • 步骤 1,获取 beanName。
      • 步骤 2,从单例 Bean 缓存中获取 Bean。
      • 步骤 3,原型模式依赖检查。
      • 步骤 4,从 parentBeanFactory 获取 Bean。
      • 步骤 5,将指定的 Bean 标记为已经创建或即将创建。
      • 步骤 6,获取 BeanDefinition。
      • 步骤 7,对依赖 Bean 的处理。
      • 步骤 8,对不同作用域的 Bean 进行实例化。
      • 步骤 9,类型转换。

    2.1.1 获取 beanName

    // AbstractBeanFactory.java
    final String beanName = transformedBeanName(name);
    
    protected String transformedBeanName(String name) {
        return canonicalName(BeanFactoryUtils.transformedBeanName(name));
    }
    
    • 因为这里的 name 不一定就是 beanName,可能是 aliasName ,也有可能是 FactoryBean ,调用 transformedBeanName() 方法,对 name 进行转换。
    • 调用 BeanFactoryUtils#transformedBeanName() 方法,去除 FactoryBean 的修饰符。
      • transformedBeanNameCache 集合的存在,是为了缓存转换后的结果。下次再获取相同的 name 时,直接返回缓存中的结果即可。
      • 去除传入 name 参数的 " & " 的前缀。假设配置了一个 FactoryBean 的名字为 "abc" ,那么获取 FactoryBean 创建的 Bean 时,使用 "abc" ,如果获取 FactoryBean 本身,使用 "$abc" 。
    // BeanFactoryUtils.java
    /**
     * Cache from name with factory bean prefix to stripped name without dereference.
     *
     * 缓存 {@link #transformedBeanName(String)} 已经转换好的结果。
     *
     * @since 5.1
     * @see BeanFactory#FACTORY_BEAN_PREFIX
     */
    private static final Map<String, String> transformedBeanNameCache = new ConcurrentHashMap<>();
    /**
     * 去除 FactoryBean 的修饰符 &
     *
     * 如果 name 以 “&” 为前缀,那么会去掉该 "&" 。
     * 例如,name = "&studentService" ,则会是 name = "studentService"。
     *
     * Return the actual bean name, stripping out the factory dereference
     * prefix (if any, also stripping repeated factory prefixes if found).
     * @param name the name of the bean
     * @return the transformed name
     * @see BeanFactory#FACTORY_BEAN_PREFIX
     */
    public static String transformedBeanName(String name) {
        Assert.notNull(name, "'name' must not be null");
        if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) { // BeanFactory.FACTORY_BEAN_PREFIX = $
            return name;
        }
        // computeIfAbsent 方法,分成两种情况:
        //      1. 未存在,则进行计算执行,并将结果添加到缓存、
        //      2. 已存在,则直接返回,无需计算。
        return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
            do {
                beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
            } while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
            return beanName;
        });
    }
    
    • 调用 canonicalName() 方法,取指定的 alias 所表示的最终 beanName 。
      • 一个循环获取 beanName 的过程,例如,别名 A 指向名称为 B 的 bean 则返回 B,若 别名 A 指向别名 B,别名 B 指向名称为 C 的 bean,则返回 C。
    // SimpleAliasRegistry.java
    /** Map from alias to canonical name. */
    // key: alias
    // value: beanName
    private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
    
    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;
    }
    

    2.1.2 从单例 Bean 缓存中获取 Bean

    • 单例模式的 Bean 在整个过程中只会被创建一次。第一次创建后会将该 Bean 加载到缓存中。后面,在获取 Bean 就会直接从单例缓存中获取。
    // AbstractBeanFactory.java
    // 从缓存中或者实例工厂中获取 Bean 对象
    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    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 + "'");
            }
        }
        // 1. 完成 FactoryBean 的相关处理,并用来获取 FactoryBean 的处理结果
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    
    • 方法的调用流程。
      • 步骤 1,如果从缓存中得到了 Bean 对象,则需要调用 getObjectForBeanInstance() 方法,对 Bean 进行实例化处理。
      • 缓存中记录的是最原始的 Bean 状态,得到的不一定是最终想要的 Bean 。
    • FactoryBean 的用途
      • Spring 通过反射机制利用 bean 的 class 属性指定实现类来实例化 bean ,某些情况下,实例化 bean 过程比较复杂,按照传统的方式,需要提供大量的配置信息,配置方式的灵活性是受限的。
      • Spring 为此提供了一个 FactoryBean 的工厂类接口,用户可以通过实现该接口定制实例化 bean 的逻辑。
      • Spring 自身提供了 70 多个 FactoryBean 的实现,它们隐藏了实例化一些复杂 bean 的细节,给上层应用带来了便利。

    2.1.2.1 getSingleton

    // DefaultSingletonBeanRegistry.java
    @Override
    @Nullable
    public Object getSingleton(String beanName) {
        return getSingleton(beanName, true);
    }
    
    @Nullable
    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
        // 1. 从单例缓冲中加载 bean
        Object singletonObject = this.singletonObjects.get(beanName);
        // 2. 缓存中的 bean 为空,且当前 bean 正在创建
        if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
            // 加锁
            synchronized (this.singletonObjects) {
                // 2. 从 earlySingletonObjects 获取
                singletonObject = this.earlySingletonObjects.get(beanName);
                // 3. earlySingletonObjects 中没有,且允许提前创建
                if (singletonObject == null && allowEarlyReference) {
                    // 从 singletonFactories 中获取对应的 ObjectFactory
                    ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
                    if (singletonFactory != null) {
                        // 获得 bean
                        singletonObject = singletonFactory.getObject();
                        // 添加 bean 到 earlySingletonObjects 中
                        this.earlySingletonObjects.put(beanName, singletonObject);
                        // 从 singletonFactories 中移除对应的 ObjectFactory
                        this.singletonFactories.remove(beanName);
                    }
                }
            }
        }
        return singletonObject;
    }
    
    • 方法的调用流程。
      • 步骤 1,从 singletonObjects 中,获取 Bean 对象。
      • 步骤 2,若为空且当前 bean 正在创建中,则从 earlySingletonObjects 中获取 Bean 对象。
      • 步骤 3,若为空且允许提前创建,则从 singletonFactories 中获取相应的 ObjectFactory 对象。
        • 若不为空,则调用其 ObjectFactory#getObject() 方法,创建 Bean 对象,然后将其加入到 earlySingletonObjects ,然后从 singletonFactories 删除。
    • 根据 beanName 依次检测三个 Map,若为空,检查下一个,否则返回。
    // DefaultSingletonBeanRegistry.java
    /**
     * Cache of singleton objects: bean name to bean instance.
     *
     * 存放的是单例 bean 的映射。
     *
     * 对应关系为 bean name --> bean instance
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    /**
     * Cache of singleton factories: bean name to ObjectFactory.
     *
     * 存放的是 ObjectFactory,可以理解为创建单例 bean 的 factory 。
     *
     * 对应关系是 bean name --> ObjectFactory
     **/
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    /**
     * Cache of early singleton objects: bean name to bean instance.
     *
     * 存放的是早期的 bean,对应关系也是 bean name --> bean instance。
     *
     * 它与 {@link #singletonFactories} 区别在于 earlySingletonObjects 中存放的 bean 不一定是完整。
     *
     * 从 {@link #getSingleton(String)} 方法中,我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了。
     * 所以当在 bean 的创建过程中,就可以通过 getBean() 方法获取。
     *
     * 这个 Map 也是【循环依赖】的关键所在。
     */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    

    isSingletonCurrentlyInCreation

    • 该方法用于判断该 beanName 对应的 Bean 是否在创建过程中,这个过程讲的是整个工厂中。
      • 在 Bean 创建过程中都会将其加入到 singletonsCurrentlyInCreation 集合中。
    // DefaultSingletonBeanRegistry.java
    /**
     * Names of beans that are currently in creation.
     *
     * 正在创建中的单例 Bean 的名字的集合
     */
    private final Set<String> singletonsCurrentlyInCreation =
            Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    

    2.1.2.2 getObjectForBeanInstance

    • 从缓存中获取 Bean 后,若其不为 null 且 args 为空,则会调用 getObjectForBeanInstance() 方法,进行处理。
      • 因为从缓存中获取的 bean 是最原始的 Bean ,并不一定是最终想要的 Bean ,调用 getObjectForBeanInstance() 方法进行处理,该方法的定义为获取给定 Bean 实例的对象,该对象要么是 bean 实例本身,要么就是 FactoryBean 创建的 Bean 对象。
    // AbstractBeanFactory.java
    protected Object getObjectForBeanInstance(
            Object beanInstance, String name, String beanName, @Nullable RootBeanDefinition mbd) {
        // 1. 若为工厂类引用(name 以 & 开头)
        // Don't let calling code try to dereference the factory if the bean isn't a factory.
        if (BeanFactoryUtils.isFactoryDereference(name)) {
            // 如果是 NullBean,则直接返回
            if (beanInstance instanceof NullBean) {
                return beanInstance;
            }
            // 如果 beanInstance 不是 FactoryBean 类型,则抛出异常
            if (!(beanInstance instanceof FactoryBean)) {
                throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
            }
        }
    
        // 到这里我们就有了一个 Bean 实例,当然该实例可能是一个正常的 bean 又或者是一个 FactoryBean
        // 如果是 FactoryBean,则创建该 Bean
        // 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.
        // 2. 对非 FactoryBean 类型的处理
        if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
            return beanInstance;
        }
    
        Object object = null;
        // 3. 若 BeanDefinition 为 null,则从缓存中加载 Bean 对象
        if (mbd == null) {
            object = getCachedObjectForFactoryBean(beanName);
        }
        // 若 object 依然为空,则可以确认,beanInstance 一定是 FactoryBean 。从而,使用 FactoryBean 获得 Bean 对象
        if (object == null) {
            // Return bean instance from factory.
            FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
            // containsBeanDefinition 检测 beanDefinitionMap 中也就是在所有已经加载的类中
            // 检测是否定义 beanName
            // Caches object obtained from FactoryBean if it is a singleton.
            if (mbd == null && containsBeanDefinition(beanName)) {
                // 将存储 XML 配置文件的 GenericBeanDefinition 转换为 RootBeanDefinition,
                // 如果指定 BeanName 是子 Bean 的话同时会合并父类的相关属性
                mbd = getMergedLocalBeanDefinition(beanName);
            }
            // 是否是用户定义的,而不是应用程序本身定义的
            boolean synthetic = (mbd != null && mbd.isSynthetic());
            // 核心处理方法,使用 FactoryBean 获得 Bean 对象
            object = getObjectFromFactoryBean(factory, beanName, !synthetic);
        }
        return object;
    }
    
    • 该方法主要是进行检测工作,方法的调用流程。
      • 步骤 1,若 name 为工厂相关的(以 & 开头),且 beanInstance 为 NullBean 类型则直接返回,如果 beanInstance 不为 FactoryBean 类型则抛出 BeanIsNotAFactoryException 异常。这里主要是 校验 beanInstance 的正确性
      • 步骤 2,如果 beanInstance 不为 FactoryBean 类型或者 name 也不是与工厂相关的,则直接返回 beanInstance 这个 Bean 对象。这里主要是 对非 FactoryBean 类型的处理
      • 步骤 3,如果 BeanDefinition 为空,则从 factoryBeanObjectCache 中加载 Bean 对象。
        • 如果还是空,则可以断定 beanInstance 一定是 FactoryBean 类型,则委托 getObjectFromFactoryBean() 方法,进行处理,使用 FactoryBean 获得 Bean 对象

    getObjectFromFactoryBean

    • getObjectForBeanInstance() 方法,可以分成两种情况。
      • 当该实例对象为非 FactoryBean 类型,直接返回给定的 Bean 实例对象 beanInstance 。
      • 当该实例对象为 FactoryBean 类型,从 FactoryBean ( beanInstance ) 中,获取 Bean 实例对象,通过 getObjectFromFactoryBean() 方法实现。
    // FactoryBeanRegistrySupport.java
    /**
     * Cache of singleton objects created by FactoryBeans: FactoryBean name to object.
     *
     * 缓存 FactoryBean 创建的单例 Bean 对象的映射
     * beanName ===> Bean 对象
     */
    private final Map<String, Object> factoryBeanObjectCache = new ConcurrentHashMap<>(16);
    
    protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        // 1. 为单例模式且缓存中存在
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) { // 1.1. 单例锁
                // 1.2. 从缓存中获取指定的 factoryBean
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    // 为空,则从 FactoryBean 中获取对象
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    // 从缓存中获取
                    // TODO 芋艿,具体原因
                    // 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)
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    } else {
                        // 1.3. 需要后续处理
                        if (shouldPostProcess) {
                            // 若该 Bean 处于创建中,则返回非处理对象,而不是存储它
                            if (isSingletonCurrentlyInCreation(beanName)) {
                                // Temporarily return non-post-processed object, not storing it yet..
                                return object;
                            }
                            // 单例 Bean 的前置处理
                            beforeSingletonCreation(beanName);
                            try {
                                // 对从 FactoryBean 获取的对象进行后处理
                                // 生成的对象将暴露给 bean 引用
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            } catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            } finally {
                                // 单例 Bean 的后置处理
                                afterSingletonCreation(beanName);
                            }
                        }
                        // 1.4. 添加到 factoryBeanObjectCache 中,进行缓存
                        if (containsSingleton(beanName)) {
                            this.factoryBeanObjectCache.put(beanName, object);
                        }
                    }
                }
                return object;
            }
        // 2.
        } else {
            // 为空,则从 FactoryBean 中获取对象
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            // 需要后续处理
            if (shouldPostProcess) {
                try {
                    // 对从 FactoryBean 获取的对象进行后处理
                    // 生成的对象将暴露给 bean 引用
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
    }
    
    • 方法的调用流程。
      • 步骤 1,若为单例且单例 Bean 缓存中存在 beanName ,则进行后续处理(跳转到下一步),否则,则执行 <步骤 2> 从 FactoryBean 中获取 Bean 实例对象。
      • 步骤 1.1,获取锁。锁住的对象都是 this.singletonObjects,因为在单例模式中必须要保证 全局唯一
    // DefaultSingletonBeanRegistry.java
    /**
     * Cache of singleton objects: bean name to bean instance.
     *
     * 存放的是单例 bean 的映射。
     *
     * 对应关系为 bean name --> bean instance
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    public final Object getSingletonMutex() {
        return this.singletonObjects;
    }
    

    步骤 1.2,从 factoryBeanObjectCache 缓存中获取实例对象 object 。

    • 若 object 为空,则调用 doGetObjectFromFactoryBean() 方法,从 FactoryBean 获取对象,内部调用 FactoryBean#getObject() 方法,获取 Bean 对象。
    private Object doGetObjectFromFactoryBean(final FactoryBean<?> factory, final String beanName)
        throws BeanCreationException {
        Object object;
        try {
            // 需要权限验证
            if (System.getSecurityManager() != null) {
                AccessControlContext acc = getAccessControlContext();
                try {
                    // 从 FactoryBean 中,获得 Bean 对象
                    object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
                } catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            } else {
                // 从 FactoryBean 中,获得 Bean 对象
                object = factory.getObject();
            }
        } catch (FactoryBeanNotInitializedException ex) {
            throw new BeanCurrentlyInCreationException(beanName, ex.toString());
        } catch (Throwable ex) {
            throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
        }
        // Do not accept a null value for a FactoryBean that's not fully
        // initialized yet: Many FactoryBeans just return null then.
        if (object == null) {
            if (isSingletonCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(
                        beanName, "FactoryBean which is currently in creation returned null from getObject");
            }
            object = new NullBean();
        }
        return object;
    }
    
    • 步骤 1.3,如果需要后续处理(shouldPostProcess = true),则进行进一步处理。
      • 若该 Bean 处于创建中(isSingletonCurrentlyInCreation() 方法返回 true),则返回 非处理的 Bean 对象,而不是存储它。
      • 调用 beforeSingletonCreation() 方法,进行创建之前的处理。默认实现是将该 Bean 标志为 当前创建的
      • 调用 postProcessObjectFromFactoryBean() 方法,对从 FactoryBean 获取的 Bean 实例对象进行后置处理。
      • 调用 afterSingletonCreation() 方法,进行创建 Bean 之后的处理,默认实现是将该 bean 标记为 不再在创建中
    • 步骤 1.4,加入到 factoryBeanObjectCache 缓存中。
    • beforeSingletonCreation()afterSingletonCreation() 记录着 Bean 的加载状态,是检测当前 Bean 是否处于创建中的关键之处,对解决 Bean 循环依赖起着关键作用

    beforeSingletonCreation

    // DefaultSingletonBeanRegistry.java
    protected void beforeSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName)
                && !this.singletonsCurrentlyInCreation.add(beanName)) { // 添加
            throw new BeanCurrentlyInCreationException(beanName); // 如果添加失败,则抛出 BeanCurrentlyInCreationException 异常。
        }
    }
    

    afterSingletonCreation

    • 移除,对 singletonsCurrentlyInCreation 集合进行 remove。
    // DefaultSingletonBeanRegistry.java
    protected void afterSingletonCreation(String beanName) {
        if (!this.inCreationCheckExclusions.contains(beanName) &&
                !this.singletonsCurrentlyInCreation.remove(beanName)) { // 移除
            // 如果移除失败,则抛出 IllegalStateException 异常
            throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
        }
    }
    

    postProcessObjectFromFactoryBean

    • 对从 FactoryBean 处获取的 Bean 实例对象进行后置处理。默认实现是直接返回 object 对象,不做任何处理。
    // DefaultSingletonBeanRegistry.java
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
        return object;
    }
    
    • **org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory **抽象类,对其提供了实现。
    // AbstractAutowireCapableBeanFactory.java
    protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
        return applyBeanPostProcessorsAfterInitialization(object, beanName);
    }
    
    • 进行回调注册 BeanPostProcessors,让能够后期处理从 FactoryBean 中获取的对象。
    // AbstractAutowireCapableBeanFactory.java
    @Override
    public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException {
        Object result = existingBean;
        // 遍历 BeanPostProcessor
        for (BeanPostProcessor processor : getBeanPostProcessors()) {
            // 处理
            Object current = processor.postProcessAfterInitialization(result, beanName);
            // 返回空,则返回 result
            if (current == null) {
                return result;
            }
            // 修改 result
            result = current;
        }
        return result;
    }
    
    • 对于后置处理器,在实际开发过程中大可以针对此特性设计自己的业务逻辑。

    2.1.3 原型模式依赖检查

    • Spring 只处理单例模式下得循环依赖,对于原型模式的循环依赖直接抛出异常。主要原因还是在于,和 Spring 解决循环依赖的策略 有关。
      • 单例(Singleton)模式, Spring 在创建 Bean 的时候,不等 Bean 创建完成就会将创建 Bean 的 ObjectFactory 提早加入到缓存中,这样一旦下一个 Bean 创建的时候需要依赖 bean 时则直接使用 ObjectFactroy
      • 原型(Prototype)模式,没法使用缓存,所以 Spring 对原型模式的循环依赖处理策略则是 不处理
    // AbstractBeanFactory.java
    // Fail if we're already creating this bean instance:
    // We're assumably within a circular reference.
    // 因为 Spring 只解决单例模式下得循环依赖,在原型模式下如果存在循环依赖则会抛出异常。
    if (isPrototypeCurrentlyInCreation(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
    
    • isPrototypeCurrentlyInCreation() 方法,判断当前 Bean 是否正在创建。
    // AbstractBeanFactory.java
    protected boolean isPrototypeCurrentlyInCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        return (curVal != null &&
                (curVal.equals(beanName)  // 相等
                        || (curVal instanceof Set && ((Set<?>) curVal).contains(beanName)))); // 包含
    }
    /** Names of beans that are currently in creation. */
    private final ThreadLocal<Object> prototypesCurrentlyInCreation =
            new NamedThreadLocal<>("Prototype beans currently in creation");
    
    
    • 检测逻辑和单例模式一样,一个集合存放着正在创建的 Bean ,从该集合中进行判断即可,只不过单例模式的集合为 Set ,而原型模式的则是 ThreadLocal

    2.1.4 从 parentBeanFactory 获取 Bean

    • 如果 beanDefinitionMap 中不存在 beanName 的 BeanDefinition(即在 Spring bean 初始化过程中没有加载),则尝试从 parentBeanFactory 中加载。
    // AbstractBeanFactory.java
    // 获取 parentBeanFactory
    BeanFactory parentBeanFactory = getParentBeanFactory();
    // parentBeanFactory 不为空且 beanDefinitionMap 中不存该 name 的 BeanDefinition
    if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
        // 确定原始 beanName
        String nameToLookup = originalBeanName(name);
        // 若为 AbstractBeanFactory 类型,委托父类处理
        if (parentBeanFactory instanceof AbstractBeanFactory) {
            return ((AbstractBeanFactory) parentBeanFactory).doGetBean(
                    nameToLookup, requiredType, args, typeCheckOnly);
        } else if (args != null) {
            // 委托给构造函数 getBean() 处理
            return (T) parentBeanFactory.getBean(nameToLookup, args);
        } else {
            // 没有 args,委托给标准的 getBean() 处理
            return parentBeanFactory.getBean(nameToLookup, requiredType);
        }
    }
    
    • 委托 parentBeanFactory 的 getBean() 方法进行处理,在获取之前对 breanName 进行简单的处理,主要是为了获取原始的 beanName 。
    // AbstractBeanFactory.java
    protected String originalBeanName(String name) {
        String beanName = transformedBeanName(name); // 1.
        if (name.startsWith(FACTORY_BEAN_PREFIX)) { // 2.
            beanName = FACTORY_BEAN_PREFIX + beanName;
        }
        return beanName;
    }
    
    • 方法的调用流程。
      • 步骤 1,对 name 进行转换,获取真正的 beanName 。
      • 步骤 2,如果 name 是以 " & " 开头的,则加上 " & ",因为在 transformedBeanName() 方法中去掉了,这里 补上

    2.1.5 将指定的 Bean 标记为已经创建或即将创建

    • 方法参数 typeCheckOnly,用于判断调用 getBean() 方法时,表示是否为仅仅进行类型检查获取 Bean 对象。
      • 如果不是仅仅做类型检查,而是创建 Bean 对象,则需要调用 markBeanAsCreated() 方法,进行记录。
    // AbstractBeanFactory.java
    /**
     *  Names of beans that have already been created at least once.
     *
     *  已创建 Bean 的名字集合
     */
    private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));
    
    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);
                }
            }
        }
    }
    
    protected void clearMergedBeanDefinition(String beanName) {
        this.mergedBeanDefinitions.remove(beanName);
    }
    

    2.1.6 获取 BeanDefinition

    • 因为从 XML 配置文件中读取到的 Bean 信息是存储在 GenericBeanDefinition 中。
      • 但是,所有的 Bean 后续处理都是针对于 RootBeanDefinition 的,所以这里需要进行一个转换。
      • 转换的同时,如果父类 bean 不为空,则一并合并父类的属性。
    // AbstractBeanFactory.java
    // 从容器中获取 beanName 相应的 GenericBeanDefinition 对象,并将其转换为 RootBeanDefinition 对象
    final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
    // 检查给定的合并的 BeanDefinition
    checkMergedBeanDefinition(mbd, beanName, args);
    
    • 调用 getMergedLocalBeanDefinition() 方法,获取相对应的 BeanDefinition 对象。
    // AbstractBeanFactory.java
    /** Map from bean name to merged RootBeanDefinition. */
    private final Map<String, RootBeanDefinition> mergedBeanDefinitions = new ConcurrentHashMap<>(256);
    
    protected RootBeanDefinition getMergedLocalBeanDefinition(String beanName) throws BeansException {
        // Quick check on the concurrent map first, with minimal locking.
        // 1. 快速从缓存中获取,如果不为空,则直接返回
        RootBeanDefinition mbd = this.mergedBeanDefinitions.get(beanName);
        if (mbd != null) {
            return mbd;
        }
        // 获取 RootBeanDefinition,
        // 2. 如果返回的 BeanDefinition 是子类 bean 的话,则合并父类相关属性
        return getMergedBeanDefinition(beanName, getBeanDefinition(beanName));
    }
    
    • 方法的调用流程。

      • 步骤 1,直接从 mergedBeanDefinitions 缓存中获取相应的 RootBeanDefinition 对象,如果存在则直接返回。
      • 步骤 2,获取 RootBeanDefinition 对象。若获取的 BeanDefinition 为子 BeanDefinition,则需要合并父类的相关属性。
    • 调用 checkMergedBeanDefinition() 方法,检查给定的合并的 BeanDefinition 对象。

    // AbstractBeanFactory.java
    protected void checkMergedBeanDefinition(RootBeanDefinition mbd, String beanName, @Nullable Object[] args)
            throws BeanDefinitionStoreException {
        if (mbd.isAbstract()) {
            throw new BeanIsAbstractException(beanName);
        }
    }
    

    2.1.7 对依赖 Bean 的处理

    • 如果一个 Bean 有依赖 Bean 的话,那么在初始化该 Bean 时需要先初始化它所依赖的 Bean。
    // AbstractBeanFactory.java
    // Guarantee initialization of beans that the current bean depends on.
    // 处理所依赖的 bean
    String[] dependsOn = mbd.getDependsOn();
    if (dependsOn != null) {
        for (String dep : dependsOn) {
            // 1. 若给定的依赖 bean 已经注册为依赖给定的 bean
            // 即循环依赖的情况,抛出 BeanCreationException 异常
            if (isDependent(beanName, dep)) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
            }
            // 2. 缓存依赖调用
            registerDependentBean(dep, beanName);
            try {
                // 3. 递归处理依赖 Bean
                getBean(dep);
            } catch (NoSuchBeanDefinitionException ex) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
            }
        }
    }
    
    • 通过迭代的方式依次对依赖 bean 进行检测、校验。如果通过,则调用 getBean() 方法,实例化依赖的 Bean 对象。
      • 对于依赖的 Bean ,会优先加载,在 Spring 的加载顺序中,在初始化某一个 Bean 的时候,首先会初始化这个 Bean 的依赖。

    isDependent

    • 调用 isDependent() 方法,校验该依赖是否已经注册给当前 Bean。
    // DefaultSingletonBeanRegistry.java
    /**
     * Map between dependent bean names: bean name to Set of dependent bean names.
     *
     * 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
     */
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
    
    protected boolean isDependent(String beanName, String dependentBeanName) {
        synchronized (this.dependentBeanMap) {
            return isDependent(beanName, dependentBeanName, null);
        }
    }
    
    • dependentBeanMap 对象保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合。
    • 同步加锁给 dependentBeanMap 对象,然后进行校验。
    // DefaultSingletonBeanRegistry.java
    private boolean isDependent(String beanName, String dependentBeanName, @Nullable Set<String> alreadySeen) {
        // alreadySeen 已经检测的依赖 bean
        if (alreadySeen != null && alreadySeen.contains(beanName)) {
            return false;
        }
        // 获取原始 beanName
        String canonicalName = canonicalName(beanName);
        // 获取当前 beanName 的依赖集合
        Set<String> dependentBeans = this.dependentBeanMap.get(canonicalName);
        if (dependentBeans == null) {
            return false;
        }
        // 存在,则证明存在已经注册的依赖
        if (dependentBeans.contains(dependentBeanName)) {
            return true;
        }
        // 递归检测依赖
        for (String transitiveDependency : dependentBeans) {
            if (alreadySeen == null) {
                alreadySeen = new HashSet<>();
            }
            // 添加到 alreadySeen 中
            alreadySeen.add(beanName);
            // 递推
            if (isDependent(transitiveDependency, dependentBeanName, alreadySeen)) {
                return true;
            }
        }
        return false;
    }
    

    registerDependentBean

    • 如果校验成功,则调用 registerDependentBean() 方法,将该依赖进行注册,便于在销毁 Bean 之前对其进行销毁。
    // DefaultSingletonBeanRegistry.java
    /**
     * Map between dependent bean names: bean name to Set of dependent bean names.
     *
     * 保存的是依赖 beanName 之间的映射关系:beanName - > 依赖 beanName 的集合
     */
    private final Map<String, Set<String>> dependentBeanMap = new ConcurrentHashMap<>(64);
    
    /**
     * Map between depending bean names: bean name to Set of bean names for the bean's dependencies.
     *
     * 保存的是依赖 beanName 之间的映射关系:依赖 beanName - > beanName 的集合
     */
    private final Map<String, Set<String>> dependenciesForBeanMap = new ConcurrentHashMap<>(64);
    
    public void registerDependentBean(String beanName, String dependentBeanName) {
        // 获取 beanName
        String canonicalName = canonicalName(beanName);
    
        // 添加 <canonicalName, <dependentBeanName>> 到 dependentBeanMap 中
        synchronized (this.dependentBeanMap) {
            Set<String> dependentBeans =
                    this.dependentBeanMap.computeIfAbsent(canonicalName, k -> new LinkedHashSet<>(8));
            if (!dependentBeans.add(dependentBeanName)) {
                return;
            }
        }
    
        // 添加 <dependentBeanName, <canonicalName>> 到 dependenciesForBeanMap 中
        synchronized (this.dependenciesForBeanMap) {
            Set<String> dependenciesForBean =
                    this.dependenciesForBeanMap.computeIfAbsent(dependentBeanName, k -> new LinkedHashSet<>(8));
            dependenciesForBean.add(canonicalName);
        }
    }
    
    • 将该映射关系保存到两个集合中 dependentBeanMap、dependenciesForBeanMap 。

    getBean

    • 调用 getBean() 方法,实例化依赖 Bean 对象。

    2.1.8 对不同作用域的 Bean 进行实例化

    • Spring Bean 的作用域默认为 singleton 。还有其他作用域,如 prototype、request、session 等,不同的作用域会有不同的初始化策略。

    2.1.8.1 singleton

    • Spring 的 scope 默认为 singleton。
      • 加载了单例 bean 后,调用 getObjectForBeanInstance() 方法,从 bean 实例中获取对象。
    // AbstractBeanFactory.java
    if (mbd.isSingleton()) { // 单例模式
        sharedInstance = getSingleton(beanName, () -> {
            try {
                return createBean(beanName, mbd, args);
            }
            catch (BeansException ex) {
                // Explicitly remove instance from singleton cache: It might have been put there
                // eagerly by the creation process, to allow for circular reference resolution.
                // Also remove any beans that received a temporary reference to the bean.
                // 显式从单例缓存中删除 Bean 实例
                // 因为单例模式下为了解决循环依赖,可能他已经存在了,所以销毁它。
                destroySingleton(beanName);
                throw ex;
            }
        });
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
    }
    
    • 可以从缓存中获取单例模式的 bean。如果缓存中不存在,则需要从头开始加载 Bean ,这个过程由 getSingleton() 方法来实现。
    // DefaultSingletonBeanRegistry.java
    public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
        Assert.notNull(beanName, "Bean name must not be null");
        // 全局加锁
        synchronized (this.singletonObjects) {
            // 1. 从缓存中检查一遍
            // 因为 singleton 模式其实就是复用已经创建的 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. 加载前置处理
                beforeSingletonCreation(beanName);
                boolean newSingleton = false;
                boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
                if (recordSuppressedExceptions) {
                    this.suppressedExceptions = new LinkedHashSet<>();
                }
                try {
                    // 3. 初始化 bean
                    // 这个过程其实是调用 createBean() 方法
                    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. 后置处理
                    afterSingletonCreation(beanName);
                }
                // 5. 加入缓存中
                if (newSingleton) {
                    addSingleton(beanName, singletonObject);
                }
            }
            return singletonObject;
        }
    }
    
    • 这个过程并没有真正创建 Bean 对象,仅仅只是做了一部分准备和预处理步骤,方法的调用流程。
      • 步骤 1,再次检查缓存是否已经加载,如果已经加载则直接返回,否则开始加载过程。
      • 步骤 2beforeSingletonCreation() 方法记录加载单例 bean 之前的加载状态,即前置处理。
      • 步骤 3,调用参数传递的 ObjectFactorygetObject() 方法,实例化 bean。
      • 步骤 4,调用 afterSingletonCreation() 方法,进行加载单例后的后置处理。
      • 步骤 5,调用 addSingleton() 方法,将结果记录并加入值缓存中,同时删除加载 bean 过程中所记录的一些辅助状态。

    addSingleton

    // DefaultSingletonBeanRegistry.java
    /**
     * Cache of singleton objects: bean name to bean instance.
     *
     * 存放的是单例 bean 的映射。
     *
     * 对应关系为 bean name --> bean instance
     */
    private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
    
    /**
     * Cache of singleton factories: bean name to ObjectFactory.
     *
     * 存放的是【早期】的单例 bean 的映射。
     *
     * 对应关系也是 bean name --> bean instance。
     *
     * 它与 {@link #singletonObjects} 的区别区别在,于 earlySingletonObjects 中存放的 bean 不一定是完整的。
     *
     * 从 {@link #getSingleton(String)} 方法中,中我们可以了解,bean 在创建过程中就已经加入到 earlySingletonObjects 中了,
     * 所以当在 bean 的创建过程中就可以通过 getBean() 方法获取。
     * 这个 Map 也是解决【循环依赖】的关键所在。
     **/
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    
    /**
     * Cache of early singleton objects: bean name to bean instance.
     *
     * 存放的是 ObjectFactory 的映射,可以理解为创建单例 bean 的 factory 。
     *
     * 对应关系是 bean name --> ObjectFactory
     */
    private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
    
    /** Set of registered singletons, containing the bean names in registration order. */
    private final Set<String> registeredSingletons = new LinkedHashSet<>(256);
    
    protected void addSingleton(String beanName, Object singletonObject) {
        synchronized (this.singletonObjects) {
            this.singletonObjects.put(beanName, singletonObject);
            this.singletonFactories.remove(beanName);
            this.earlySingletonObjects.remove(beanName);
            this.registeredSingletons.add(beanName);
        }
    }
    
    操作 说明
    put singletonObjects 属性,单例 bean 的缓存。
    remove singletonFactories 属性,单例 bean Factory 的缓存。
    remove earlySingletonObjects 属性,“早期”创建的单例 bean 的缓存。
    add registeredSingletons 属性,已经注册的单例缓存。

    2.1.8.2 原型模式

    // AbstractBeanFactory.java
    else if (mbd.isPrototype()) {
        Object prototypeInstance = null;
        try {
           // 1. 加载前置处理
            beforePrototypeCreation(beanName);
            // 2. 创建 Bean 对象
            prototypeInstance = createBean(beanName, mbd, args);
        } finally {
           // 3. 加载后缀处理
            afterPrototypeCreation(beanName);
        }
        // 4. 从 Bean 实例中获取对象
        bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
    }
    
    • 原型模式的初始化过程,直接创建一个新的 Bean 的实例,方法的调用流程。
      • 调用 beforePrototypeCreation() 方法,记录加载原型模式 bean 之前的加载状态,即前置处理。
      • 调用 createBean() 方法,创建一个 bean 实例对象。
      • 调用 afterSingletonCreation() 方法,进行加载原型模式 bean 后的后置处理。
      • 加载了单例 bean 后,调用 getObjectForBeanInstance() 方法,从 bean 实例中获取对象。

    beforePrototypeCreation

    // AbstractBeanFactory.java
    /** Names of beans that are currently in creation. */
    private final ThreadLocal<Object> prototypesCurrentlyInCreation =
            new NamedThreadLocal<>("Prototype beans currently in creation");
            
    protected void beforePrototypeCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        if (curVal == null) { // String
            this.prototypesCurrentlyInCreation.set(beanName);
        } else if (curVal instanceof String) { // String => Set
            Set<String> beanNameSet = new HashSet<>(2);
            beanNameSet.add((String) curVal);
            beanNameSet.add(beanName);
            this.prototypesCurrentlyInCreation.set(beanNameSet);
        } else { // Set
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.add(beanName);
        }
    }
    

    afterSingletonCreation

    // AbstractBeanFactory.java
    protected void afterPrototypeCreation(String beanName) {
        Object curVal = this.prototypesCurrentlyInCreation.get();
        if (curVal instanceof String) { // String => null
            this.prototypesCurrentlyInCreation.remove();
        } else if (curVal instanceof Set) { // Set
            Set<String> beanNameSet = (Set<String>) curVal;
            beanNameSet.remove(beanName);
            if (beanNameSet.isEmpty()) { // Set => null
                this.prototypesCurrentlyInCreation.remove();
            }
        }
    }
    

    2.1.8.3 其它作用域

    • 核心流程和原型模式一样,只是获取 bean 实例由 Scope#get() 方法实现。
    // AbstractBeanFactory.java
    else {
        // 获得 scopeName 对应的 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 {
            // 从指定的 scope 下创建 bean
            Object scopedInstance = scope.get(beanName, () -> {
                // 加载前置处理
                beforePrototypeCreation(beanName);
                try {
                    // 创建 Bean 对象
                    return createBean(beanName, mbd, args);
                } finally {
                    // 加载后缀处理
                    afterPrototypeCreation(beanName);
                }
            });
            // 从 Bean 实例中获取对象
            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);
        }
    }
    
    • org.springframework.beans.factory.config.Scope 接口,有多种实现类。
    // SimpleThreadScope.java
    private final ThreadLocal<Map<String, Object>> threadScope =
        new NamedThreadLocal<Map<String, Object>>("SimpleThreadScope") {
            @Override
            protected Map<String, Object> initialValue() {
                return new HashMap<>();
            }
        };
    
    @Override
    public Object get(String name, ObjectFactory<?> objectFactory) {
        // 获取 scope 缓存
        Map<String, Object> scope = this.threadScope.get();
        Object scopedObject = scope.get(name);
        if (scopedObject == null) {
            scopedObject = objectFactory.getObject();
            // 加入缓存
            scope.put(name, scopedObject);
        }
        return scopedObject;
    }
    

    2.1.9 类型转换

    • 在调用 doGetBean() 方法时,有一个 requiredType 参数。该参数的功能是将返回的 Bean 转换为 requiredType 类型,一般而言,是不需要进行类型转换的,requiredType 为空(比如 getBean(String name) 方法)。
    // AbstractBeanFactory.java
    // 检查需要的类型是否符合 bean 的实际类型
    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // 执行转换
            T convertedBean = getTypeConverter().convertIfNecessary(bean, requiredType);
            // 转换失败,抛出 BeanNotOfRequiredTypeException 异常
            if (convertedBean == null) {
                throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
            }
            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());
        }
    }
    

    2.1.10 小结

    • Spring Bean 加载过程可以拆分分为三个部分。
      • 从缓存中获取单例 Bean ,以及对 Bean 的实例中获取对象。
      • 从单例缓存中获取 Bean ,Bean 加载,以及 Bean 的依赖处理。
      • Bean 已经加载,依赖也处理完毕,则进行各个作用域的 Bean 初始化过程。
    get Bean 的全流程

    相关文章

      网友评论

        本文标题:【Spring 笔记】Bean 加载相关整理

        本文链接:https://www.haomeiwen.com/subject/uoejuctx.html