5.3从bean的实例中获取对象

让我们尝试打开"5.bean的加载 - 3) bean的实例化的大门":
AbstractBeanFactory
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.
    //如果指定的name是工厂相关的(以&为前缀),那么返回工厂实例FactoryBean
    if (BeanFactoryUtils.isFactoryDereference(name)) {
        if (beanInstance instanceof NullBean) {
            return beanInstance;
        }
        //并且beanInstance又不是FactoryBean类型则验证不通过
        if (!(beanInstance instanceof FactoryBean)) {
            throw new BeanIsNotAFactoryException(beanName, beanInstance.getClass());
        }
        if (mbd != null) {
            mbd.isFactoryBean = true;
        }
        return beanInstance;
    }

    // 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.
    //如果beanInstance不是FactoryBean的实例,那么返回此实例
    //如果是FactoryBean,又没有&前缀,通过FactoryBean的getObject获取实例
    if (!(beanInstance instanceof FactoryBean)) {
        return beanInstance;
    }

    //加载FactoryBean
    Object object = null;
    if (mbd != null) {
        mbd.isFactoryBean = true;
    }
    else {
        //尝试从缓存中加载bean
        object = getCachedObjectForFactoryBean(beanName);
    }
    if (object == null) {
        // Return bean instance from factory.
        //到这里已经明确知道beanInstance一定是FactoryBean类型
        FactoryBean<?> factory = (FactoryBean<?>) beanInstance;
        // Caches object obtained from FactoryBean if it is a singleton.
        //containsBeanDefinition检测beanDefinitionMap中也就是所有已经加载的类中
        //检测是否定义beanName
        if (mbd == null && containsBeanDefinition(beanName)) {
            //将存储XML配置文件的GernericBeanDefinition转换为RootBeanDefinition
            //如果指定beanName是子bean的话同时合并父类相关属性
            mbd = getMergedLocalBeanDefinition(beanName);
        }
        //是否是用户定义的而不是应用程序本身定义的
        boolean synthetic = (mbd != null && mbd.isSynthetic());
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

 

大致逻辑:
首先Object beanInstance可能是BeanFactory,也可能已经是我们需要的实例。
1.如果beanName包含了 "&" 前缀,那么返回工厂实例Factory。
2.如果beanInstance不是Factory的实例,那么返回此实例。
3.如果beanInstance是Factory的实例,又不包含 "&" 前缀,通过FactoryBean的getObject获取实例返回,委托给getObjectFromFactoryBean()处理。
FactoryBeanRegistrySupport
protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
    //如果是单例模式并且singletonObjects包含了beanName
    if (factory.isSingleton() && containsSingleton(beanName)) {
        synchronized (getSingletonMutex()) {
            Object object = this.factoryBeanObjectCache.get(beanName);
            if (object == null) {
                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)
                //判断在getObject()期间缓存中是否设置了Bean
                //因为factoryBeanObjectCache是单例的,可以同时被别人操作
                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;
                        }
                        beforeSingletonCreation(beanName);
                        try {
                            //调用ObjectFactory的后处理
                            object = postProcessObjectFromFactoryBean(object, beanName);
                        }
                        catch (Throwable ex) {
                            throw new BeanCreationException(beanName,
                                                            "Post-processing of FactoryBean's singleton object failed", ex);
                        }
                        finally {
                            afterSingletonCreation(beanName);
                        }
                    }
                    if (containsSingleton(beanName)) {
                        this.factoryBeanObjectCache.put(beanName, object);
                    }
                }
            }
            return object;
        }
    }
    else {
        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;
    }
}

 

这里要注意的是第二处:
Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
因为doGetObjectFromFactoryBean获取getObject()期间缓存中可能设置好了我们需要的Bean。因为factoryBeanObjectCache是单例的,可以同时被别人操作。
FactoryBeanRegistrySupport
private Object doGetObjectFromFactoryBean(FactoryBean<?> factory, String beanName) throws BeanCreationException {
    Object object;
    try {
        //权限验证
        if (System.getSecurityManager() != null) {
            AccessControlContext acc = getAccessControlContext();
            try {
                object = AccessController.doPrivileged((PrivilegedExceptionAction<Object>) factory::getObject, acc);
            }
            catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }
        else {
            //直接调用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);
    }

    // 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.如果beanName包含了 "&" 前缀,那么返回工厂实例Factory。
2.如果beanInstance不是Factory的实例,那么返回此实例。
3.如果beanInstance是Factory的实例,又不包含 "&" 前缀,通过FactoryBean的getObject获取实例返回,委托给getObjectFromFactoryBean()处理。





posted @ 2021-01-13 17:13  _Shing  阅读(305)  评论(0)    收藏  举报