1. 程式人生 > >Spring多執行緒環境下Bean的管理策略

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模式,scope要配成prototype作用域。 

Prototype: 每次對bean的請求都會建立一個新的bean例項

由上可總結得出:無狀態的Bean適合用不變模式,就是單例模式,這樣可以共享例項,提高效能。

有狀態的Bean,多執行緒環境下不安全,那麼適合用Prototype原型模式。

三、多執行緒環境下Bean的處理策略:

1.對於實體bean一般通過方法引數的的形式傳遞, 引數是區域性變數,多執行緒之間不會有影響。如Spring的DI.

2.對於有狀態的bean直接使用prototype原型模式來進行解決。

3.私有成員變數可以用ThreadLocal加以保護,

讓它們也成為執行緒安全的狀態,這樣有狀態的Bean就可以在多執行緒中共享了

如,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