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

猜你喜欢

转载自blog.csdn.net/wxb880114/article/details/88836002