doGetBean方法

代码解析

org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean

protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
            @Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
        //通过三种形式获取beanName
        //一个是原始的beanName,一个是加了&的,一个是别名
        final String beanName = transformedBeanName(name);

        // Eagerly check singleton cache for manually registered singletons.
        //尝试从单例缓存集合里获取bean实例
        Object sharedInstance = getSingleton(beanName);
        Object bean;
        //如果先前已经创建过单例Bean的实例,并且调用的getBean方法传入的参数为空
        //则执行if里面的逻辑
        //args之所以要求为空是因为如果有args,则需要做进一步赋值,因此无法直接返回
        if (sharedInstance != null && args == null) {
            if (logger.isTraceEnabled()) {
                //如果Bean还在创建中,则说明是循环引用
                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 + "'");
                }
            }
            //如果是普通bean,直接返回,如果是FactoryBean,则返回它的getObject
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
        }
        //若scope为prototype或者单例模式但是缓存中还不存在bean
        else {
            //如果scope为prototype并且 显示还在创建中,则基本是循环依赖的情况
            //针对prototype的循环依赖,spring误解,直接抛出异常
            if (isPrototypeCurrentlyInCreation(beanName)) {
                throw new BeanCurrentlyInCreationException(beanName);
            }

            // Check if bean definition exists in this factory.
            BeanFactory parentBeanFactory = getParentBeanFactory();
            //从当前容器中找不到指定名称的bean,此时递归去parentFactory查找
            if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
                // Not found -> check parent.
                //主要针对FactoryBean,将Bean的&重新加上
                String nameToLookup = originalBeanName(name);
                //如果parent容器依旧是AbstractBeanFactory的实例
                //instanceof通过返回一个布尔值来指出,这个对象是否是这个特定类或者是它的子类的一个实例
                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) {
                    // No args -> delegate to standard getBean method.
                    //委派父级容器根据指定名称和类型查找
                    return parentBeanFactory.getBean(nameToLookup, requiredType);
                }
                else {
                    //委派父级容器根据指定名称查找
                    return (T) parentBeanFactory.getBean(nameToLookup);
                }
            }
            //typeCheckOnly是用来判断调用getBean()是否仅仅是为了类型检查获取bean,而不是为了创建Bean
            if (!typeCheckOnly) {
                //如果不是仅仅做类型检查则是创建bean
                markBeanAsCreated(beanName);
            }

            try {
                //将父类的BeanDefinition与子类的BeanDefinition进行合并覆盖
                final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
                //对合并的BeanDefinition做验证,主要看属性是否为abstract的
                checkMergedBeanDefinition(mbd, beanName, args);

                // Guarantee initialization of beans that the current bean depends on.
                //获取当前Bean所有依赖Bean的名称
                String[] dependsOn = mbd.getDependsOn();
                //如果当前Bean设置了dependsOn的属性
                //depends-on用来指定Bean初始化及销毁时的顺序
                //<bean id="a" Class="com.imooc.A" depends-on="b" />
                //<bean id="b" Class="com.imooc.B" />
                if (dependsOn != null) {
                    for (String dep : dependsOn) {
                        //校验该依赖是否已经注册给当前bean,注意这里传入的key是当前的bean名称
                        //这里主要是判断是否有以下这种类型的依赖:
                        //<bean id="beanA" Class="com.imooc.A" depends-on="beanB" />
                        //<bean id="beanB" Class="com.imooc.B" depends-on="beanA" />
                        //如果有,直接抛出异常
                        if (isDependent(beanName, dep)) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
                        }
                        //缓存依赖调用,注意这里传入的key是被依赖的bean名称
                        registerDependentBean(dep, beanName);
                        try {
                            //递归调用getBean方法,注册Bean之间的依赖(如C需要晚于B初始化,而B需要晚于A初始化)
                            //初始化依赖的bean
                            getBean(dep);
                        }
                        catch (NoSuchBeanDefinitionException ex) {
                            throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                    "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                        }
                    }
                }

                // Create bean instance.
                //如果BeanDefinition为单例
                if (mbd.isSingleton()) {
                    //这里使用了一个匿名内部类,创建Bean实例对象,并且注册给所依赖的对象
                    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,直接返回,如果是FactoryBean,则返回它的getObject
                    bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
                }

                else if (mbd.isPrototype()) {
                    // It's a prototype -> create a new instance.
                    Object prototypeInstance = null;
                    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;
            }
        }

        // Check if required type matches the type of the actual bean instance.
        //检查需要的类型是否符合bean的实际类型
        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;
    }

核心步骤

尝试从缓存中加载单例

单例在spring容器内只会创建一次,后续获取都是从单例缓存中获取。如果获取不到则从singletonFactories中加载。因为在创建单例bean的时候会存在依赖注入的情况,而在创建的时候为了避免循环依赖,在Spring中创建bean的原则是不等bean创建完就会将创建bean的ObjectFactory提早曝光,也就是将ObjectFactory加入到缓存中,一旦下个bean创建时候需要依赖上个bean则直接使用ObjectFactory。

缓存池获取bean实例:

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
    //一级缓存:存放的是已经完成实例化,属性填充和初始化步骤的单例bean实例
    Object singletonObject = this.singletonObjects.get(beanName);
    if (singletonObject == null && this.isSingletonCurrentlyInCreation(beanName)) {
        synchronized(this.singletonObjects) {
            //二级缓存:存放的是提前暴露的单例bean实例,可能是代理对象,也可能是未经代理的原对象,但都还没有完成初始化的步骤
            singletonObject = this.earlySingletonObjects.get(beanName);
            if (singletonObject == null && allowEarlyReference) {
                //三级缓存:存放的是ObjectFactory的匿名内部类实例
                ObjectFactory<?> singletonFactory = (ObjectFactory)this.singletonFactories.get(beanName);
                if (singletonFactory != null) {
                    //回调ObjectFactory#getObject方法获取提前暴露的引用
                    singletonObject = singletonFactory.getObject();
                    //移入二级缓存
                    this.earlySingletonObjects.put(beanName, singletonObject);
                    //移除三级缓存
                    this.singletonFactories.remove(beanName);
                }
            }
        }
    }
    return singletonObject != NULL_OBJECT ? singletonObject : null;
}

   转载规则


《doGetBean方法》 锦泉 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录