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


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
多线程下注入 Spring Bean,我们需要注意一些问题。首先,Spring Bean 的依赖注入是线程安全的,因为 Spring 容器会保证 Bean 的实例唯一,并且在多线程环境中不会出现竞态条件。然而,如果我们在多线程环境下手动创建 Bean 实例并注入,就需要注意线程安全性。 为了在多线程下注入 Spring Bean,我们需要确保 Bean 的作用域是线程安全的。通常情况下,我们可以将 Bean 的作用域设置为 prototype,使得每个线程都拥有自己的 Bean 实例,避免线程间的竞态条件。 另外,我们需要注意在多线程环境下对 Bean 的操作是否会造成线程安全问题。比如在单例 Bean 中使用了非线程安全的对象或方法,就可能会导致线程安全问题。在这种情况下,我们需要使用同步机制来保证线程安全,或者考虑将 Bean 的作用域设置为 prototype。 在注入 Bean 的时候,我们还需要考虑是否需要进行依赖注入或者手动创建 Bean 实例。如果需要在多线程下注入 Bean,最好使用 Spring 容器进行依赖注入,这样可以保证线程安全性并且简化代码逻辑。 总的来说,在多线程下注入 Spring Bean,我们需要确保 Bean 的作用域是线程安全的,并且在操作 Bean 的过程中注意线程安全性,避免出现竞态条件。同时尽量使用 Spring 容器进行依赖注入,避免手动创建 Bean 实例造成线程安全问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值