Spring Ioc容器的設計:BeanFactory和ApplicationContext

Spring Ioc容器的設計java

在Spring Ioc容器的設計中,有兩個主要的容器系列,一個是實現BeanFactory接口的簡單容器系列,只實現了容器的最基本的功能;另外一個是ApplicationContext應用上下文,進行了不少擴展,它做爲容器的高級形態存在。編程

Spring Ioc容器的設計:。。。。函數

BeanFactory容器的設計原理(以 實現類XmlBeanFactory爲例):this

public class XmlBeanFactory extends DefaultListableBeanFactory
{

    public XmlBeanFactory(Resource resource)
        throws BeansException
    {
        this(resource, null);
    }

    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory)
        throws BeansException
    {
        super(parentBeanFactory);
        reader = new XmlBeanDefinitionReader(this);
        reader.loadBeanDefinitions(resource);
    }

    private final XmlBeanDefinitionReader reader;
}

在Spring中,其實是把DefaultListableBeanFactory做爲一個默認的功能完整的Ioc容器來使用。XmlBeanFactory容器繼承了DefaultListableBeanFactory又增長了一些新的功能。XmlBeanFactory是一個與XML相關的BeanFactory,是一個能夠讀取以XML文件方式定義的BeanDefinition(XML定義的信息)的Ioc容器。設計

BeanDefinition分爲FileSystemResource(文件系統中的Bean定義的信息可使用FileSystemResource來進行抽象)、ClassPathResource(在類路徑中的Bean定義信息可使用ClassPathResource來使用)等code

實現XML讀取的功能實現:對這些XML形式的信息處理並非直接經過XmlBeanFactory直接完成。從上面XmlBeanFactory的代碼中能夠看出初始化了一個XmlBeanDefinitionReader對象,對XML形式的信息處理其實是由XmlBeanDefinitionReader(Reader對象)來完成的。xml

構造XmlBeanFactory這個Ioc容器時,須要指定BeanDefinition的信息來源,須要被封裝成Spring中的Resource類給出。Resource是Spring用來封裝I/O操做的類。BeanDefinition信息是以XML文件形式存在的,可使用像ClassPathResource res = new ClassPathResource("beans.xml");這樣具體的ClassPathResource來構造須要的Resource,而後將Resource做爲構造參數傳遞給XmlBeanFactory構造函數。這樣,Ioc容器就能夠方便地定位到須要的BeanDefinition信息來對Bean完成容器的初始化和依賴注入過程。對象

ApplicationContext容器的設計原理(FileSystemXmlApplicationContext爲例):繼承

ApplicationContext與FileSystemXmlApplicationContext關係圖:接口

public class FileSystemXmlApplicationContext extends AbstractXmlApplicationContext
{

    public FileSystemXmlApplicationContext()
    {
    }

    public FileSystemXmlApplicationContext(ApplicationContext parent)
    {
        super(parent);
    }

    public FileSystemXmlApplicationContext(String configLocation)
        throws BeansException
    {
        this(new String[] {
            configLocation
        }, true, null);
    }

    public transient FileSystemXmlApplicationContext(String configLocations[])
        throws BeansException
    {
        this(configLocations, true, null);
    }

    public FileSystemXmlApplicationContext(String configLocations[], ApplicationContext parent)
        throws BeansException
    {
        this(configLocations, true, parent);
    }

    public FileSystemXmlApplicationContext(String configLocations[], boolean refresh)
        throws BeansException
    {
        this(configLocations, refresh, null);
    }
//下文所說自身須要實現的第一個功能
    public FileSystemXmlApplicationContext(String configLocations[], boolean refresh, ApplicationContext parent)
        throws BeansException
    {
        super(parent);
        setConfigLocations(configLocations);
        if(refresh)
            refresh();
    }
//下文所說自身須要實現的第二個功能
    protected Resource getResourceByPath(String path)
    {
        if(path != null && path.startsWith("/"))
            path = path.substring(1);
        return new FileSystemResource(path);
    }
}

在FileSystemXmlApplicationContext設計中,ApplicationContext應用上下文的功能已經在FileSystemXmlApplicationContext的基類AbstractXmlApplicationContext中實現了,在FileSystemXmlApplicationContext中,做爲一個具體的應用上下文,只需實現和它自身相關的兩個功能。

一個是:若是應用直接使用FileSystemXmlApplicationContext,須要實例化這個應用的上下文支持,同時啓動IoC容器的refresh()過程。這個refresh()過程會牽涉IoC容器啓動的一系列複雜操做,同時,對於不一樣容器的實現這些操做相似,所以在基類中將它封裝好,須要時調用。

另外一個:是與FileSystemXmlApplicationContext設計具體相關的功能,與怎樣從文件系統中加載XML的Bean定義資源有關。不一樣的應用上下文實現對應着不一樣的讀取BeanDefinition的方式,而FileSystemXmlApplicationContext經過這個過程,能夠爲在文件系統中讀取以XML形式存在的BeanDefinition作準備。

IoC容器的初始化過程

Spring Ioc容器的初始化是由前面介紹的refresh()方法來啓動的,這個方法標誌着Ioc容器的正式啓動。

包括三個步驟:BeanDefinition的Resource定位、載入、註冊

編程的方式使用DefaultListableBeanFactory(XmlBeanFactory的基類)(IoC容器初始化的過程和以編程的方式相似,能夠作參考):

//定義一個Resource來定位容器使用的BeanDefinition,這裏使用的是ClassPathResource(類路徑中找)
ClassPathResource res = new ClassPathResource("beans.xml");

DefaultListableBeanFactory factory = new DefaultListableBeanFactory();

//這裏的Resource不能由DefaultListableBeanFactory直接使用,Spring經過使用BeanDefinitionReader對這些信息進行處理
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);

reader.loadBeanDefinitions(res);

圖2-1

在這裏,咱們能夠看到使用ApplicationContext相對直接使用DefaultListableBeanFactory的好處,由於在ApplicationContext中,Spring已經爲咱們提供了一系列加載不一樣Resource的讀取器的實現,而DefaultListableBeanFactory只是一個純粹的IoC容器,須要爲它配置特定的讀取器才能完成這些功能。可是使用DefaultListableBeanFactory這種更底層的容器,能提升定製IoC容器的靈活性

BeanDefinition的Resource定位(這個定位過程相似容器尋找數據的過程):

回到ApplicationContext上來,例如FileSystemXmlApplicationContext、ClassPathXmlApplicationContext以及XmlApplicationContext等。

FileSystemXmlApplicationContext的繼承體系如上圖2-2

FileSystemXmlApplicationContext經過繼承AbstractApplicationContext具有了ResourceLoader讀入以Resource定義的BeanDefinition的能力,由於AbstractApplicationContext的基類是DefaultResourceLoader,而DefaultResourceLoader實現了ResourceLoader接口

參照FileSystemXmlApplicationContext的代碼清單,BeanDefinition資源定位(調用getResourceByPath)的過程,最初是由refresh來觸發的,而這個refresh的調用是在FileSystemXmlApplicationContext構造函數中啓動的。

相關文章
相關標籤/搜索