BeanFactory和FactoryBean的區別

BeanFactory

簡介

BeanFactory是Spring容器的Root Interface,提供了 IOC 容器最基本的功能。
BeanFactory只是一個接口,沒有具體的實現,但是它的實現類如XmlBeanFactory,ApplicationContext在其基礎之上附加了其他的功能。

源碼


public interface BeanFactory {

    /**
     *
     */
    String FACTORY_BEAN_PREFIX = "&";


    /**
     *  這個方法是BeanFactory的主要方法,通過指定名字可以取得IOC容器中相應的Bean對象
   *  這種方法使得Spring BeanFactory代替單例或原型設計模式來獲取Bean對象
     */
    Object getBean(String name) throws BeansException;

    /**
     * 也是獲取Bean對象的方法,但是增加了Class類型的安全驗證機制
   * 如果類型不符,則跑出BeanNotOfRequiredTypeException異常
     */
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    /**
     * 通過Bean類型獲取bean實例
     */
    <T> T getBean(Class<T> requiredType) throws BeansException;

    /**
     * 傳入的參數什麼用途 暫時不清楚
     */
    Object getBean(String name, Object... args) throws BeansException;

    /**
     *
     */
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;


    /**
     * 判斷是否含有指定名字的bean對象
     */
    boolean containsBean(String name);

    /**
     *判斷指定名稱的bean對象是否是單例,如果是,則永遠返回同一個對象
   * 可以在 BeanDefinition中設置
     */
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;

    /**
     * 判斷Bean是不是prototype的bean,是的話 返回獨立的實例
     */
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;

    /**
     *
     */
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 判斷指定名稱的bean對象的Class類型是否是特定的Class類型。
     */
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;

    /**
     * 獲取指定名稱bean對象的Class類型
     */
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;

    /**
     *查詢指定了名字的bean的所有別名,這些別名都是在BeanDefinition中定義的
     */
    String[] getAliases(String name);

}

FactoryBean

簡介

FactoryBean是一個接口,當在IOC容器中的Bean實現了FactoryBean後,通過getBean(String BeanName)獲取到的Bean對象並不是FactoryBean的實現類對象,而是這個實現類中的getObject()方法返回的對象。如果要獲取FactoryBean對象,在beanName前面加一個&符號來獲取,如:getBean(&BeanName)。

源碼

getBean


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

    final String beanName = transformedBeanName(name);
    Object bean;

    // Eagerly check singleton cache for manually registered singletons.
    Object sharedInstance = getSingleton(beanName);
    if (sharedInstance != null && args == null) {
        //。。。。
        bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
    }

    else {

        // 。。。。。
        if (mbd.isSingleton()) {
            //。。。。。
            bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
        }

        else if (mbd.isPrototype()) {
            // 。。。。
            bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
        }

        else {
                //scope獲取Bean。。。。
                bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);

        }


    }

    // ......
    return (T) bean;
}

我們在獲取Bean的過程中會發現,不管是從單例緩存還是新創建Bean過程中單例、原型或者Scope獲取Bean之後都會調用getObjectForBeanInstance()方法。

getObjectForBeanInstance


protected Object getObjectForBeanInstance(
        Object beanInstance, String name, String beanName, RootBeanDefinition mbd) {

    //  要獲取的Bean是帶有&符號,並且beanInstance不是FactoryBean則拋出異常
    if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
        throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
    }

    // beanInstance不是FactoryBean或者要獲取的Bean不帶有&符號,直接返回beanInstance
    if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
        return beanInstance;
    }

    Object object = null;
    if (mbd == null) {
        //嘗試從FactoryBean的緩存中獲取
        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#getObject()方法獲取Bean對象
        object = getObjectFromFactoryBean(factory, beanName, !synthetic);
    }
    return object;
}

getObjectFromFactoryBean

 protected Object getObjectFromFactoryBean(FactoryBean<?> factory, String beanName, boolean shouldPostProcess) {
        //判斷單例 以便加鎖、緩存
        if (factory.isSingleton() && containsSingleton(beanName)) {
            synchronized (getSingletonMutex()) {
                Object object = this.factoryBeanObjectCache.get(beanName);
                if (object == null) {
                    //實際調用getObject方法的地方
                    object = doGetObjectFromFactoryBean(factory, beanName);
                    Object alreadyThere = this.factoryBeanObjectCache.get(beanName);
                    if (alreadyThere != null) {
                        object = alreadyThere;
                    }
                    else {
                        if (object != null && shouldPostProcess) {
                            try {
                                object = postProcessObjectFromFactoryBean(object, beanName);
                            }
                            catch (Throwable ex) {
                                throw new BeanCreationException(beanName,
                                        "Post-processing of FactoryBean's singleton object failed", ex);
                            }
                        }
                        this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
                    }
                }
                return (object != NULL_OBJECT ? object : null);
            }
        }
        else {
            Object object = doGetObjectFromFactoryBean(factory, beanName);
            if (object != null && shouldPostProcess) {
                try {
                    object = postProcessObjectFromFactoryBean(object, beanName);
                }
                catch (Throwable ex) {
                    throw new BeanCreationException(beanName, "Post-processing of FactoryBean's object failed", ex);
                }
            }
            return object;
        }
}

應用

Spring的Aop的工廠ProxyFactoryBean就是一個FactoryBean,具體可以參考Sring源碼分析——AOP

總結

除了名字很相似外,其他沒有任何可比性,只要充分了解彼此間的特性,就不會有任何混淆了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章