Spring中的Bean是线程安全的吗?为什么?
答案:不是。
因为SpringIOC容器本身没有提供Bean的线程安全策略,所以Spring容器中的Bean本身不具备线程安全的特性,现在结合具体的作用域(scope)去研究。
Spring的Bean作用域scope类型(五种):
a.singleton(单例):默认作用域,SpringIOC中仅存在一个Bean实例,以单例Bean的方式存在。
b.prototype(原型):每次从容器中getBean()时,都返回一个新的实例。等于执行new Bean()。
c.request(请求):每次Http请求创建一个新对象。
d.session(会话):同一个会话共享一个实例,不同会话使用不同实例。
e.global-session(全局会话):所有会话共享一个实例。
request(请求)、session(会话)、global-session(全局会话):
**\color{red}{仅仅适用于WebApplicationContext环境下。}**
$\color{red}{红色字}$
线程安全这个问题,从常用的单例和原型Bean分别说明:
singleton(单例)Bean:
所有线程都共享一个单例Bean,因此是存在资源的竞争。
如果单例Bean是无状态的,也就是线程之间的操作不会对Bean的成员执行查询以外的操作,那么这个单例Bean是线程安全的。比如:Spring Mvc、Controller、Service、Dao等,这些Bean大多数是无状态的,只需要关注方法本身即可。
prototype(原型)Bean:
每个线程都创建一个新的对象,线程之间不存在Bean的共享,自然不存在线程安全的问题。
Spring中Bean是默认单例的,为什么Controller、Service、和Dao能保证线程安全?
Spring 中Bean默认是单例模式的,框架并没有对Bean进行多线程的封装处理。
Controller、Service和Dao本身并不是线程安全的,Java虚拟机栈是线程私有的,它的生命周期与线程相同,跟随线程结束而结束。
但是,如果Bean是有状态的,就需要开发人员自己来进行线程安全的保证,最简单的方法就是改变Bean的作用域把“singleton”改为“prototype",这样每次请求Bean都相当于new Bean(),问题解决。
tips:
有状态就是有存储数据的功能。
无状态就是不会存储数据。
网友评论