spring之BeanFactory
?BeanFactory
BeanFactory 是 Spring 的“心臟”。它就是 Spring IoC 容器的真面目。Spring 使用 BeanFactory 來實(shí)例化、配置和管理 Bean。但是,在大多數(shù)情況我們并不直接使用 BeanFactory,而是使用 ApplicationContext。它也是 BeanFactory 的一個(gè)實(shí)現(xiàn),但是它添加了一系列“框架”的特征,比如:國際化支持、資源訪問、事件傳播等。ApplicationContext 我們將在后面章節(jié)中介紹。
BeanFactory 其實(shí)是一個(gè)接口-org.springframework.beans.factory.BeanFactory,它可以配置和管理幾乎所有的 Java 類。當(dāng)然,具體的工作是由實(shí)現(xiàn) BeanFactory 接口的實(shí)現(xiàn)類完成。我們最常用的 BeanFactory 實(shí)現(xiàn)是 org.springframework.beans.factory.xml.XmlBeanFactory。它從 XML 文件中讀取 Bean 的定義信息。當(dāng) BeanFactory 被創(chuàng)建時(shí),Spring 驗(yàn)證每個(gè) Bean 的配置。當(dāng)然,要等 Bean 創(chuàng)建之后才能設(shè)置 Bean 的屬性。單例(Singleton)Bean 在啟動(dòng)時(shí)就會被 BeanFactory 實(shí)例化,其它的 Bean 在請求時(shí)創(chuàng)建。根據(jù) BeanFactory 的 Java 文檔(Javadocs)介紹,“Bean 定義的持久化方式?jīng)]有任何的限制:LDAP、RDBMS、XML、屬性文件,等等”。現(xiàn)在 Spring 已提供了 XML 文件和屬性文件的實(shí)現(xiàn)。無疑,XML 文件是定義 Bean 的最佳方式。
BeanFactory 是初始化 Bean 和調(diào)用它們生命周期方法的“吃苦耐勞者”。注意,BeanFactory 只能管理單例(Singleton)Bean 的生命周期。它不能管理原型(prototype,非單例)Bean 的生命周期。這是因?yàn)樵?Bean 實(shí)例被創(chuàng)建之后便被傳給了客戶端,容器失去了對它們的引用。
spring的IOC容器能夠幫我們自動(dòng)new對象,對象交給spring管之后我們不用自己手動(dòng)去new對象了。那么它的原理是什么呢?是怎么實(shí)現(xiàn)的呢?下面我來簡單的模擬一下spring的機(jī)制,相信看完之后就會對spring的原理有一定的了解。spring使用BeanFactory來實(shí)例化、配置和管理對象,但是它只是一個(gè)接口,里面有一個(gè)getBean()方法。我們一般都不直接用BeanFactory,而是用它的實(shí)現(xiàn)類ApplicationContext,這個(gè)類會自動(dòng)解析我們配置的applicationContext.xml,然后根據(jù)我們配置的bean來new對象,將new好的對象放進(jìn)一個(gè)Map中,鍵就是我們bean的id,值就是new的對象。
首先我們建立一個(gè)BeanFactory接口
1 package com.spring; 2 3 public interface BeanFactory { 4 Object getBean(String id); 5 }然后建立一個(gè)BeanFactory的實(shí)現(xiàn)類ClassPathXmlApplicationContext.java
1 package com.spring;2 3 import java.util.HashMap;4 import java.util.List;5 import java.util.Map;6 7 import org.dom4j.Document;8 import org.dom4j.DocumentException;9 import org.dom4j.Element; 10 import org.dom4j.io.SAXReader; 11 12 13 public class ClassPathXmlApplicationContext implements BeanFactory { 14 private Map<String, Object> beans = new HashMap<String, Object>(); 15 public ClassPathXmlApplicationContext(String fileName) throws Exception{ 16 SAXReader reader = new SAXReader(); 17 Document document = reader.read(this.getClass().getClassLoader().getResourceAsStream(fileName)); 18 List<Element> elements = document.selectNodes("/beans/bean"); 19 for (Element e : elements) { 20 String id = e.attributeValue("id"); 21 String value = e.attributeValue("class"); 22 Object o = Class.forName(value).newInstance(); 23 beans.put(id, o); 24 } 25 } 26 27 public Object getBean(String id) { 28 return beans.get(id); 29 } 30 31 }然后配置applicationContext.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans> 3 <bean id="c" class="com.spring.Car"></bean> 4 <bean id="p" class="com.spring.Plane"></bean> 5 </beans>創(chuàng)建類的時(shí)候順便演示一下工廠模式,其實(shí)BeanFactory它也是一種工廠模式的。
1 package com.spring; 2 3 public interface Moveable { 4 void run(); 5 } 1 package com.spring; 2 3 public class Car implements Moveable{ 4 5 public void run(){ 6 System.out.println("拖著四個(gè)輪子滿街跑car·····"); 7 } 8 } 1 package com.spring; 2 3 public class Plane implements Moveable{ 4 5 public void run() { 6 System.out.println("拖著翅膀天空飛plane......"); 7 } 8 9 }?
現(xiàn)在來看一看效果吧,寫一個(gè)類測試一下:
1 package com.spring;2 3 import org.dom4j.DocumentException;4 5 public class Test {6 7 /**8 * @param args9 * @throws DocumentException 10 */ 11 public static void main(String[] args) throws Exception { 12 BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); 13 Object o = factory.getBean("c"); 14 Moveable m = (Moveable)o; 15 m.run(); 16 } 17 18 }由于Map容器里面保存的是Object類型,所以通過getBean()方法取出來的對象要強(qiáng)制類型轉(zhuǎn)換。
BeanFactory 管理 Bean(組件)的生命周期
下圖描述了 Bean 的生命周期。它是由 IoC 容器控制。IoC 容器定義 Bean 操作的規(guī)則,即 Bean 的定義(BeanDefinition)。Bean 的定義包含了 BeanFactory 在創(chuàng)建 Bean 實(shí)例時(shí)需要的所有信息。BeanFactory 首先通過構(gòu)造函數(shù)創(chuàng)建一個(gè) Bean 實(shí)例,之后它會執(zhí)行 Bean 實(shí)例的一系列之前初始化動(dòng)作,初始化結(jié)束 Bean 將進(jìn)入準(zhǔn)備就緒(ready)狀態(tài),這時(shí)應(yīng)用程序就可以獲取這些 Bean 實(shí)例了。最后,當(dāng)你銷毀單例(Singleton)Bean 時(shí),它會調(diào)用相應(yīng)的銷毀方法,結(jié)束 Bean 實(shí)例的生命周期。
Bean 的定義
前面的用戶注冊的例子中,我們已經(jīng)使用 Spring 定義了一個(gè)用戶持久化類:
<bean id="userDao" class="com.dev.spring.simple.MemoryUserDao"/> 這是一個(gè)最簡單的 Bean 定義。它類似于調(diào)用了語句: MemoryUserDao userDao = new MemoryUserDao()。 id屬性必須是一個(gè)有效的 XML ID,這意味著它在整個(gè) XML 文檔中必須唯一。它是一個(gè) Bean 的“終身代號(9527)”。同時(shí)你也可以用 name 屬性為 Bean 定義一個(gè)或多個(gè)別名(用逗號或空格分開多個(gè)別名)。name 屬性允許出現(xiàn)任意非法的 XML 字母。例如: <bean id="userDao" name="userDao*_1, userDao*_2"class="com.dev.spring.simple.MemoryUserDao"/>。class屬性定義了這個(gè) Bean 的全限定類名(包名+類名)。Spring 能管理幾乎所有的 Java 類。一般情況,這個(gè) Java 類會有一個(gè)默認(rèn)的構(gòu)造函數(shù),用set方法設(shè)置依賴的屬性。
Bean 元素出了上面的兩個(gè)屬性之外,還有很多其它屬性。說明如下:
<beanid="beanId"(1)name="beanName"(2)class="beanClass"(3)parent="parentBean"(4)abstract="true | false"(5)singleton="true | false"(6)lazy-init="true | false | default"(7)autowire="no | byName | byType | constructor | autodetect | default"(8)dependency-check = "none | objects | simple | all | default"(9)depends-on="dependsOnBean"(10)init-method="method"(11)destroy-method="method"(12)factory-method="method"(13)factory-bean="bean">(14)</bean> (1).id: Bean 的唯一標(biāo)識名。它必須是合法的 XML ID,在整個(gè) XML 文檔中唯一。(2).name: 用來為 id 創(chuàng)建一個(gè)或多個(gè)別名。它可以是任意的字母符合。多個(gè)別名之間用逗號或空格分開。(3).class: 用來定義類的全限定名(包名+類名)。只有子類 Bean 不用定義該屬性。(4).parent: 子類 Bean 定義它所引用它的父類 Bean。這時(shí)前面的 class 屬性失效。子類 Bean 會繼承父類 Bean 的所有屬性,子類 Bean 也可以覆蓋父類 Bean 的屬性。注意:子類 Bean 和父類 Bean 是同一個(gè) Java 類。(5).abstract(默認(rèn)為”false”):用來定義 Bean 是否為抽象 Bean。它表示這個(gè) Bean 將不會被實(shí)例化,一般用于父類 Bean,因?yàn)楦割?Bean 主要是供子類 Bean 繼承使用。(6).singleton(默認(rèn)為“true”):定義 Bean 是否是 Singleton(單例)。如果設(shè)為“true”,則在 BeanFactory 作用范圍內(nèi),只維護(hù)此 Bean 的一個(gè)實(shí)例。如果設(shè)為“flase”,Bean將是 Prototype(原型)狀態(tài),BeanFactory 將為每次 Bean 請求創(chuàng)建一個(gè)新的 Bean 實(shí)例。(7).lazy-init(默認(rèn)為“default”):用來定義這個(gè) Bean 是否實(shí)現(xiàn)懶初始化。如果為“true”,它將在 BeanFactory 啟動(dòng)時(shí)初始化所有的 Singleton Bean。反之,如果為“false”,它只在 Bean 請求時(shí)才開始創(chuàng)建 Singleton Bean。(8).autowire(自動(dòng)裝配,默認(rèn)為“default”):它定義了 Bean 的自動(dòng)裝載方式。“no”:不使用自動(dòng)裝配功能。 “byName”:通過 Bean 的屬性名實(shí)現(xiàn)自動(dòng)裝配。 “byType”:通過 Bean 的類型實(shí)現(xiàn)自動(dòng)裝配。 “constructor”:類似于 byType,但它是用于構(gòu)造函數(shù)的參數(shù)的自動(dòng)組裝。 “autodetect”:通過 Bean 類的反省機(jī)制(introspection)決定是使用“constructor”還是使用“byType”。 (9).dependency-check(依賴檢查,默認(rèn)為“default”):它用來確保 Bean 組件通過 JavaBean 描述的所以依賴關(guān)系都得到滿足。在與自動(dòng)裝配功能一起使用時(shí),它特別有用。none:不進(jìn)行依賴檢查。 objects:只做對象間依賴的檢查。 simple:只做原始類型和 String 類型依賴的檢查 all:對所有類型的依賴進(jìn)行檢查。它包括了前面的 objects 和 simple。 (10).depends-on(依賴對象):這個(gè) Bean 在初始化時(shí)依賴的對象,這個(gè)對象會在這個(gè) Bean 初始化之前創(chuàng)建。(11).init-method:用來定義 Bean 的初始化方法,它會在 Bean 組裝之后調(diào)用。它必須是一個(gè)無參數(shù)的方法。(12).destroy-method:用來定義 Bean 的銷毀方法,它在 BeanFactory 關(guān)閉時(shí)調(diào)用。同樣,它也必須是一個(gè)無參數(shù)的方法。它只能應(yīng)用于singleton Bean。(13).factory-method:定義創(chuàng)建該 Bean 對象的工廠方法。它用于下面的“factory-bean”,表示這個(gè) Bean 是通過工廠方法創(chuàng)建。此時(shí),“class”屬性失效。(14).factory-bean:定義創(chuàng)建該 Bean 對象的工廠類。如果使用了“factory-bean”則“class”屬性失效。(1).id: Bean 的唯一標(biāo)識名。它必須是合法的 XML ID,在整個(gè) XML 文檔中唯一。(2).name: 用來為 id 創(chuàng)建一個(gè)或多個(gè)別名。它可以是任意的字母符合。多個(gè)別名之間用逗號或空格分開。(3).class: 用來定義類的全限定名(包名+類名)。只有子類 Bean 不用定義該屬性。(4).parent: 子類 Bean 定義它所引用它的父類 Bean。這時(shí)前面的 class 屬性失效。子類 Bean 會繼承父類 Bean 的所有屬性,子類 Bean 也可以覆蓋父類 Bean 的屬性。注意:子類 Bean 和父類 Bean 是同一個(gè) Java 類。(5).abstract(默認(rèn)為”false”):用來定義 Bean 是否為抽象 Bean。它表示這個(gè) Bean 將不會被實(shí)例化,一般用于父類 Bean,因?yàn)楦割?Bean 主要是供子類 Bean 繼承使用。(6).singleton(默認(rèn)為“true”):定義 Bean 是否是 Singleton(單例)。如果設(shè)為“true”,則在 BeanFactory 作用范圍內(nèi),只維護(hù)此 Bean 的一個(gè)實(shí)例。如果設(shè)為“flase”,Bean將是 Prototype(原型)狀態(tài),BeanFactory 將為每次 Bean 請求創(chuàng)建一個(gè)新的 Bean 實(shí)例。(7).lazy-init(默認(rèn)為“default”):用來定義這個(gè) Bean 是否實(shí)現(xiàn)懶初始化。如果為“true”,它將在 BeanFactory 啟動(dòng)時(shí)初始化所有的 Singleton Bean。反之,如果為“false”,它只在 Bean 請求時(shí)才開始創(chuàng)建 Singleton Bean。(8).autowire(自動(dòng)裝配,默認(rèn)為“default”):它定義了 Bean 的自動(dòng)裝載方式。“no”:不使用自動(dòng)裝配功能。 “byName”:通過 Bean 的屬性名實(shí)現(xiàn)自動(dòng)裝配。 “byType”:通過 Bean 的類型實(shí)現(xiàn)自動(dòng)裝配。 “constructor”:類似于 byType,但它是用于構(gòu)造函數(shù)的參數(shù)的自動(dòng)組裝。 “autodetect”:通過 Bean 類的反省機(jī)制(introspection)決定是使用“constructor”還是使用“byType”。 (9).dependency-check(依賴檢查,默認(rèn)為“default”):它用來確保 Bean 組件通過 JavaBean 描述的所以依賴關(guān)系都得到滿足。在與自動(dòng)裝配功能一起使用時(shí),它特別有用。none:不進(jìn)行依賴檢查。 objects:只做對象間依賴的檢查。 simple:只做原始類型和 String 類型依賴的檢查 all:對所有類型的依賴進(jìn)行檢查。它包括了前面的 objects 和 simple。 (10).depends-on(依賴對象):這個(gè) Bean 在初始化時(shí)依賴的對象,這個(gè)對象會在這個(gè) Bean 初始化之前創(chuàng)建。(11).init-method:用來定義 Bean 的初始化方法,它會在 Bean 組裝之后調(diào)用。它必須是一個(gè)無參數(shù)的方法。(12).destroy-method:用來定義 Bean 的銷毀方法,它在 BeanFactory 關(guān)閉時(shí)調(diào)用。同樣,它也必須是一個(gè)無參數(shù)的方法。它只能應(yīng)用于singleton Bean。(13).factory-method:定義創(chuàng)建該 Bean 對象的工廠方法。它用于下面的“factory-bean”,表示這個(gè) Bean 是通過工廠方法創(chuàng)建。此時(shí),“class”屬性失效。(14).factory-bean:定義創(chuàng)建該 Bean 對象的工廠類。如果使用了“factory-bean”則“class”屬性失效。?
轉(zhuǎn)載于:https://www.cnblogs.com/wei-91/p/6616991.html
總結(jié)
以上是生活随笔為你收集整理的spring之BeanFactory的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 7620:区间合并
- 下一篇: 【转载】栈溢出原理及实现