Spring多執行緒環境下Bean的管理策略
一、Bean的狀態:stateful 與 stateless
有狀態會話bean:每個使用者有自己特有的一個例項,在使用者的生存期內,bean保持了使用者的資訊,即“有狀態”;
一旦使用者滅亡(呼叫結束或例項結束),bean的生命期也告結束。即每個使用者最初都會得到一個初始的bean。
無狀態會話bean:bean一旦例項化就被加進會話池中,各個使用者都可以共用。即使使用者已經消亡,bean的生命期也不一定結束,
它可能依然存在於會話池中,供其他使用者呼叫。由於沒有特定的使用者,那麼也就不能保持某一使用者的狀態,所以叫無狀態bean。
但無狀態會話bean並非沒有狀態,如果它有自己的屬性(變數),那麼這些變數就會受到所有呼叫它的使用者的影響
二、Spring Bean的作用域及狀態
1.預設情況下,從Spring bean工廠所取得的例項為singleton(scope屬性為singleton),容器只存在一個共享的bean例項。
2.雖然在Spring容器中controller中會注入service,service中會注入dao,但service與dao中只要不宣告私有成員變數,也都是無狀態單例的,
所以最終controller中也不宣告私有的成員變數,就也是無狀態單例的,在多執行緒環境下依然是安全的
3.Struts2中的Action因為宣告有私有的例項物件或變數,是有狀態資訊的,在多執行緒環境下是不安全的,
所以Struts2的Action
Prototype: 每次對bean的請求都會建立一個新的bean例項
由上可總結得出:無狀態的Bean適合用不變模式,就是單例模式,這樣可以共享例項,提高效能。
有狀態的Bean,多執行緒環境下不安全,那麼適合用Prototype原型模式。
三、多執行緒環境下Bean的處理策略:
1.對於實體bean一般通過方法引數的的形式傳遞, 引數是區域性變數,多執行緒之間不會有影響。如Spring的DI.
2.對於有狀態的bean直接使用prototype原型模式來進行解決。
3.私有成員變數可以用ThreadLocal加以保護,
如,Hibernate中的sessionFactory,就使用的是 org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean,
而在 AnnotationSessionFactoryBean的父類LocalSessionFactoryBean中,定義了大量的ThreadLocal來保證多執行緒的安全性。
四、Spring Bean的生命週期:
1、Bean自身的方法:這個包括了Bean本身呼叫的方法和通過配置檔案中<bean>的init-method和destroy-method指定的方法
2、Bean級生命週期介面方法:這個包括了BeanNameAware、BeanFactoryAware、InitializingBean和DiposableBean這些介面的方法
3、容器級生命週期介面方法:這個包括了InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 這兩個介面實現,
一般稱它們的實現類為“後處理器”。
4、工廠後處理器介面方法:這個包括了AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer等等 非常有用的工廠後處理器介面的方法。工廠後處理器也是容器級的。在應用上下文裝配配置檔案之後立即呼叫。
五、Spring 多執行緒環境下對bean的注入
基於執行緒安全性,spring不能為多執行緒注入bean,使用@Resource或者@Autowired注入全部為NULL。
1.將需要的Bean作為執行緒的的建構函式的引數傳入
2.使用ApplicationContext.getBean方法來靜態的獲取Bean