一 API 閱讀
獲取一個(gè) SpringBean 容器的根接口。是客戶端的基礎(chǔ) bean 視圖;還有一些其他的接口比如
ListableBeanFactory
org.springframework.beans.factory.config.ConfigurableBeanFactory
是為一些特殊的目的而編寫的。
這個(gè)接口由那些持有一定量 bean 定義(bean definition) 的對(duì)象實(shí)現(xiàn),這些 bean 由字符串做唯一標(biāo)識(shí)。根據(jù) bean 定義,工廠會(huì)返回一個(gè)獨(dú)立的實(shí)例,或者一個(gè)單獨(dú)的共享實(shí)例(一種相較于單例設(shè)計(jì)模式的更好的選擇,得到一個(gè)在工廠作用域范圍內(nèi)的單例實(shí)例)。返回實(shí)例的類型取決于 bean 工廠的配置:API是相同的。從 Spring2.0 開(kāi)始,更多可選的 bean 作用域都由不同的上下文實(shí)現(xiàn)了(比如 request 和 session 作用域)。
這種設(shè)計(jì)方案的 核心 要點(diǎn)是 BeanFactory 會(huì)成為應(yīng)用程序組件的注冊(cè)中心,由此集中化應(yīng)用程序的組件配置信息。
相比于 beanFactory 查找 bean 配置信息的方式,依靠依賴注入,使用 setter 和 constructor 來(lái)配置應(yīng)用的對(duì)象是更好的方案。Spring的依賴注入功能正是通過(guò)實(shí)現(xiàn)BeanFactory和其子接口實(shí)現(xiàn)的。
正常情況下 beanFactory 會(huì)加載保存于一些配置源的 bean 配置信息(這些配置源可以是 XML/properties配置文件等等),并使用 ==org.springframework.beans== 包下的工具來(lái)配置這些 bean。不過(guò) beanFactory 的實(shí)現(xiàn)類可以簡(jiǎn)單的通過(guò) Java 代碼直接創(chuàng)建 bean 實(shí)例并返回。這里也沒(méi)有限制 bean 定義信息的保存載體:LDAP/RDBMS/XML 或者 properties 文件等等。beanFactory 的實(shí)現(xiàn)類更鼓勵(lì)支持引用而不是依賴注入的bean(?)。
beanFactory 的實(shí)現(xiàn)類應(yīng)該盡可能地支持 bean 的生命周期接口。完整的初始化方法和它們的初始化順序是:
- BeanNameAware's {@code setBeanName}
- BeanClassLoaderAware's {@code setBeanClassLoader}
- BeanFactoryAware's {@code setBeanFactory}
- EnvironmentAware's {@code setEnvironment}
- EmbeddedValueResolverAware's {@code setEmbeddedValueResolver}
- ResourceLoaderAware's {@code setResourceLoader}(only applicable when running in an application context)
- ApplicationEventPublisherAware's {@code setApplicationEventPublisher} (only applicable when running in an application context)
- MessageSourceAware's {@code setMessageSource}(only applicable when running in an application context)
- ApplicationContextAware's {@code setApplicationContext} (only applicable when running in an application context)
- ServletContextAware's {@code setServletContext} (only applicable when running in a web application context)
- {@code postProcessBeforeInitialization} methods of BeanPostProcessors
- InitializingBean's {@code afterPropertiesSet}
- a custom init-method definition<li>
- {@code postProcessAfterInitialization} methods of BeanPostProcessors
二 類成員與接口定義的方法
String FACTORY_BEAN_PREFIX = "&";
用于 間接引用 一個(gè) FactoryBean,以及區(qū)分 FactoryBean 和 FactoryBean 創(chuàng)建的實(shí)例。比如,myJndiObject 是一個(gè) factoryBean,那么使用 name = "&myJndiObject",得到的是 factory,而不是 factory 中保存的 bean 實(shí)例。
Object getBean(String name) throws BeansException;
工廠接口中的基礎(chǔ)核心方法定義,當(dāng)容器已經(jīng)啟動(dòng)完成,我們需要使用這個(gè)方法的實(shí)現(xiàn),來(lái)獲取對(duì)應(yīng)的 bean 實(shí)例。獲取到的 bean,具體是單例還是其他類型的,取決于提前定義好的 bean 信息(即 beanDefination)。
<T> T getBean(String name, Class<T> requiredType) throws BeansException;
這個(gè)方法和前一個(gè)方法很類似,區(qū)別在于參數(shù)列表上多了一個(gè) class 類型信息。相較于前面的一個(gè)方法,該方法對(duì)要獲取的 bean 實(shí)例的限制信息更加明確,這樣可以 避免類型轉(zhuǎn)換異常。
<T> T getBean(Class<T> requiredType) throws BeansException;
依據(jù)傳入的類型參數(shù)信息來(lái)獲取 bean 的實(shí)例。這個(gè)方法沒(méi)有要求傳入 bean 的名稱。實(shí)際上其實(shí)是一個(gè)很模糊的范圍檢索的 bean 獲取方式。
Object getBean(String name, Object... args) throws BeansException;
獲取指定 beanName 的 bean 實(shí)例,添加了一個(gè)可變參數(shù)列表,這個(gè)可變參數(shù)列表用于傳入創(chuàng)建對(duì)應(yīng) bean 所需的 構(gòu)造方法或者工廠方法 的參數(shù)。這個(gè)方法的應(yīng)用,我們可以聯(lián)想到在 xml 里面配置 bean 信息的時(shí)候,要求指定這個(gè) bean 初始化是使用工廠方法還是構(gòu)造函數(shù)的時(shí)候。
如上是 getBean 一系列的重載方法。
boolean containsBean(String name);
用戶檢索當(dāng)前 beanFactory 是否包含指定的 bean。這個(gè)包含的含義,可以是 bean definition,也可以是執(zhí)行 beanName 的單例實(shí)例。如果傳入的 name 是別名,那將會(huì)被轉(zhuǎn)換為標(biāo)準(zhǔn)的 bean 名稱。
部分繼承結(jié)構(gòu)的 beanFactory ,在調(diào)用這個(gè)方法的時(shí)候也會(huì)查詢父類容器中是否包含了指定 beanName 的對(duì)象實(shí)例。
注意只要在 factory 中發(fā)現(xiàn)了對(duì)應(yīng)的 bean definition 或者單例的實(shí)例。不管這個(gè) bean 是否已經(jīng)被實(shí)例化,抑或是處于為被加載的 延遲加載 狀態(tài),都會(huì)返回 true。
因此我們要注意到,不是說(shuō) containsBean 方法返回了 true,使用 getBean 方法就一定會(huì)拿到對(duì)應(yīng)的 bean 實(shí)例。
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
該方法用于判斷指定的 bean 是否是 單例。當(dāng)判斷的方法返回了 true。當(dāng)然可以說(shuō)明這個(gè) bean 是一個(gè)單例 bean。但是當(dāng)方法的返回值是 false 的時(shí)候,并不意味著這個(gè) bean 是一個(gè) prototype 類型的 bean(應(yīng)用:原型設(shè)計(jì)模式)。如果要判斷 bean 的作用域是否是 prototype,可以使用另一個(gè)方法 isPrototype。
boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
該方法用于判斷指定的 bean 是否是 原型設(shè)計(jì)模式下的實(shí)例(prototype)。與前一個(gè)方法類似,返回 true 表示這個(gè) bean 的作用域一定是 prototype,但是返回 false 并不意味著這個(gè) bean 是一個(gè)單例實(shí)例。
boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
用于對(duì)想要獲取的 bean 的類型檢查。
Class<?> getType(String name) throws NoSuchBeanDefinitionException;
獲取指定 bean 的類型信息。
String[] getAliases(String name);
獲取指定 bean 的別名數(shù)組。
三 ListableBeanFactory
3.1 API 文檔簡(jiǎn)述
一個(gè)實(shí)現(xiàn)了 BeanFactory 的擴(kuò)展接口,用戶枚舉工廠中的所有 bean 實(shí)例,而不是通過(guò)客戶端請(qǐng)求,用名字挨個(gè)獲取。 需要預(yù)先加載 beanFactory 中所有的 beanDefinition 的工廠類會(huì)考慮實(shí)現(xiàn)這個(gè)擴(kuò)展接口。
如果實(shí)現(xiàn)了該接口的類還實(shí)現(xiàn)了 HierarchicalBeanFactory,那么方法的返回值將不會(huì)考慮父容器中定義的 bean,而僅關(guān)注于當(dāng)前的 beanFactory 中的 bean。如果有必要,可以使用 BeanFactoryUtils 中的方法來(lái)獲取父類容器中的 bean。
這個(gè)接口中的方法也僅僅考慮當(dāng)前 beanFactory 中的 beanDefinition。類似于 ConfigurableBeanFactory.registerSingleton 這種注冊(cè)單例 bean 的方法會(huì)在當(dāng)前接口方法中被忽略。例外的是 getBeanNamesOfType 和 getBeansOfType 這樣的方法會(huì)考慮注冊(cè)的單例。
當(dāng)前接口中的部分方法不是為了快速響應(yīng)而設(shè)計(jì)。 getBeanDefinitionCount 和 containsBeanDefinition 性能比較低下。少用為好。
3.2 方法描述
boolean containsBeanDefinition(String beanName);
檢查當(dāng)前容器是否包含執(zhí)行 beanName 的 beanDefinition 信息。不會(huì)檢索父容器的內(nèi)容,同時(shí)還會(huì)忽略任何使用非 definition 方式注冊(cè)的單例 bean。
int getBeanDefinitionCount();
返回當(dāng)前 bean 容器定義的 bean 數(shù)量。不會(huì)記入父容器中的 bean 數(shù)量。忽略使用非 bean definition 方式注冊(cè)的 bean。
String[] getBeanDefinitionNames();
返回當(dāng)前容器中定義的所有的 bean 的 beanName,得到一個(gè)字符串?dāng)?shù)組。不會(huì)記入父容器中的 bean 數(shù)量。忽略使用非 bean definition 方式注冊(cè)的 bean。
String[] getBeanNamesForType(ResolvableType type);
根據(jù) bean 的類型信息來(lái)獲取指定類型信息的 beanName 數(shù)組。判斷的依據(jù)是:容器中是否存在對(duì)應(yīng)的 beanDefinition 或者 getObjectType方法返回有效的實(shí)例信息。
String[] getBeanNamesForType(Class<?> type);
系列方法的重載。入?yún)㈩愋筒煌?,前者?Spring 自定義的一種類型輔助類。
String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit);
多出了兩個(gè)參數(shù),對(duì)對(duì)應(yīng) beanName 的獲取有更加明確的限定條件。
- boolean includeNonSingletons 是否限定僅獲取單例類型 bean 的 beanName
- boolean allowEagerInit 是否將“延遲加載”的 bean 實(shí)例化。
<T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
根據(jù) class 對(duì)象類型來(lái)獲取 bean 的實(shí)例集合。結(jié)果都保存在一個(gè) map 中。這個(gè)指定的類型,可以是類本身類型也可以是其子類對(duì)象類型。不會(huì)忽略以非 beanDefinitions 方式初始化的單例 bean。也不會(huì)檢索父容器中的 bean。
<T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException;
上一個(gè)方法的重載,新的入?yún)⒑x和前面的方法類似。
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
然后是一系列根據(jù) bean 代碼中添加的注解類型來(lái)獲取 beanName/bean集合 的方法。
String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType);
Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType) throws BeansException;
...
四 HierarchicalBeanFactory
4.1 API
beanFactory 的擴(kuò)展子接口,可以作為容器層級(jí)中的一部分。
與這個(gè)層級(jí)擴(kuò)展接口相比,還有對(duì)應(yīng)的 setParentBeanFactory 方法,這個(gè)方法需要另一個(gè)同級(jí)的擴(kuò)展接口 ConfigurableBeanFactory。
接口中定義的方法也很少,只有兩個(gè)
BeanFactory getParentBeanFactory();
返回當(dāng)前容器的父容器
boolean containsLocalBean(String name);
判斷當(dāng)前容器是否包含指定了 beanName 的bean,不會(huì)檢索父容器中的 bean。這個(gè)方法可以和 containsBean 方法結(jié)合對(duì)比:
基類接口中的 containsBean 方法,是否檢索父類容器的 bean 也要視情況而定。文檔中清晰的說(shuō)明了:如果是處于一個(gè)包含層級(jí)容器結(jié)構(gòu)的 beanFactory 中,那么這個(gè)方法是會(huì)去檢索父類容器的。但是 containsLocalBean 就是明確指出了不會(huì)檢索父容器。
五 AutowireCapableBeanFactory
beanFactory 的擴(kuò)展接口。這個(gè)擴(kuò)展接口主要定義了關(guān)于 bean 的自動(dòng)裝配部分的內(nèi)容。
這個(gè)擴(kuò)展接口也不是用戶常規(guī)的應(yīng)用代碼,常常與 BeanFactory 或者 ListableBeanFactory 搭配使用。
其他框架可以集成這個(gè)接口代碼以操控 Spring 中已經(jīng)存在的且無(wú)法控制其生命周期的 bean 實(shí)例。
這個(gè)接口也沒(méi)有被 ApplicationContext 實(shí)現(xiàn),雖然這個(gè)接口也曾用于上下文的代碼。獲取方法見(jiàn) ApplicationContext.getAutowireCapableBeanFactory()。
5.1 類成員
int AUTOWIRE_NO = 0;
用于指示沒(méi)有外部定義的自動(dòng)裝配信息的常量。諸如 BeanFactoryAware 等注解驅(qū)動(dòng)的注入依然是有效的。
int AUTOWIRE_BY_NAME = 1;
用于指明根據(jù) name 自動(dòng)裝配 bean 屬性的常量。
int AUTOWIRE_BY_TYPE = 2;
用于指明根據(jù)類型 自動(dòng)裝配 bean 屬性的常量。
int AUTOWIRE_CONSTRUCTOR = 3;
用于指明根據(jù)合適的構(gòu)造函數(shù) 自動(dòng)裝配 bean 屬性的常量。
5.2 方法定義
<T> T createBean(Class<T> beanClass) throws BeansException;
創(chuàng)建給定類的全新的實(shí)例。會(huì)執(zhí)行完整的 bean 實(shí)例化邏輯。包含可用的 bean 預(yù)處理方法,比如 BeanPostProcessor。
該方法不是傳統(tǒng)的 按名字 或者 按類型 的自動(dòng)裝配,如果要達(dá)到這一目的,可以使用另一個(gè)方法 createBean(Class, int, boolean)
void autowireBean(Object existingBean) throws BeansException;
該方法名就可以簡(jiǎn)要了解到方法的用途:自動(dòng)裝配 bean。在一些 bean 的初始化工作完成后,這些 bean 中的一部分采用了組裝的技巧耦合的其他的 bean。這個(gè)時(shí)候我們需要把這些由 spring 托管的 bean 的實(shí)例裝配到對(duì)應(yīng)的地方。
這個(gè)自動(dòng)裝配方法在 bean 的實(shí)例化過(guò)程中的, after-instantiation 以及 屬性初始化中的 post=processing 的階段執(zhí)行。注解驅(qū)動(dòng)的 bean 注入就是依賴了這個(gè)方法定義。
這個(gè)方法本質(zhì)上就是裝配注解的類成員和方法,或者說(shuō)是反序列化 bean 實(shí)例。和前一個(gè)方法一樣,該方法也不是傳統(tǒng)的 按名字 或者 按類型 裝配。
Object configureBean(Object existingBean, String beanName) throws BeansException;
配置一個(gè)(接近完成的) bean:裝配 bean 的域,初始化域的值和相關(guān)的回調(diào)函數(shù)(比如 set/get 和 xml 中配置的工廠方法)。
該方法是 initializeBean 的方法超集。會(huì)完整執(zhí)行對(duì)應(yīng)的 beanDefinition 實(shí)例中配置的信息。需要注意的是該方法需要對(duì)應(yīng) beanDefinition 的名字。
有關(guān) bean 生命周期控制的詳細(xì)方法列表
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;
...
這些系列方法,基本上都是 bean 的初始化,bean 的自動(dòng)裝配,bean 的屬性值獲取等等,很多初始化策略都已經(jīng)在接口中以常量的方式定義了。比如 是按類型裝配還是按名字裝配。
除了的 bean 的初始化,還有幾個(gè)關(guān)于 bean 創(chuàng)建完成后的處理方法(postProcessing)已經(jīng)銷毀已經(jīng)創(chuàng)建的 bean 的方法(destroy bean)。
=====
<T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException;
解析出符合類型要求的 bean。
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) throws BeansException;
解析出指定 beanName 的依賴 bean。
Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
同上,差異在入?yún)ⅰ?/p>
六 簡(jiǎn)要總結(jié)
BeanFactory 接口是 Spring 中有關(guān) bean 管理的頂級(jí)接口,然后其下的三個(gè)擴(kuò)展接口又對(duì)這個(gè)頂層接口做了不同程度的擴(kuò)展。各個(gè)擴(kuò)展接口的目的和方向也各不相同。
ListableBeanFactory 可以通過(guò)遍歷獲取 factory 中的所有 bean 實(shí)例。也包含了一些有關(guān) bean 數(shù)量統(tǒng)計(jì)的方法。
HierarchicalBeanFactory 是一個(gè)層級(jí)擴(kuò)展接口,有關(guān)父子容器關(guān)系的定義內(nèi)容。方法很少,就一個(gè) 獲取父容器 和 判斷是否包含父容器。 當(dāng)我們需要使用有層級(jí)關(guān)系的 beanFactory 時(shí),需要實(shí)現(xiàn)這個(gè)接口。
AutowireCapableBeanFactory 是處理有關(guān) bean 容器中的 bean 自動(dòng)裝配操作的擴(kuò)展接口。接口中定義了一些列的方法,用于 解析和裝配有依賴關(guān)系的 bean 和 控制 bean 的完整的生命周期 。