阿豪說Spring之開篇BeanFactory

阿豪說Spring之開篇BeanFactory
阿豪說Spring之開篇BeanFactory

寫在前面

想來從開始接觸和使用Spring已四年有餘,雖說使用不成問題,但對其內部具體實現實現原理卻只知一二,於是乎痛下決心要好好擼一遍Spring,以便更好地使用Spring的高級功能而且還能知其然知其所以然,吸收它的好思想、設計模式等等,從現在開始每次把get到的相關內容跟各位客官分享,願一起進步,一起走的更遠!除了Spring,後續我們也嘗試着擼Mybatis等框架,以求功力大增。

Spring基石

BeanFactory,毫無疑問,就是生產Bean的工廠。我們都知道Spring框架提倡我們使用POJO,如果我們把每個業務對象都看成是一個JavaBean的話,我們就能很好的理解這個名字的由來了。Spring中生產Bean的過程並沒有想象中的簡單,這個工廠至少還應該具有業務對象的註冊以及對象間依賴關係綁定等功能,這樣看起來纔是一個完整的工廠。

我們都知道蘋果公司將自己生產的或者從別的供應商那裏採購的手機零件輸送到富士康工廠,那就可以在富士康生產線的最後一個節點獲取成品的蘋果手機。如果我們可以把BeanFactory看作是富士康廠,那手機配件就是各個業務對象。也就是說我們可以直接從BeanFactory中獲取已經組裝好的所需對象,而不需要關心該對象到底是如何被組裝出來的。

對於我們這些使用框架的來說,使用BeanFactory其實很簡單,因爲它已經提供了取得組裝完成的對象的方法,源碼如下:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType, Object... args) throws BeansException;
    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException;
    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}

這些方法大多都是查詢業務對象的,如查找某個對象是否存在的方法(containsBean),獲取某個對象的方法(getBean),當然由於需要存在諸多的重載方法。

BeanFactory提供的便利

在BeanFactory沒有出現之前,我們如果需要某個類的對象毫無疑問是直接new一個,出來,那現在只需要將這些工作讓BeanFactory來幹就好了,具體實例如下:

AClass a = new AClass();
BClass b = new BClass();
CClass c = new CClass();
a.setB(b);
a.setC(c);
a.doSomeThing();

有了BeanFactory之後,我們需要畫出一個生產圖紙並告訴它就可以了,如下:

<beans>
    <bean id="a" class="AClass">
        <property name="b" ref="b"/>
        <property name="c" ref="c"/>
  </bean>
  <bean id="b" class="BClass"></bean>
  <bean id="c" class="CClass"></bean>
</beans>

然後我們可以如下調用:

BeanFactory factory = new XmlBeanFactory(new ClassPathResource("上面配置文件位置"));
AClass a = (AClass)factory.getBean("a");
a.doSomeThing();

乍看起來好像改變並不是很大對不對?沒關係看官別急,隨着學習的深入我們會慢慢的能體會到其中的奧祕。

BeanFactory如何維護Bean關係

實際上,BeanFactory並不負責直接維護Bean關係,而是將Bean之間的關係委託給BeanDefinitionRegistry來進行管理。在Spring中,每一個Bean的原信息都會被看做是一個BeanDefinition,也就是Bean定義。那BeanDefinitionRegistry通過管理這些BeanDefinition從而實現對Bean的關係。我們可以把BeanDefinition看做是圖書館裏的一本書,而BeanDefinitionRegistry就是圖書館的書架。從上文源碼中我們得知BeanFactory其實是個接口,那它的功能終究是會由它的實現類來完成,DefaultListableBeanFactory就是這個一個實現類。這幾個概念之間的UML類圖如下:
阿豪說Spring之開篇BeanFactory

在BeanFactory中,每一個交給它管理的對象,在BeanDefinitionRegistry中都會有一個BeanDefinition實例跟關聯對象綁定,BeanDefinition實例負責保存該Bean的原信息,如class類型、構造方法參數等。當我們向BeanFactory索要bean時,它就根據這些原信息生成一個可用的對象給到我們。

透過BeanFactory看Spring

通過上面的內容,我們不難發現,對於Spring來說,在初始化階段要首先完成三件事:收集Bean原信息、註冊Bean原信息、根據原信息生成Bean代理對象,只有這樣才能很好爲我們服務。收集時可以通過XML文件收集、可以通過TXT文件收集、可以通過代碼(包括通過註解和手動調用收集方法)收集。註冊就是將收集到Bean原信息保存到BeanDefinitionRegistry中以便後續使用。

阿豪說Spring之開篇BeanFactory

阿豪說
學到了?請我喝杯咖啡吧~

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