天天看點

Spring5源碼淺析(二)—ListableBeanFactory與HierarchicalBeanFactory

      在上一篇中,我們簡單分析了一下Spring IOC容器中的根基BeanFactory,今天我們來看一下BeanFactory的兩個擴充,ListableBeanFactory與HierarchicalBeanFactory.他們的基本情況如下圖所示:

Spring5源碼淺析(二)—ListableBeanFactory與HierarchicalBeanFactory

       我們首先來看一下HierarchicalBeanFactory,他在BeanFactory的基礎上增加了兩個函數,一個是用來擷取父級BeanFactory的,一個是用來判斷目前BeanFactory裡是否包含指定名字的Bean(忽略其他的BeanFactory).這個接口是一個二級接口,從中我們可以看到Spring在設計時的兩個理念,首先是工廠的分層,其次呢是将設定和擷取分離,無論是容器的擷取和設定還是說容器内的Bean的設定和擷取都是如此.

       我們再來看ListableBeanFactory.這個接口擴充了BeanFactory,然後提供了對Bean的周遊枚舉功能,他一下傳回所有的Bean,不用像之前一樣一個個地查找了。我們現在來看一下他的幾個api.

     首先是第一組函數:

    1.getBeanDefinitionCount,用來傳回工廠中的Bean的數目;

    2.containsBeanDefinition,用來檢索工廠中是否包含某個Bean

    3.getBeanDefinitionNames,用來傳回工廠中所有Bean的名稱

       注意:但是呢,如果實作該接口的具體工廠本身是有層級的,比如同時實作了HierarchicalBeanFactory,那麼這組函數無法使用.另外,如果說你的bean不是使用BeanDefinitions的形式而是使用其他形式定義并注冊到工廠中的話,也會被這組函數給忽略.

       其次是第二組函數:

      1.getBeanNamesForType: 傳回工廠中所有類型與給定類型一緻的Bean的名字,包括了給定類型的子類或實作類

      2.getBeansOfType: 傳回工廠中所有類型與給定類型一直的Bean的執行個體,包括了給定類型的子類和實作類

      注意:這組函數對于FactoryBean而言,他們是根據Bean Definition或者getObjectType的值來進行判斷的.這組接口隻能比對到頂級的Bean,而内嵌的Bean即使與指定類型一緻,也是沒有辦法比對到的.并且因為FactoryBean在建立對象的時候會對對象進行初始化。是以由FactoryBean建立的對象,如果他們本身的類型不比對,他們将使用FactoryBean再次進行比對.與上一組一樣,這組函數也不會考慮層級中的其他工廠,如果真想擷取其他工廠内部的Bean,可以使用BeanFactoryUtils提供的beanNamesForTypeIncludingAncestors方法.getBeanNamesForType比對所有類型的bean,包括單例、原生類型或者FactoryBean.在大多數實作中,getBeanNamesForType(ResolvableType type)的結果與getBeanNamesForType(true,true,true)的結果是一樣的.該組函數不會忽略使用BeanDefinition以及其他方式注冊的單例Bean,并且BeanName在傳回的時候,總是按着順序尋找最靠後的那一個BeanName來進行傳回的.

       getBeanNamesForType(Class<?> type,boolean includeNonSingletons,boolean allowEagerInit).這個函數跟其他幾個重載不太一樣.在使用這個函數的時候,如果FactoryBean在建立對象時設定了”allowEagerInit”,那麼FactoryBean建立的對象将首先按着對象本身的類型進行比對,如果不一緻将作為FactoryBean進行再次比對.如果”allowEagerInit”沒有被設定,則FactoryBean建立的對象将隻被作為FactoryBean類型來進行比對.(補充說明,以上兩段内容同樣适用于getBeansOfType).

       最後一組函數如下:

       getBeanNamesForAnnotation:這個函數是4.0開始引入的,主要用于尋找那些已經應用了注解,并且還沒建立相應執行個體的Bean.對于那些由FactoryBean建立的對象,他們的類型則是在FactoryBean對其初始化的時候決定的.

       getBeansWithAnnotation:這個函數是3.0開始引入的,這個接口與上一個函數是互補的,他主要用于尋找那些也能管用了注解,并且已經建立了相應執行個體的Bean,傳回的是Bean的名稱和他們的執行個體.FactoryBean所建立的對象,處理方式與getBeanNameForAnnotation相同.

       findAnnotationOnBean:這個函數也是3.0開始引入的,主要用于尋找指定類上所具備的某一種特定的注解,如果給定的那個Bean沒有,就會尋找給定bean的父類或者給定Bean所實作的接口上是否有某一種特定的注解.如果有,就傳回.

       其實看到這裡,我們就能夠看到Spring對接口隔離原則的執着。在了解了這兩個基本的接口之後呢,我們緊接着就可以了解這倆接口的預設實作DefaultListableBeanFactory.我們下次來分享.

繼續閱讀