IOC(一)BeanFactory和BeanDefinition

前言

從這篇文章開始我會去探索一下Spring中IOC機制的一些底層實現,至於IOC(控制反轉)是什麼在這裏很少作介紹,網上的資料也不少。

IOC(控制反轉)是Spring框架中最核心的機制,因此咱們須要對其實現原理有必定的理解,才能更好的使用它甚至本身設計一個相似Spring的簡單框架。這篇文章咱們先無論其運行流程,而是先來看一下他的兩個重要的接口,只有先把這些接口弄明白了,咱們才能理解IOC機制的工做流程及原理。java

BeanFactory

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;

public interface BeanFactory {

    String FACTORY_BEAN_PREFIX = "&";
    
    Object getBean(String name) throws BeansException;

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

     T getBean(Class 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);
}複製代碼
這個即是spring核心的Bean工廠定義,上面的author說是2001年寫的,已經歷史久遠了, 這個類是spring中全部bean工廠,也就是俗稱的IOC容器的祖宗,各類IOC容器都只是它的實現或者爲了知足特別需求的擴展實現。 從上面的方法就能夠看出,這些工廠的實現最大的做用就是根據bean的名稱亦或類型等等,來返回一個bean的實例。

BeanFactory
  BeanFactory,以Factory結尾,表示它是一個工廠類(接口), 它負責生產和管理bean的一個工廠。在Spring中, BeanFactory是IOC容器的核心接口,它的職責包括:實例化、定位、配置應用程序中的對象及創建這些對象間的依賴。

       BeanFactory只是個接口,並非IOC容器的具體實現,可是Spring容器給出了不少種實現,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是經常使用的一個,該實現將以XML方式描述組成應用的對象及對象間的依賴關係。XmlBeanFactory類將持有此XML配置元數據,並用它來構建一個徹底可配置的系統或應用。web

ApplicationContext接口

它由BeanFactory接口派生而來,ApplicationContext包含BeanFactory的全部功能,一般建議比BeanFactory優先。spring

ApplicationContext以一種更向面向框架的方式工做以及對上下文進行分層和實現繼承,ApplicationContext包還提供瞭如下的功能:框架

  • MessageSource, 提供國際化的消息訪問
  • 資源訪問,如URL和文件
  • 事件傳播
  • 載入多個(有繼承關係)上下文 ,使得每個上下文都專一於一個特定的層次,好比應用的web層;

對BeanFactory的思考

一個工廠若是想擁有這樣的功能,那麼它必定須要如下幾個因素:
  1. 須要持有各類bean的定義,不然沒法正確的完成bean的實例化。
  2. 須要持有bean之間的依賴關係,不然在bean實例化的過程當中也會出現問題。例如,A包含了B的實例。可是在A初始化以後,調用B實例的方法時,就會報空指針異常,由於A並無被真正的正確初始化。
  3. 以上兩種都要依賴於咱們所寫的依賴關係的定義,暫且認爲是XML文件(其實能夠是各類各樣的),那麼咱們須要一個工具來完成XML文件的讀取。

我目前想到的,只須要知足以上三種條件,即可以建立一個bean工廠,來生產各類bean。固然,spring確定有更高級的作法,以上只是我直觀的去想如何實現IOC。函數

那麼從上面的描述中,我又引伸出了另外一個核心問題,Bean的定義是什麼,他的依賴關係又如何描述?工具

那麼答案是,一個祖宗級別的接口,來看BeanDefinition。ui

BeanDefinition

package org.springframework.beans.factory.config;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.core.AttributeAccessor;

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;

    String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;

    int ROLE_APPLICATION = 0;

    int ROLE_SUPPORT = 1;

    int ROLE_INFRASTRUCTURE = 2;

    String getParentName();

    void setParentName(String parentName);

    String getBeanClassName();

    void setBeanClassName(String beanClassName);

    String getFactoryBeanName();

    void setFactoryBeanName(String factoryBeanName);

    String getFactoryMethodName();

    void setFactoryMethodName(String factoryMethodName);

    String getScope();

    void setScope(String scope);

    boolean isLazyInit();

    void setLazyInit(boolean lazyInit);

    String[] getDependsOn();

    void setDependsOn(String[] dependsOn);

    boolean isAutowireCandidate();

    void setAutowireCandidate(boolean autowireCandidate);
    
    boolean isPrimary();

    void setPrimary(boolean primary);

    ConstructorArgumentValues getConstructorArgumentValues();

    MutablePropertyValues getPropertyValues();

    boolean isSingleton();

    boolean isPrototype();

    boolean isAbstract();

    int getRole();

    String getDescription();

    String getResourceDescription();

    BeanDefinition getOriginatingBeanDefinition();
}複製代碼
接口上給出的註釋簡明扼要的描述了該接口: BeanDefinition描述了一個bean實例,它具備屬性值,構造函數參數值以及具體實現提供的更多信息。

能夠看到上面的不少屬性和方法都很熟悉,例如類名、scope、屬性、構造函數參數列表、依賴的bean、是不是單例類、是不是懶加載等,其實就是將Bean的定義信息存儲到這個BeanDefinition相應的屬性中,後面對Bean的操做就直接對BeanDefinition進行,例如拿到這個BeanDefinition後,能夠根據裏面的類名、構造函數、構造函數參數,使用反射進行對象建立。 BeanDefinition是一個接口,是一個抽象的定義,實際使用的是其實現類,如ChildBeanDefinition、RootBeanDefinition、GenericBeanDefinition等。

繼承關係

BeanDefinition這個接口即是spring中的bean定義接口,因此其實咱們工廠裏持有的bean定義,就是一堆這個玩意,或者是他的實現類和子接口。這個接口並不是直接的祖宗接口,他所繼承的兩個接口一個是core下面的AttributeAccessor,繼承這個接口就覺得這咱們的bean定義接口一樣具備處理屬性的能力,而另一個是beans下面的BeanMetadataElement,這個接口就是bean的元數據元素,它能夠得到bean的配置定義的一個元素。在XML文件中來講,就是會持有一個bean標籤。spa


BeanDefinition的一些依賴與實現,這裏就不細緻展開
(圖片參考自 www.jianshu.com/p/1d06f6342…

小結

本篇文章介紹了Spring實現IOC這一機制的最基礎的兩個接口BeanFactory和BeanDefinition。一個是生產Bean的工廠,一個是對Bean的定義,這兩個接口以最基礎的形式定義了Bean是什麼以及是如何產生的,Spring在實際應用中使用的類或者接口不少也都是實現了這兩個接口,如ApplicationContext、ChildBeanDefinition等等。設計

相關文章
相關標籤/搜索