接著開(kāi)始了解更加深入的東西戳吝。浩销。。骨坑。
在上篇中撼嗓,我們提到了兩個(gè)接口ApplicationContext,BeanFactory柬采。那么我們這章便從這里開(kāi)始了解這兩個(gè)接口欢唾。
BeanFactoty 如上述結(jié)構(gòu)圖所示,它其實(shí)是一個(gè)最頂級(jí)的接口粉捻,它是最基層的接口信息礁遣,它提供了最基本的IOC容器使用方法。
The root interface for accessing a Spring bean container.
This is the basic client view of a bean container;
這是Beanfactory所提供的所有接口肩刃,其功能依賴(lài)的注入功能其實(shí)都是依靠這個(gè)接口祟霍。它是可以將bean的信息保存起來(lái)(像xml)。
它定義了一個(gè)字符串盈包,“&”沸呐,用戶(hù)在使用&bean可以得到FactoryBean其本身,而不是獲取它產(chǎn)生的對(duì)象呢燥。獲取bean對(duì)象時(shí)崭添,只需要調(diào)用getBean方法,這個(gè)方法可以通過(guò)名稱(chēng)來(lái)獲取也可以增加其他參數(shù)叛氨。isPrototype 以及issingleton這些方法呼渣,來(lái)獲取這個(gè)bean的信息,并且這些信息都可以用用戶(hù)自己去控制寞埠。
HierarchicalBeanFactory這個(gè)接口中有一個(gè)方法:
我們可以根據(jù)這個(gè)方法去獲取一個(gè)root 屁置,BeanFactory.通過(guò)該方法Spring實(shí)現(xiàn)了可以控制雙親IOC容器的能力。
以前的BeanFactory 的調(diào)用時(shí)用XmlBeanFactory來(lái)實(shí)現(xiàn)的仁连。之后的Spring使用ClassPathXmlApplicationContext這個(gè)類(lèi)來(lái)實(shí)現(xiàn)的蓝角。這個(gè)過(guò)程我在上篇中講過(guò),有興趣的可以去看看饭冬。這個(gè)類(lèi)是實(shí)現(xiàn)ConfigurableApplicationContext接口的一個(gè)類(lèi)帅容,可以說(shuō)這個(gè)類(lèi)是繼承自ApplicationContext。
這整個(gè)IOC容器其實(shí)就是在這樣的接口框架下實(shí)現(xiàn)的伍伤。從一方面來(lái)說(shuō)并徘,ApplicationContext其實(shí)是在BeanFactory這個(gè)最基層的容器上進(jìn)行加工實(shí)現(xiàn)更加復(fù)雜的功能。
javawork ja=(javawork)ac.getBean("javawork");
這個(gè)方法獲取bean正在調(diào)用的getbean其實(shí)是BeanFactory的方法扰魂。
整個(gè)IOC就是先初始化麦乞,ClassPathXmlApplicationContext這個(gè)類(lèi)初始化會(huì)傳入配置文件的地址蕴茴,Resource是封裝了Spring對(duì)于inputStream的操作。
2.開(kāi)始初始化factory:ConfigurableListableBeanFactory這個(gè)factory姐直。
我們可以看到這個(gè)接口繼承于其他的三個(gè)倦淀,都是來(lái)源于BeanFactory。
refresh()中還初始化了一個(gè)XmlBeanDefinitionReader用來(lái)讀取xml配置文件声畏。
先從refresh()代碼中看撞叽,
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
這段代碼是初始化ConfigurableListableBeanFactory,進(jìn)入obtainFreshBeanFactory()函數(shù)插龄,
這段代碼返回的就是一個(gè)BeanFactory,那么一個(gè)問(wèn)題資源配置在哪里讀愿棋?
我們接著向下看:refreshBeanFactory();
在其類(lèi)中是這樣的:
是一個(gè)抽象方法,需要在其子類(lèi)中實(shí)現(xiàn)均牢。之前我發(fā)過(guò)的一張結(jié)構(gòu)圖糠雨,中間就是這類(lèi):AbstractRefeshableApplicationContext,其實(shí)我個(gè)人認(rèn)為這個(gè)名字就是告訴我們可以refresh.
如果有factory存在先銷(xiāo)毀在建立,它生成了一個(gè)DefaultListableBeanFactory 類(lèi)徘跪。
而加載配置xml 是通過(guò)loadBeanDefinitions()這個(gè)方法甘邀。
這個(gè)方法應(yīng)是在XmlWebApplicationContext.class
這個(gè)類(lèi)中
從中我們看到了loadBeanDefinitions(beanDefinitionReader);這段代碼,看名字應(yīng)該是引導(dǎo)配置文件的代碼垮庐。
這個(gè)函數(shù)有個(gè)getConfigLocations()松邪,這個(gè)函數(shù)在本身的類(lèi)中是沒(méi)有實(shí)現(xiàn)的,它實(shí)際是用了AbstractRefreshableConfigApplicationContext這個(gè)類(lèi)的getConfigLocations()方法哨查。
現(xiàn)在我們就應(yīng)該可以看到為什么
中有setConfigLocations這個(gè)方法逗抑,調(diào)用的是同一個(gè)對(duì)象。這就是為什么可以理解這個(gè)資源對(duì)象的地址來(lái)歷解恰。
然后調(diào)用
reader.loadBeanDefinitions(configLocation);
進(jìn)入到AbstractBeanDefinitionReader類(lèi)中對(duì)應(yīng)的方法中锋八。
中間進(jìn)行不斷的判斷,在跳轉(zhuǎn)到其子類(lèi)XmlBeanDefinitionReader中調(diào)用loadBeanDefinitions(EncodedResource encodedResource)
獲取inputstream护盈,再進(jìn)入protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)函數(shù)中便開(kāi)始不斷地解析xml挟纱。
這個(gè)調(diào)用饒了很多的彎,畫(huà)了張圖:
Spring將三個(gè)模塊分開(kāi)腐宋,這使用戶(hù)如果去定制自己的Spring的話(huà)更加方便紊服。
這個(gè)解析過(guò)程完善了上一篇的不足。但這一篇還有applicationContext類(lèi)胸竞。
它的結(jié)構(gòu)是
可以從中看出來(lái)欺嗤,其實(shí)該接口還實(shí)現(xiàn)了EnvironmentCapable ,ApplicationEventPublisher 以及MessageSource (除了BeanFactory的接口外)。
MessageSource是實(shí)現(xiàn)資源國(guó)家化的接口卫枝。ApplicationEventPublisher是事件處理煎饼,這些其實(shí)是更好的管理Bean。
這篇就先到這里了校赤。
若有問(wèn)題請(qǐng)私信吆玖。