AbstractBeanFactory#getBean(beanName)

由于 getBean 内容比较多, 所以单独出来, 接着上一篇的顺序来看.

//org.springframework.beans.factory.support.AbstractBeanFactory#getBean
@Override
public Object getBean(String name) throws BeansException {
    return doGetBean(name, null, null, false);
}

doGetBean里面, 有一堆乱七八糟的判断,

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

    /**
     * 通过 name 获取 beanName。这里不使用 name 直接作为 beanName 有两个原因
     * 1、name 可能会以 & 字符开头,表明调用者想获取 FactoryBean 本身,而非 FactoryBean
     *   实现类所创建的 bean。在 BeanFactory 中,FactoryBean 的实现类和其他的 bean 存储
     *   方式是一致的,即 <beanName, bean>,beanName 中是没有 & 这个字符的。所以我们需要
     *   将 name 的首字符 & 移除,这样才能从缓存里取到 FactoryBean 实例。
     * 2、还是别名的问题,转换需要
     * &beanName
     */
    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    /**
     * 这个方法在初始化的时候会调用,在getBean的时候也会调用
     * 为什么需要这么做呢?
     * 也就是说spring在初始化的时候先获取这个对象
     * 判断这个对象是否被实例化好了(普通情况下绝对为空====初始化完之后, 此处返回就不是空了)
     * 从spring的bean容器中获取一个bean,由于spring中bean容器是一个map(singletonObjects)
     * 所以你可以理解getSingleton(beanName)等于beanMap.get(beanName)
     * 由于方法会在spring环境初始化的时候(就是对象被创建的时候调用一次)调用一次
     * 还会在getBean的时候调用一次
     *
     * 需要说明的是在初始化时候调用一般都是返回null
     */
    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 + "'");
            }
        }
        /**
         * 如果 sharedInstance 是普通的单例 bean,下面的方法会直接返回。
         * 但如果 sharedInstance 是 FactoryBean 类型的,则需调用 getObject 工厂方法获取真正的 bean 实例。
         * 如果用户想获取 FactoryBean 本身,这里也不会做特别的处理,直接返回即可。
         * 毕竟 FactoryBean 的实现类本身也是一种 bean,只不过具有一点特殊的功能而已。
         */
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }
    else {
        // Fail if we're already creating this bean instance:
        // We're assumably within a circular reference.
        /**
         * 原型模式
         * 如果是原型不应该在初始化的时候创建
         */
        if (isPrototypeCurrentlyInCreation(beanName)) {
            throw new BeanCurrentlyInCreationException(beanName);
        }

        // Check if bean definition exists in this factory.
        BeanFactory parentBeanFactory = getParentBeanFactory();
        if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
           ......
        }

        if (!typeCheckOnly) {
            //添加到 alreadyCreated set集合当中,表示他已经创建过一场
            markBeanAsCreated(beanName);
        }

        try {
            final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
            //bd检测, 如果是 abstract, 则抛异常
            checkMergedBeanDefinition(mbd, beanName, args);

            // Guarantee initialization of beans that the current bean depends on.
            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 + "'");
                    }
                    registerDependentBean(dep, beanName);
                    try {
                        getBean(dep);
                    }
                    catch (NoSuchBeanDefinitionException ex) {
                        throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                                "'" + beanName + "' depends on missing bean '" + dep + "'", ex);
                    }
                }
            }

            // 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.
                        destroySingleton(beanName);
                        throw ex;
                    }
                });
                bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
            }

            else if (mbd.isPrototype()) {
                ......
            }

            else {
                ......
            }
        }
        catch (BeansException ex) {
            cleanupAfterBeanCreationFailure(beanName);
            throw ex;
        }
    }

    // Check if required type matches the type of the actual bean instance.
    if (requiredType != null && !requiredType.isInstance(bean)) {
        ......
    }
    return (T) bean;
}

方法比较长, 我删掉一部分. 不影响观看.

主要看两个方法 :

1.getSingleton(String beanName, ObjectFactory<?> singetonFactory)

2.createBean

 

getSingleton

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
    Assert.notNull(beanName, "Bean name must not be null");
    synchronized (this.singletonObjects) {
        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 + "'");
            }
            /**
             * 将beanName添加到singletonsCurrentlyInCreation这样一个set集合中
             * 表示beanName对应的bean正在创建中
             */
            beforeSingletonCreation(beanName);
            boolean newSingleton = false;
            boolean recordSuppressedExceptions = (this.suppressedExceptions == null);
            if (recordSuppressedExceptions) {
                this.suppressedExceptions = new LinkedHashSet<>();
            }
            try {
                //这里会调用传入的 lambda 表达式创建的匿名 singletonFactory 对象, 调用他的 getObject() 方法
                //其方法内部, 也就是调用 org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.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;
                }
                //把标识为正在创建的标识去掉
                afterSingletonCreation(beanName);
            }
            if (newSingleton) {
                addSingleton(beanName, singletonObject);
            }
        }
        return singletonObject;
    }
}

 这里的getSingleton , 明显是一个创建 bean 的地方. 

1. 在创建之前, 通过 beforeSingletonCreation() 方法, 执行了  this.singletonsCurrentlyInCreation.add(beanName) 这句代码,

这里其实是在做一个标志, 表示 这个 beanName 对应的 bean 正在创建当中. 将 singletonsCurrentlyInCreation 翻译过来, 就能看懂. 

这里做到了变量名的命名就是最好的注释.

2. 调用 factory.getObject 方法, 进行 bean 的创建, 调用的其实就是 createBean() 方法.

3. 创建完成之后, 通过 afterSingletonCreation() 方法, 将标志位改回去, 其内部执行了 this.singletonsCurrentlyInCreation.remove(beanName) 这句代码.

4. 在最后, 通过 addSingleton() 方法, 将创建的 bean 放到 spring 容器中 : this.singletonObjects.put(beanName, singletonObject)

 这里的这个顺序很重要, 尤其是那个 正在创建的标志, 很重要的 : singletonsCurrentlyInCreation 

这个正在创建的标志, 在解决 循环依赖的时候, 起了很重要的作用

 

createBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean

@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
        throws BeanCreationException {

    if (logger.isTraceEnabled()) {
        logger.trace("Creating instance of bean '" + beanName + "'");
    }
    RootBeanDefinition mbdToUse = mbd;

    // Make sure bean class is actually resolved at this point, and
    // clone the bean definition in case of a dynamically resolved Class
    // which cannot be stored in the shared merged bean definition.
    Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
    if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
        mbdToUse = new RootBeanDefinition(mbd);
        mbdToUse.setBeanClass(resolvedClass);
    }

    //Prepare method overrides.
    //处理xml中的 lookup-method 和 replace-method 配置,Spring将这两个配置统称为override method
    try {
        mbdToUse.prepareMethodOverrides();
    }
    catch (BeanDefinitionValidationException ex) {
        throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),
                beanName, "Validation of method overrides failed", ex);
    }

    try {
        // Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
        // 在 bean实例化之前 应用后置处理,如果后置处理返回的bean不为空,则直接返回
        // 返回的是一个寡妇对象, 属性什么的, spring不会去维护
        // spring不推荐开发人员使用这个接口 InstantiationAwareBeanPostProcessor
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        if (bean != null) {
            return bean;
        }
    }
    catch (Throwable ex) {
        throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
                "BeanPostProcessor before instantiation of bean failed", ex);
    }

    try {
        // 创建bean
        Object beanInstance = doCreateBean(beanName, mbdToUse, args);
        if (logger.isTraceEnabled()) {
            logger.trace("Finished creating instance of bean '" + beanName + "'");
        }
        return beanInstance;
    }
    catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
        // A previously detected exception with proper bean creation context already,
        // or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(
                mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);
    }
}

 

在 spring 里面, 有一个习惯, 喜欢把 真正干活的那个方法, 以 do 开头.

所以, 这个 doCreateBean() 方法, 应该就是干活方法.

不过在此之前, 要看一个重要扩展方法: resolveBeforeInstantiation

 

posted @ 2020-07-27 21:16  Sniper_ZL  阅读(424)  评论(0编辑  收藏  举报