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構造函數中啓動的。