1. 程式人生 > >Spring原始碼分析——BeanFactory體系之介面詳細分析

Spring原始碼分析——BeanFactory體系之介面詳細分析

Spring原始碼分析——BeanFactory體系之介面詳細分析

  Spring的BeanFactory的繼承體系堪稱經典。這是眾所周知的!作為Java程式設計師,不能錯過!

  前面的博文分析了Spring的Resource資源類Resouce。今天開始分析Spring的IOC部分。眾所周知,IOC是Spring框架最迷人的地方。它最重要的介面,就是BeanFactory了。BeanFactory有著龐大的繼承、實現體系,有眾多的子介面、實現類。本博文的目標就是抽絲剝繭,從原始碼入手,分析Spring的實現和架構,從中進步。

  在閱讀的過程中,可以參照Spring文件來一起學習:

Spring3.1.1文件

  本人英文水平有限,部分翻譯可能不恰當,歡迎指出!

 

一、BeanFactory的基本類體系結構(介面為主)

  這是我畫的BeanFactory基本的類體系結構,這裡沒有包括強大的ApplicationContext體系,ApplicationContext我準備放到下一篇再分析。

具體:

  1、BeanFactory作為一個主介面不繼承任何介面,暫且稱為一級介面

  2、有3個子介面繼承了它,進行功能上的增強。這3個子介面稱為二級介面

  3、ConfigurableBeanFactory可以被稱為三級介面

,對二級介面HierarchicalBeanFactory進行了再次增強,它還繼承了另一個外來的介面SingletonBeanRegistry

  4、ConfigurableListableBeanFactory是一個更強大的介面,繼承了上述的所有介面,無所不包,稱為四級介面

  (這4級介面是BeanFactory的基本介面體系。繼續,下面是繼承關係的2個抽象類和2個實現類:)

  5、AbstractBeanFactory作為一個抽象類,實現了三級介面ConfigurableBeanFactory大部分功能。

  6、AbstractAutowireCapableBeanFactory同樣是抽象類,繼承自AbstractBeanFactory,並額外實現了二級介面AutowireCapableBeanFactory

  7、DefaultListableBeanFactory繼承自AbstractAutowireCapableBeanFactory,實現了最強大的四級介面ConfigurableListableBeanFactory,並實現了一個外來介面BeanDefinitionRegistry,它並非抽象類。

  8、最後是最強大的XmlBeanFactory,繼承自DefaultListableBeanFactory,重寫了一些功能,使自己更強大。

總結:

  BeanFactory的類體系結構看似繁雜混亂,實際上由上而下井井有條,非常容易理解。

 

二、IOC的始祖——BeanFactory

  來看一下BeanFactory的原始碼,這麼牛逼哄哄的介面就不折疊了吧:

複製程式碼

package org.springframework.beans.factory;

public interface BeanFactory {

    /**
     * 用來引用一個例項,或把它和工廠產生的Bean區分開,就是說,如果一個FactoryBean的名字為a,那麼,&a會得到那個Factory
     */
    String FACTORY_BEAN_PREFIX = "&";

    /*
     * 四個不同形式的getBean方法,獲取例項
     */
    Object getBean(String name) throws BeansException;

    <T> T getBean(String name, Class<T> requiredType) throws BeansException;

    <T> T getBean(Class<T> requiredType) throws BeansException;

    Object getBean(String name, Object... args) throws BeansException;

    boolean containsBean(String name); // 是否存在

    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;// 是否為單例項

    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;// 是否為原型(多例項)

    boolean isTypeMatch(String name, Class<?> targetType)
            throws NoSuchBeanDefinitionException;// 名稱、型別是否匹配

    Class<?> getType(String name) throws NoSuchBeanDefinitionException; // 獲取型別

    String[] getAliases(String name);// 根據例項的名字獲取例項的別名

}

複製程式碼

 具體:

  1、4個獲取例項的方法。getBean的過載方法。

  2、4個判斷的方法。判斷是否存在,是否為單例、原型,名稱型別是否匹配。

  3、1個獲取型別的方法、一個獲取別名的方法。根據名稱獲取型別、根據名稱獲取別名。一目瞭然!

總結:

  這10個方法,很明顯,這是一個典型的工廠模式的工廠介面。

 

三、可將Bean逐一列出的工廠——ListableBeanFactory

原始碼:

複製程式碼

public interface ListableBeanFactory extends BeanFactory {

    boolean containsBeanDefinition(String beanName); // 對於給定的名字是否含有BeanDefinition

    int getBeanDefinitionCount(); // 返回工廠的BeanDefinition總數

    String[] getBeanDefinitionNames(); // 返回工廠中所有Bean的名字

    String[] getBeanNamesForType(Class<?> type); // 返回對於指定型別Bean(包括子類)的所有名字

    /*
     * 返回指定型別的名字 includeNonSingletons為false表示只取單例Bean,true則不是
     * allowEagerInit為true表示立刻載入,false表示延遲載入。 注意:FactoryBeans都是立刻載入的。
     */
    String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons,
            boolean allowEagerInit);

    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException; // 根據型別(包括子類)返回指定Bean名和Bean的Map

    <T> Map<String, T> getBeansOfType(Class<T> type,
            boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;

    Map<String, Object> getBeansWithAnnotation(
            Class<? extends Annotation> annotationType) throws BeansException; // 根據註解型別,查詢所有有這個註解的Bean名和Bean的Map

    <A extends Annotation> A findAnnotationOnBean(String beanName,
            Class<A> annotationType);// 根據指定Bean名和註解型別查詢指定的Bean

}

複製程式碼

 

具體:

  1、3個跟BeanDefinition有關的總體操作。包括BeanDefinition的總數、名字的集合、指定型別的名字的集合。

  (這裡指出,BeanDefinition是Spring中非常重要的一個類,每個BeanDefinition例項都包含一個類在Spring工廠中所有屬性。)

  2、2個getBeanNamesForType過載方法。根據指定型別(包括子類)獲取其對應的所有Bean名字。

  3、2個getBeansOfType過載方法。根據型別(包括子類)返回指定Bean名和Bean的Map。

  4、2個跟註解查詢有關的方法。根據註解型別,查詢Bean名和Bean的Map。以及根據指定Bean名和註解型別查詢指定的Bean。

總結:

  正如這個工廠介面的名字所示,這個工廠介面最大的特點就是可以列出工廠可以生產的所有例項。當然,工廠並沒有直接提供返回所有例項的方法,也沒這個必要。它可以返回指定型別的所有的例項。而且你可以通過getBeanDefinitionNames()得到工廠所有bean的名字,然後根據這些名字得到所有的Bean。這個工廠介面擴充套件了BeanFactory的功能,作為上文指出的BeanFactory二級介面,有9個獨有的方法,擴充套件了跟BeanDefinition的功能,提供了BeanDefinition、BeanName、註解有關的各種操作。它可以根據條件返回Bean的集合,這就是它名字的由來——ListableBeanFactory。

 

四、分層的Bean工廠——HierarchicalBeanFactory

原始碼:

複製程式碼

public interface HierarchicalBeanFactory extends BeanFactory {

    BeanFactory getParentBeanFactory();    //  返回本Bean工廠的父工廠

    boolean containsLocalBean(String name);    //  本地工廠是否包含這個Bean

}

複製程式碼

 具體:

  1、第一個方法返回本Bean工廠的父工廠。這個方法實現了工廠的分層。

  2、第二個方法判斷本地工廠是否包含這個Bean(忽略其他所有父工廠)。這也是分層思想的體現。

總結:這個工廠介面非常簡單,實現了Bean工廠的分層。這個工廠介面也是繼承自BeanFacotory,也是一個二級介面,相對於父介面,它只擴充套件了一個重要的功能——工廠分層。

 

五、自動裝配的Bean工廠——AutowireCapableBeanFactory

原始碼:

複製程式碼

public interface AutowireCapableBeanFactory extends BeanFactory {

    int AUTOWIRE_NO = 0;   //  這個常量表明工廠沒有自動裝配的Bean

    int AUTOWIRE_BY_NAME = 1;  //表明根據名稱自動裝配

    int AUTOWIRE_BY_TYPE = 2;  //表明根據型別自動裝配

    int AUTOWIRE_CONSTRUCTOR = 3;  //表明根據構造方法快速裝配

    @Deprecated
    int AUTOWIRE_AUTODETECT = 4;   //表明通過Bean的class的內部來自動裝配(有沒翻譯錯...)Spring3.0被棄用。

    <T> T createBean(Class<T> beanClass) throws BeansException;    //  根據指定Class建立一個全新的Bean例項

    void autowireBean(Object existingBean) throws BeansException;  //  給定物件,根據註釋、後處理器等,進行自動裝配

    /*
     * 根據Bean名的BeanDefinition裝配這個未加工的Object,執行回撥和各種後處理器。
     */
    Object configureBean(Object existingBean, String beanName) throws BeansException;

    /*
     * 分解Bean在工廠中定義的這個指定的依賴descriptor
     */
    Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;

    /*
     * 根據給定的型別和指定的裝配策略,建立一個新的Bean例項
     */
    Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    /*
     * 與上面類似,不過稍有不同。
     */
    Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    /*
     * 根據名稱或型別自動裝配
     */
    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
            throws BeansException;

    /*
     * 也是自動裝配
     */
    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;

    /*
     * 初始化一個Bean...
     */
    Object initializeBean(Object existingBean, String beanName) throws BeansException;

    /*
     * 初始化之前執行BeanPostProcessors
     */
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException;
    /*
     * 初始化之後執行BeanPostProcessors
     */
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException;

    /*
     * 分解指定的依賴
     */
    Object resolveDependency(DependencyDescriptor descriptor, String beanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;

}

複製程式碼

 具體:

  1、總共5個靜態不可變常量來指明裝配策略,其中一個常量被Spring3.0廢棄、一個常量表示沒有自動裝配,另外3個常量指明不同的裝配策略——根據名稱、根據型別、根據構造方法。

  2、8個跟自動裝配有關的方法,實在是繁雜,具體的意義我們研究類的時候再分辨吧。

  3、2個執行BeanPostProcessors的方法。

  4、2個分解指定依賴的方法

總結:這個工廠介面繼承自BeanFacotory,它擴充套件了自動裝配的功能,根據類定義BeanDefinition裝配Bean、執行前、後處理器等。

 

六、複雜的配置Bean工廠——ConfigurableBeanFactory

原始碼:

複製程式碼

public interface ConfigurableBeanFactory extends HierarchicalBeanFactory, SingletonBeanRegistry {

    String SCOPE_SINGLETON = "singleton";  //  單例

    String SCOPE_PROTOTYPE = "prototype";  //  原型

    /*
     * 搭配HierarchicalBeanFactory介面的getParentBeanFactory方法
     */
    void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

    /*
     * 設定、返回工廠的類載入器
     */
    void setBeanClassLoader(ClassLoader beanClassLoader);

    ClassLoader getBeanClassLoader();

    /*
     * 設定、返回一個臨時的類載入器
     */
    void setTempClassLoader(ClassLoader tempClassLoader);

    ClassLoader getTempClassLoader();

    /*
     * 設定、是否快取元資料,如果false,那麼每次請求例項,都會從類載入器重新載入(熱載入)

     */
    void setCacheBeanMetadata(boolean cacheBeanMetadata);
    
    boolean isCacheBeanMetadata();//是否快取元資料

    /*
     * Bean表示式分解器
     */
    void setBeanExpressionResolver(BeanExpressionResolver resolver);
    
    BeanExpressionResolver getBeanExpressionResolver();

    /*
     * 設定、返回一個轉換服務
     */
    void setConversionService(ConversionService conversionService);

    ConversionService getConversionService();

    /*
     * 設定屬性編輯登記員...
     */
    void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

    /*
     * 註冊常用屬性編輯器
     */
    void registerCustomEditor(Class<?> requiredType, Class<? extends PropertyEditor> propertyEditorClass);

    /*
     * 用工廠中註冊的通用的編輯器初始化指定的屬性編輯註冊器
     */
    void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

    /*
     * 設定、得到一個型別轉換器
     */
    void setTypeConverter(TypeConverter typeConverter);

    TypeConverter getTypeConverter();

    /*
     * 增加一個嵌入式的StringValueResolver
     */
    void addEmbeddedValueResolver(StringValueResolver valueResolver);

    String resolveEmbeddedValue(String value);//分解指定的嵌入式的值

    void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);//設定一個Bean後處理器

    int getBeanPostProcessorCount();//返回Bean後處理器的數量

    void registerScope(String scopeName, Scope scope);//註冊範圍

    String[] getRegisteredScopeNames();//返回註冊的範圍名

    Scope getRegisteredScope(String scopeName);//返回指定的範圍

    AccessControlContext getAccessControlContext();//返回本工廠的一個安全訪問上下文

    void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);//從其他的工廠複製相關的所有配置

    /*
     * 給指定的Bean註冊別名
     */
    void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;

    void resolveAliases(StringValueResolver valueResolver);//根據指定的StringValueResolver移除所有的別名

    /*
     * 返回指定Bean合併後的Bean定義
     */
    BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;//判斷指定Bean是否為一個工廠Bean

    void setCurrentlyInCreation(String beanName, boolean inCreation);//設定一個Bean是否正在建立

    boolean isCurrentlyInCreation(String beanName);//返回指定Bean是否已經成功建立

    void registerDependentBean(String beanName, String dependentBeanName);//註冊一個依賴於指定bean的Bean

    String[] getDependentBeans(String beanName);//返回依賴於指定Bean的所欲Bean名

    String[] getDependenciesForBean(String beanName);//返回指定Bean依賴的所有Bean名

    void destroyBean(String beanName, Object beanInstance);//銷燬指定的Bean

    void destroyScopedBean(String beanName);//銷燬指定的範圍Bean

    void destroySingletons();  //銷燬所有的單例類

}

複製程式碼

在具體介紹之前,先看一下介面SingletonBeanRegistry的原始碼:

複製程式碼

public interface SingletonBeanRegistry {

    void registerSingleton(String beanName, Object singletonObject); //在容器內註冊一個單例類  
    
    Object getSingleton(String beanName);//返回給定名稱對應的單例類

    boolean containsSingleton(String beanName);//給定名稱是否對應單例類

    String[] getSingletonNames();//返回容器內所有單例類的名字

    int getSingletonCount();//返回容器內註冊的單例類數量

}

複製程式碼

 可以看到,SingletonBeanRegistry這個介面非常簡單,5個方法,實現了單例類註冊的功能。

ConfigurableBeanFactory同時繼承了HierarchicalBeanFactory 和 SingletonBeanRegistry 這兩個介面,即同時繼承了分層和單例類註冊的功能。

具體:

  1、2個靜態不可變常量分別代表單例類和原型類。

  2、1個設定父工廠的方法,跟HierarchicalBeanFactory介面的getParentBeanFactory方法互補。

  3、4個跟類載入器有關的方法:get/set工廠類載入器和get/set臨時類載入器。

  4、2個設定、是否快取元資料的方法(熱載入開關)。

  5、11個處理Bean註冊、載入等細節的方法,包括:Bean表示式分解器、轉換服務、屬性編輯登記員、屬性編輯器、屬性編輯註冊器、型別轉換器、嵌入式的字串分解器

  6、2個處理Bean後處理器的方法。

  7、3個跟註冊範圍相關的方法。

  8、1個返回安全訪問上下文的方法、1個從其他的工廠複製相關的所有配置的方法。

  9、2個跟Bean別名相關的方法、1個返回合併後的Bean定義的方法。

  10、1個判斷是否為工廠Bean的方法、2個跟當前Bean建立時機相關的方法。

  11、3個跟Bean依賴相關的方法、3個銷燬Bean相關的方法。

總結:這個巨大的工廠介面,繼承自HierarchicalBeanFactory 和 SingletonBeanRegistry 這兩個介面,並額外獨有37個方法!!!(看的我都快瘋了...)這37個方法包含了工廠建立、註冊一個Bean的眾多細節。這個工廠名為ConfigurableBeanFactory,真是名不虛傳!統計一下此時的ConfigurableBeanFactory的方法數吧。自有的37個方法、HierarchicalBeanFactory的2個方法、SingletonBeanRegistry的5個方法、爺爺介面BeanFactory的10個方法,共有54個方法!雖然方法繁多,還算井井有條!

 

7、BeanFactory的集大成者——ConfigurableListableBeanFactory

原始碼:  

複製程式碼

public interface ConfigurableListableBeanFactory
        extends ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory {

    void ignoreDependencyType(Class<?> type);//忽略自動裝配的依賴型別

    void ignoreDependencyInterface(Class<?> ifc);//忽略自動裝配的介面

    /*
     * 註冊一個可分解的依賴
     */
    void registerResolvableDependency(Class<?> dependencyType, Object autowiredValue);

    /*
     * 判斷指定的Bean是否有資格作為自動裝配的候選者
     */
    boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
            throws NoSuchBeanDefinitionException;

    /*
     * 返回註冊的Bean定義
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    void freezeConfiguration();//暫時凍結所有的Bean配置

    boolean isConfigurationFrozen();//判斷本工廠配置是否被凍結

    void preInstantiateSingletons() throws BeansException;//使所有的非延遲載入的單例類都例項化。

}

複製程式碼

 具體:

  1、2個忽略自動裝配的的方法。

  2、1個註冊一個可分解依賴的方法。

  3、1個判斷指定的Bean是否有資格作為自動裝配的候選者的方法。

  4、1個根據指定bean名,返回註冊的Bean定義的方法。

  5、2個凍結所有的Bean配置相關的方法。

  6、1個使所有的非延遲載入的單例類都例項化的方法。

總結:工廠介面ConfigurableListableBeanFactory同時繼承了3個介面,ListableBeanFactory、AutowireCapableBeanFactory 和 ConfigurableBeanFactory,擴充套件之後,加上自有的這8個方法,這個工廠介面總共有83個方法,實在是巨大到不行了。這個工廠介面的自有方法總體上只是對父類介面功能的補充,包含了BeanFactory體系目前的所有方法,可以說是介面的集大成者。

 

8、額外的介面——BeanDefinitionRegistry

這個介面基本用來操作定義在工廠內部的BeanDefinition的。我們先來看一下這個介面的父介面:

複製程式碼

public interface AliasRegistry {

    void registerAlias(String name, String alias);//對指定的名稱註冊別名

    void removeAlias(String alias);//從當前容器移除指定別名

    boolean isAlias(String beanName);//判斷指定名稱是否為別名

    String[] getAliases(String name);//返回指定名稱的所有別名

}

複製程式碼

 可以看到這4個方法都非常簡單,都是用來操作別名的。

再來看一下BeanDefinitionRegistry的原始碼:

複製程式碼

public interface BeanDefinitionRegistry extends AliasRegistry {

    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;//給定bean名稱,註冊一個新的bean定義

    /*
     * 根據指定Bean名移除對應的Bean定義
     */
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /*
     * 根據指定bean名得到對應的Bean定義
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /*
     * 查詢,指定的Bean名是否包含Bean定義
     */
    boolean containsBeanDefinition(String beanName);

    String[] getBeanDefinitionNames();//返回本容器內所有註冊的Bean定義名稱

    int getBeanDefinitionCount();//返回本容器內註冊的Bean定義數目

    boolean isBeanNameInUse(String beanName);//指定Bean名是否被註冊過。

}

複製程式碼

 這7個方法都是用來操作容器內的BeanDefinition的。

 下一結就會介紹BeanFactory體系的終極實現類——XmlBeanFactory

 

/**
*   ————————如果覺得本博文還行,別忘了推薦一下哦,謝謝!
*   作者:錢書康
*   歡迎轉載,請保留此段宣告。
*   出處:http://www.cnblogs.com/zrtqsk/ 
*/