Spring的核心容器就是一個大工廠,所有的對象,也就是所有的Bean(包括數(shù)據(jù)源等)都是Spring核心容器管理的對象。只要是一個Java類,Spring就可以把它當(dāng)作Bean來管理。
Spring Bean的好處
- Lifecycle method生命周期方法:更好實現(xiàn)對象的初始化和資源銷毀;
- Scope作用域:提供如singleton、prototype等作用域,使在創(chuàng)建對象時根據(jù)訪問次數(shù)來選擇相關(guān)作用域。
- Lazy延遲加載方法(懶加載):對象用時調(diào)用,不用時無需加載和實例化;
根據(jù)以上三種方法,實現(xiàn)Bean對象的有效管理。
同時,Spring框架可以基于用戶設(shè)計管理對象與對象之間的依賴關(guān)系,來降低兩者之間的耦合,從而提供程序的復(fù)用性和擴展性。
Bean作用域
Bean提供五種作用域,默認情況下采用單例模式
- singleton:單例模式,Spring IoC容器中只會存在一個共享的Bean實例,無論有多少個Bean引用它,始終指向同一對象。Singleton作用域是Spring中的缺省作用域,也可以顯示的將Bean定義為singleton模式,配置為:
- prototype:原型模式,每次通過Spring容器獲取prototype定義的bean時,容器都將創(chuàng)建一個新的Bean實例,每個Bean實例都有自己的屬性和狀態(tài),而singleton全局只有一個對象。根據(jù)經(jīng)驗,對有狀態(tài)的bean使用prototype作用域,而對無狀態(tài)的bean使用singleton作用域。
- request:在一次Http請求中,容器會返回該Bean的同一實例。而對不同的Http請求則會產(chǎn)生新的Bean,而且該bean僅在當(dāng)前Http Request內(nèi)有效。
,針對每一次Http請求,Spring容器根據(jù)該bean的定義創(chuàng)建一個全新的實例,且該實例僅在當(dāng)前Http請求內(nèi)有效,而其它請求無法看到當(dāng)前請求中狀態(tài)的變化,當(dāng)當(dāng)前Http請求結(jié)束,該bean實例也將會被銷毀。 - session:在一次Http Session中,容器會返回該Bean的同一實例。而對不同的Session請求則會創(chuàng)建新的實例,該bean實例僅在當(dāng)前Session內(nèi)有效。
,同Http請求相同,每一次session請求創(chuàng)建新的實例,而不同的實例之間不共享屬性,且實例僅在自己的session請求內(nèi)有效,請求結(jié)束,則實例將被銷毀。 - global Session:在一個全局的Http Session中,容器會返回該Bean的同一個實例,僅在使用portlet context時有效。
在實際開發(fā)中是存在多例的需求的(如購物車,用戶的訂單等
我們可以通過設(shè)置scope的值來改變某一個Bean的作用域
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd" xmlns:tx="http://www.springframework.org/schema/tx">
<bean id="beanScope" class="org.bean.example.BeanScope" scope="singleton"></bean>
</beans>
Spring Bean 為什么默認是單例模式
單例bean的優(yōu)勢
由于不會每次都新創(chuàng)建新對象所以有一下幾個性能上的優(yōu)勢:
- 減少了新生成實例的消耗
新生成實例消耗包括兩方面,第一,Spring會通過反射或者cglib來生成bean實例這都是耗性能的操作,其次給對象分配內(nèi)存也會涉及復(fù)雜算法。
- 減少jvm垃圾回收
由于不會給每個請求都新生成bean實例,所以自然回收的對象少了。
- 可以快速獲取到bean
因為單例的獲取bean操作除了第一次生成之外其余的都是從緩存里獲取的所以很快。
單例有啥劣勢?
如果是有狀態(tài)的話在并發(fā)環(huán)境下線程不安全。
這里我的理解是單例模式分為餓漢模式和懶漢模式,其中懶漢模式在沒有鎖的情況下遇到并發(fā)同時訪問就會出現(xiàn)線程不安全問題。
生命周期
bean在單例模式下的生命周期:
bean在單例模式下,spring容器啟動時解析xml發(fā)現(xiàn)該bean標(biāo)簽后,直接創(chuàng)建該bean的對象存入內(nèi)部map中保存,此后無論調(diào)用多少次getBean()獲取該bean都是從map中獲取該對象返回,一直是一個對象。此對象一直被Spring容器持有,直到容器退出時,隨著容器的退出對象被銷毀。
bean在多例模式下的生命周期:
bean在多例模式下,spring容器啟動時解析xml發(fā)現(xiàn)該bean標(biāo)簽后,只是將該bean進行管理,并不會創(chuàng)建對象,此后每次使用 getBean()獲取該bean時,spring都會重新創(chuàng)建該對象返回,每次都是一個新的對象。這個對象spring容器并不會持有,什么銷毀取決于使用該對象的用戶自己什么時候銷毀該對象。
BeanFactory
從應(yīng)用中我們可以了解到,使用Spring的好處就是,程序員不用再關(guān)心對象的創(chuàng)建過程與對象之間依賴關(guān)系,這些都交給Spring去管理了。spring通過BeanFactory來管理這些對象,我們只需做到以下幾點:
- 告訴spring哪些類是需要交給它去管理的;
- 怎么告訴spring這些類;
- 怎樣維護依賴關(guān)系(setter或contructor);
- 怎樣體現(xiàn)setter、contructor;
BeanFactory和FactoryBean的區(qū)別
BeanFactory
BeanFactory是一個spring中的一個工廠,可以產(chǎn)生bean,可以通過getBean獲??;
FactoryBean
FactoryBean是spring中一個特殊的bean,它可以產(chǎn)生bean,實現(xiàn)了FactoryBean接口的類,可以通過getObject獲取生產(chǎn)出來的bean。FactoryBean和它所產(chǎn)生出來的bean的存在形式也不一樣,如果你想要直接獲取FactoryBean本身則通過getBean(bean名字)獲取,如果想要獲取它生產(chǎn)出來的bean則通過getBean(&bean名字)來獲取。