栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring getBean()源码笔记

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring getBean()源码笔记

目录

一、概要

二、getBean(String name):获取指定名称的bean

 三、总结


一、概要

通过前面几篇文章对IOC容器创建流程的详细分析,相信大家对IOC有了一个全新的认识,但是我们还不知道Spring如何获取Bean实例的,本篇文章,我们就关于获取 Bean 实例的过程做一个比较详细的分析。

二、getBean(String name):获取指定名称的bean

org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)方法主要用于从bean工厂中获取指定名称的bean实例,如果获取不到,将会执行实例化、属性填充、初始化等一系列过程。

首先来看看getBean(String name)方法的定义:

// org.springframework.beans.factory.support.AbstractBeanFactory#getBean(java.lang.String)
public Object getBean(String name) throws BeansException {
    // 真正获取bean的方法
    return doGetBean(name, null, null, false);
}

getBean()方法内部通过doGetBean()执行真正获取bean,大体过程如下:

  1. 第一步:转换bean的名称,包括去除FactoryBean引用前缀“&”,如果是别名就需要找到它最终指向的beanName;
  2. 第二步:尝试从缓存中获取对应的bean;
  3. 第三步:返回beanName对应的实例对象,内部包含对FactoryBean的处理;
  4. 第四步:如果在当前工厂中获取不到bean实例,则获取到父容器,如果不存在当前beanName对应的bean定义信息,则尝试从父容器获取对应的bean;
  5. 第五步:将指定的 bean 标记为已创建(或即将创建);
  6. 第六步:返回bean定义信息;
  7. 第七步:获取到当前bean依赖的bean名称集合,保证当前bean依赖的bean的初始化;
  8. 第八步:尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean实例,并添加到缓存中;
  9. 第九步:检查所需类型是否与实际 bean 实例的类型匹配;
  10. 第十步:返回上述创建好的bean实例对象;

doGetBean()方法源码如下:

protected  T doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
    // 1、第一步:转换bean的名称,包括去除FactoryBean引用前缀“&”;如果是别名就需要找到最终指向的beanName
    String beanName = transformedBeanName(name);
    Object bean;

    // 2、第二步:尝试从缓存中获取对应的bean(解决循环依赖的方法)
    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 + "'");
            }
        }
        // 如果存在手动注册的单例
        // 3、第三步:返回beanName对应的实例对象,内部包含对FactoryBean的处理
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {  // 如果不存在手动注册的单例
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.

        // Spring容器将每一个正在创建的bean标识符放在一个“当前创建bean池”中,bean在创建过程中将一直保持在这个池中,
        // 如果在创建bean过程中发现自己已经在“当前创建bean池”中,将抛出BeanCurrentlyInCreationException异常,表示发生了循环依赖。
        // bean创建完毕后,将会从“当前创建bean池”中移除掉
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.

        // 4、第四步:获取到父容器,如果不存在当前beanName对应的bean定义信息,则尝试从父容器获取对应的bean
        // 获取父容器
        BeanFactory parentBeanFactory = getParentBeanFactory();
        // 如果存在父容器,并且在当前工厂中不存在当前beanName对应的Bean定义信息,则尝试从父容器中获取bean实例
        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) {
            // 如果不是仅仅做类型检测,则将指定的 bean 标记为已创建(或即将创建)
            // private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256))
            // 也就是将beanName存入上述alreadyCreated集合中
            markBeanAsCreated(beanName);
        }

        try {
            // 6、第六步:返回bean定义信息
            RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            // 校验bean定义信息,如果是抽象的,则抛异常BeanIsAbstractException
            checkMergedBeanDefinition(mbd, beanName, args);

            // 7、第七步:获取到当前bean依赖的bean名称集合,保证当前bean依赖的bean的初始化
            String[] dependsOn = mbd.getDependsOn();
            if (dependsOn != null) {
                for (String dep : dependsOn) {
                    // 检查是否存在循环依赖
                    if (isDependent(beanName, dep)) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                    }
                    // 如果BeanDefinition有依赖,就先把依赖关系注册到容器的dependentBeanMap缓存,再递归加载依赖的bean
                    registerDependentBean(dep, beanName);
                    try {
                        // 先实例化当前bean依赖的其他bean
                        getBean(dep);
                    } catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                                        "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            
            // 单例bean的创建
            if (mbd.isSingleton()) {  //单例作用域
                // 第二个参数是一个ObjectFactory,是一个函数式接口,当调用ObjectFactory的getObject()方法的时候,实际上调用的是createBean(beanName, mbd, args)
                // 也就是说在getSingleton()方法内部调用ObjectFactory的getObject()方法的时候,会回调到这里的createBean(beanName, mbd, args)创建bean,接着才会调用下面的getObjectForBeanInstance()方法

                // 8、第八步:尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean
                sharedInstance = getSingleton(beanName, () -> {
                    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;
                    }
                });
                // 返回beanName对应的实例对象
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }
            else if (mbd.isPrototype()) {  //多例bean的创建
                Object prototypeInstance = null;
                try {
                    // 多例bean创建前的操作:保存beanName到prototypesCurrentlyInCreation缓存中(为了防止循环依赖)
                    // private final ThreadLocal prototypesCurrentlyInCreation = new NamedThreadLocal<>("Prototype beans currently in creation");
                    beforePrototypeCreation(beanName);
                    // 创建bean实例
                    prototypeInstance = createBean(beanName, mbd, args);
                } finally {
                    // 多例bean创建后的操作:移除prototypesCurrentlyInCreation缓存中保存的beanName
                    // 即执行this.prototypesCurrentlyInCreation.remove()
                    afterPrototypeCreation(beanName);
                }
                // 返回beanName对应的实例对象
                bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
            }

            else {
                // 其它作用域的bean对象的创建
                // 在spring中,主要有singleton、prototype、request、session等作用域,前面已经处理了singleton、prototype两种作用域,剩下的都会走这个逻辑
                String scopeName = mbd.getScope();
                if (!StringUtils.hasLength(scopeName)) {
                    throw new IllegalStateException("No scope name defined for bean ´" + beanName + "'");
                }
                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, () -> {
                        // bean创建前的操作:保存beanName到prototypesCurrentlyInCreation缓存中
                        beforePrototypeCreation(beanName);
                        try {
                            // 创建bean实例
                            return createBean(beanName, mbd, args);
                        } finally {
                            // bean创建后的操作:移除prototypesCurrentlyInCreation缓存中保存的beanName
                            afterPrototypeCreation(beanName);
                        }
                    });
                    // 返回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) {
            // 在bean创建失败后对缓存的元数据执行适当的清理
            // 也就是将beanName从alreadyCreated缓存中移除
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.

    // 9、第九步:检查所需类型是否与实际 bean 实例的类型匹配
    if (requiredType != null && !requiredType.isInstance(bean)) {
        try {
            // 如果类型不匹配,则需要将bean转换为要求的类型
            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());
        }
    }
    // 10、第十步:返回上述创建好的bean实例对象
    return (T) bean;
} 

下面对一些比较重要的方法做一下分析:

  • transformedBeanName(name):转换bean的名称,必要时去除FactoryBean引用前缀“&”,如果是别名就去寻找它最终指向的beanName;
// 返回 bean 名称,包括去除FactoryBean引用前缀,并将别名解析为真正的bean名称
protected String transformedBeanName(String name) {
    return canonicalName(BeanFactoryUtils.transformedBeanName(name));
}

// org.springframework.beans.factory.BeanFactoryUtils#transformedBeanName
public static String transformedBeanName(String name) {
    Assert.notNull(name, "'name' must not be null");
    // 如果name不是以&开头,则直接返回,无需处理
    if (!name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
        return name;
    }

    // 如果name以&开头,则需要处理,获取到实际的bean名称
    return transformedBeanNameCache.computeIfAbsent(name, beanName -> {
        do {
            // 截取掉FactoryBean的前缀&
            beanName = beanName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
        }
        while (beanName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
        return beanName;
    });
}

// org.springframework.core.SimpleAliasRegistry#canonicalName
// 确定bean原始名称,将别名解析为真正的bean名称
public String canonicalName(String name) {
    String canonicalName = name;
    // Handle aliasing...
    String resolvedName;
    do {
        // 处理别名
        resolvedName = this.aliasMap.get(canonicalName);
        if (resolvedName != null) {
            canonicalName = resolvedName;
        }
    } while (resolvedName != null);
    return canonicalName;
}

  •  getSingleton(beanName):尝试从缓存中获取对应的bean

getSingleton()方法是Spring中用来解决循环依赖的核心代码,涉及到三级缓存、提前暴露对象等,后面我们单独用一篇文章总结Spring是如何解决循环依赖的。

getSingleton()方法大体过程如下:

  1. 第一步:从一级缓存中(singletonObjects)中尝试获取;
  2. 第二步:如果一级缓存没有获取到,就从提早曝光单例对象(earlySingletonObjects)二级缓存中尝试获取;
  3. 第三步:如果二级缓存中还没有,就从singletonFactories(三级缓存)中尝试获取这个bean的ObjectFactory对象工厂,再调用ObjectFactory.getObject()获取到bean,然后放入earlySingletonObjects二级缓存中,把ObjectFactory从singletonFactories(三级缓存)中移除;

getSingleton()源码如下:

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String)
public Object getSingleton(String beanName) {
    // 尝试从缓存中加载bean对象
    // 第二个参数:表示是否允许bean早期依赖
    // 调用重载的getSingleton()方法
    return getSingleton(beanName, true);
}

// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
// Spring 解决循环引用的核心代码
@Nullable
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    // Quick check for existing instance without full singleton lock

    // 尝试从一级缓存中获取对应的bean对象
    Object singletonObject = this.singletonObjects.get(beanName);
    // 如果一级缓存中不存在,并且当前单例bean处于正在创建中
    if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
        // 如果一级缓存中没有的话,再尝试从二级缓存中获取对应的bean对象
        // 从早期单例对象缓存earlySingletonObjects中获取单例对象(之所称为早期单例对象,是因为earlySingletonObjects里的对象的都是通过提前曝光的ObjectFactory对象工厂创建出来的,还未进行属性填充等操作)
        singletonObject = this.earlySingletonObjects.get(beanName);
        if (singletonObject == null && allowEarlyReference) {
            // 加锁
            synchronized (this.singletonObjects) {
                // Consistent creation of early reference within full singleton lock
                singletonObject = this.singletonObjects.get(beanName);
                if (singletonObject == null) {
                    singletonObject = this.earlySingletonObjects.get(beanName);
                    if (singletonObject == null) {
                        // 如果二级缓存中也没有的话,再尝试从三级缓存中获取对应的ObjectFactory单例工厂
                        ObjectFactory singletonFactory = this.singletonFactories.get(beanName);

                        // 如果存在单例工厂,则调用单例工厂ObjectFactory的getObject()方法,创建一个bean
                        if (singletonFactory != null) {

                            // 调用ObjectFactory的getObject()方法,产生一个半成品bean
                            // 因为添加三级缓存的时候执行的是: addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean)),
                            // 所以singletonFactory.getObject()真正执行的其实是:获取bean的早期引用  ===>  getEarlyBeanReference(beanName, mbd, bean)
                            singletonObject = singletonFactory.getObject();

                            
                            // 将bean放置于二级缓存中(放到早期单例对象缓存中)
                            this.earlySingletonObjects.put(beanName, singletonObject);

                            // 删除三级缓存中对应bean的单例工厂ObjectFactory
                            // 因为该单例工厂已经创建了一个实例对象,并且放到earlySingletonObjects缓存(二级缓存)中了,所以后面获取beanName的单例对象的时候,
                            // 可以从earlySingletonObjects二级缓存拿到,不需要再用到该单例工厂
                            this.singletonFactories.remove(beanName);

                        }
                    }
                }
            }
        }
    }
    // 返回单例对象
    return singletonObject;
}

 Spring循环依赖涉及到三个缓存,这里先简单介绍一下:

  1. singletonObjects:一级缓存,它用于存放初始化好的 bean 实例;
  2. earlySingletonObjects:二级缓存,它用于存放初始化中的 bean,此时的bean是一个半成品,提前暴露的对象都放在这里,Spring利用它来解决循环依赖;
  3. singletonFactories:三级缓存,它用于存放生成bean的对象工厂,注意bean 工厂所生成的 bean 还没有完成初始化;
  • getObjectForBeanInstance(sharedInstance, name, beanName, null):返回beanName对应的实例对象

getObjectForBeanInstance()大体流程如下:

  1. 第一步:判断name是否以“&”为前缀;
  2. 第二步:如果name以“&”为前缀,但是又不是一个FactoryBean的话,则会抛出BeanIsNotAFactoryException异常;
  3. 第三步:如果beanInstance不是FactoryBean,则直接返回beanInstance;如果name以“&”为前缀,并且beanInstance是FactoryBean的话,表示希望获取到工厂bean对象,则直接返回beanInstance;
  4. 第四步:beanInstance是FactoryBean,并且name不是以“&”为前缀,表示希望获取到工厂帮我们创建的bean对象,则需要执行FactoryBean的getObject()方法帮我们创建对应的bean实例;
// org.springframework.beans.factory.support.AbstractBeanFactory#getObjectForBeanInstance
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是不是以“&”为前缀
    // 判断逻辑在isFactoryDereference()方法
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        // 2、如果name以“&”为前缀,但是又不是一个FactoryBean的话,则会抛出BeanIsNotAFactoryException异常
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
    }

    // 现在我们有了 bean 实例,它可能是普通 bean 或 FactoryBean.
    // 如果它是一个FactoryBean,我们用它来创建一个 bean 实例,除非调用者实际上想要一个对工厂的引用

    // 3、如果beanInstance不是FactoryBean,则直接返回beanInstance;如果name以“&”为前缀,并且beanInstance是FactoryBean的话,则直接返回beanInstance;

    // !(beanInstance instanceof FactoryBean): 如果beanInstance不是FactoryBean,则直接返回beanInstance
    // BeanFactoryUtils.isFactoryDereference(name): 如果name以“&”为前缀,并且beanInstance是FactoryBean的话,则直接返回beanInstance
    // 前面已经介绍过,如果bean实现了FactoryBean结果,并且通过getBean(&beanName)获取bean的话,则获取的是FactoryBean本身
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    // 4、beanInstance是FactoryBean,并且name不是以“&”为前缀,表示需要执行FactoryBean的getObject()方法帮我们创建对应的bean实例
    Object object = null;
    if (mbd == null) {
        // 如果mdb为空,尝试从factoryBeanObjectCache缓存中获取FactoryBean创建的对象实例
        // 如果缓存中存在对象实例,则直接返回object
        object = getCachedObjectForFactoryBean(beanName);
    }

    // 缓存中不存在对应的对象实例
    if (object == null) {
        // Return bean instance from factory.
        FactoryBean factory = (FactoryBean) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        if (mbd == null && containsBeanDefinition(beanName)) {
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        // 从FactoryBean中获取对应的对象实例,底层实际上是执行FactoryBean的getObject()方法
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}
  • BeanFactoryUtils.isFactoryDereference(name):判断name是否以&为前缀
// org.springframework.beans.factory.BeanFactoryUtils#isFactoryDereference
public static boolean isFactoryDereference(@Nullable String name) {
    // 判断name是否以&为前缀
    // String FACTORY_BEAN_PREFIX = "&";
    return (name != null && name.startsWith(BeanFactory.FACTORY_BEAN_PREFIX));
}
  • getObjectFromFactoryBean():从给定的 FactoryBean 获取要公开的对象
// 从给定的 FactoryBean 获取要公开的对象
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#getObjectFromFactoryBean
protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
    // 如果是单例的,并且beanName已经在singletonObjects单例缓存池中
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            // 尝试从FactoryBean创建的单例对象的缓存factoryBeanObjectCache中获取bean实例
            Object object = this.factoryBeanObjectCache.get(beanName);

            // 缓存factoryBeanObjectCache中获取bean实例为空,则执行doGetObjectFromFactoryBean()创建bean实例
            if (object == null) {
                // 这里真正执行FactoryBean的getObject()方法创建bean
                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)
                Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                if (alreadyThere != null) {
                    object = alreadyThere;
                } else {
                    // 是否需要后置增强处理
                    if (shouldPostProcess) {
                        if (isSingletonCurrentlyInCreation(beanName)) {
                            // Temporarily return non-post-processed object, not storing it yet..
                            return object;
                        }
                        // 单例创建前的准备:将beanName添加到singletonsCurrentlyInCreation缓存中
                        beforeSingletonCreation(beanName);

                        try {
                            // 执行BeanPostProcessor的postProcessAfterInitialization()方法
                            // 具体参考:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        } catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                                            "Post-processing of FactoryBean's singleton object failed", ex);
                        } finally {
                            // 单例创建完成后的工作:移除singletonsCurrentlyInCreation中对应的beanName缓存
                            afterSingletonCreation(beanName);
                        }
                    }
                    if (containsSingleton(beanName)) {
                        // 将beanName和object放到factoryBeanObjectCache缓存中,这样下来再次获取,就可以从缓存中获取,无需重复创建
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            // 如果缓存factoryBeanObjectCache中获取bean实例不为空,则直接返回
            return object;
        }
    } else {
        // 非单例的
        // 这里真正执行FactoryBean的getObject()方法创建bean
        Object object = doGetObjectFromFactoryBean(factory, beanName);
        if (shouldPostProcess) {
            try {
                // 后置增强
                object = postProcessObjectFromFactoryBean(object, beanName);
            }
            catch (Throwable ex) {
                throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
            }
        }
        return object;
    }
}
  • doGetObjectFromFactoryBean():真正执行FactoryBean的getObject()方法创建bean
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#doGetObjectFromFactoryBean
private Object doGetObjectFromFactoryBean(FactoryBean factory, String beanName) throws BeanCreationException {
    Object object;
    try {
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = getAccessControlContext();
            try {
                // 执行FactoryBean的getObject()方法
                object = AccessController.doPrivileged((PrivilegedExceptionAction) factory::getObject, acc);
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        } else {
            // 执行FactoryBean的getObject()方法
            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);
    }

    // 不接受尚未完全初始化的FactoryBean返回的null值:许多FactoryBean只返回 null
    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;
} 
  • postProcessObjectFromFactoryBean(object, beanName):执行后置增强
// org.springframework.beans.factory.support.FactoryBeanRegistrySupport#postProcessObjectFromFactoryBean
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) throws BeansException {
    return object;
}

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#postProcessObjectFromFactoryBean
protected Object postProcessObjectFromFactoryBean(Object object, String beanName) {
    return applyBeanPostProcessorsAfterInitialization(object, beanName);
}

// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        // 执行BeanPostProcessor的后置增强方法postProcessAfterInitialization()
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}
  • markBeanAsCreated(beanName):将指定的 bean 标记为已创建
// 将指定的 bean 标记为已创建
protected void markBeanAsCreated(String beanName) {
    // private final Set alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256))
    // 如果alreadyCreated缓存中不包含指定的beanName
    if (!this.alreadyCreated.contains(beanName)) {
        // 加锁,避免BeanDefinition发生变化
        synchronized (this.mergedBeanDefinitions) {
            // 再一次判断
            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.

                // 实际上执行this.mergedBeanDefinitions.remove(beanName):移除缓存mergedBeanDefinitions中beanName对应的bean定义信息
                // 为了后面的代码重新获取时,能使用到最新的MergedBeanDefinition来创建bean实例
                clearMergedBeanDefinition(beanName);

                // 将beanName存入alreadyCreated缓存,标记bean为已创建
                this.alreadyCreated.add(beanName);
            }
        }
    }
}

 从上图中我们也可以看到,在本例子中,student这个beanName已经被加入到alreadyCreated缓存中。

  • getSingleton(String beanName, ObjectFactory singletonFactory):尝试从缓存中获取对应的bean实例,获取不到的话,则执行singletonFactory的回调 -> createBean()创建bean
public Object getSingleton(String beanName, ObjectFactory singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");

    // 加锁,避免重复创建单例对象
    synchronized (this.singletonObjects) {
        // 尝试从一级缓存中获取对应的bean
        Object singletonObject = this.singletonObjects.get(beanName);

        // 如果一级缓存中存在的话,则直接返回singletonObject
        // 如果一级缓存中不存在的话,才进行singletonObject的创建
        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 + "'");
            }

            // 创建单例前的操作:通过this.singletonsCurrentlyInCreation.add(beanName)记录bean正在加载的状态,将当前正要创建的bean记录在缓存singletonsCurrentlyInCreation中
            // 	private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
            beforeSingletonCreation(beanName);

            // 是否是一个新的单例对象的标识
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new linkedHashSet<>();
            }
            try {
                // 执行singletonFactory的回调,也就是FactoryBean真正帮我们创建对象的地方
                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;
                }

                // 创建单例后的操作:通过this.singletonsCurrentlyInCreation.remove(beanName)移除bean正在加载状态的记录
                // 	private final Set singletonsCurrentlyInCreation = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                // 如果是新的bean对象,则将bean保存到一级缓存(singletonObjects)、已注册bean缓存(registeredSingletons)中,同时删除二级缓存(earlySingletonObjects)、三级缓存(singletonFactories)中对应的bean信息
                addSingleton(beanName, singletonObject);
            }
        }
        // 返回处理结果
        return singletonObject;
    }
}

getSingleton(String beanName, ObjectFactory singletonFactory)主要步骤:

  • a、尝试从一级缓存中获取对应的bean,如果获取到,直接返回;如果获取不到,则执行singletonFactory.getObject()方法回调,从方法调用处可以看到,执行createBean()方法,这个方法也是非常重要的一个方法,里面包括了bean的实例化、初始化等,后面单独分析。

  • b、创建单例前的操作,记录bean正在加载的状态,将当前正要创建的bean记录在缓存singletonsCurrentlyInCreation中;
  • c、创建单例后的操作:通过this.singletonsCurrentlyInCreation.remove(beanName)移除bean正在加载状态的记录;
  • d、如果是新的bean对象,则将bean保存到一级缓存(singletonObjects)、已注册bean缓存(registeredSingletons)中,同时删除二级缓存(earlySingletonObjects)、三级缓存(singletonFactories)中对应的bean信息;

来看几个关键方法的代码:

  • beforeSingletonCreation():创建单例前的操作
protected void beforeSingletonCreation(String beanName) {
    // inCreationCheckExclusions表示当前从创建检查中排除的bean的名称,通常情况下为空
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.add(beanName)) {
        throw new BeanCurrentlyInCreationException(beanName);
    }
}

如上图,本例中的student的beanName已经添加到singletonsCurrentlyInCreation缓存中了。

  • afterSingletonCreation():创建单例后的操作
protected void afterSingletonCreation(String beanName) {
    if (!this.inCreationCheckExclusions.contains(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) {
        throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation");
    }
}

同理,beforeSingletonCreation()方法添加对应的缓存,那么afterSingletonCreation()创建完后续工作就是需要移除对应的缓存:

  • addSingleton():添加bean到一级缓存中,方面后面直接获取
protected void addSingleton(String beanName, Object singletonObject) {
    synchronized (this.singletonObjects) {
        // 将bean保存到一级缓存中
        this.singletonObjects.put(beanName, singletonObject);
        // 删除三级缓存对应的bean
        this.singletonFactories.remove(beanName);
        // 删除二级缓存中对应的bean
        this.earlySingletonObjects.remove(beanName);
        // 记录当前所有已注册的bean
        this.registeredSingletons.add(beanName);
    }
}

 三、总结

到这里,关于Spring中getBean()获取bean实例的核心流程基本上就介绍完了,我们可以看到,获取一个bean的流程还是比较复杂的,涉及到了非常多的流程。读者在学习过程中,可以多跟踪几次源代码,对一些特殊场景写一些示例代码调试,逐步了解Spring是如何获取bean实例的,慢慢地对getBean流程就没那么陌生了。

最后我们简述一下getBean()整体流程:

1、将name转化为真正的beanName,包括去除FactoryBean的前缀符&,将别名转换为真正beanName

2、通过getSingleton()方法尝试从缓存中获取指定的bean对象

        2.1、先从一级缓存singletonObjects中查找;

        2.2、如果一级缓存中在找不到的话,再尝试从二级缓存earlySingletonObjects(提早曝光单例缓存池)中查找;

        2.3、如果二级缓存也找不到的话,则从三级缓存singletonFactories中查找ObjectFactory对象工厂,并生成对应的bean对象,然后放入earlySingletonObjects二级缓存中,

最后移除三级缓存中对应的ObjectFactory对象工厂;

3、如果缓存中都没有找到对应的bean,则需要新建一个bean

        3.1、从当前容器中查找对应的BeanDefinition定义信息;

        3.2、如果当前容器没找到,再从父容器中查找有没有BeanDefinition;

        3.3、获取到BeanDefinition中定义的depends-on依赖的bean对象,递归加载的其依赖的bean对象;

        3.4、根据不同的scope分别创建bean实例;

4、如果是FactoryBean,返回生产的bean

        4.1、首先尝试从缓存factoryBeanObjectCache中获取;

        4.2、如果获取的到,则直接返回,否则调用BeanFactory.getObject()生产一个bean实例;

        4.3、如果不是应用程序本身的bean,调用后置处理器BeanPostProcessor的postProcessAfterInitialization()方法;

        4.4、如果是单例的话存入factoryBeanObjectCache缓存中;

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号