Spring 容器中的 Bean 是否线程安全, 容器本身并没有提供 Bean 的线程安全策略, 因此可以说 Spring 容器中的 Bean 本身不具备线程安全的特性, 但是具体还是要结合具体 scope 的 Bean 去研究.
Spring 的 bean 作用域 (scope) 类型
1,singleton: 单例, 默认作用域.
2,prototype: 原型, 每次创建一个新对象.
3,request: 请求, 每次 Http 请求创建一个新对象, 适用于 webApplicationContext 环境下.
4,session: 会话, 同一个会话共享一个实例, 不同会话使用不用的实例.
5,global-session: 全局会话, 所有会话共享一个实例.
线程安全这个问题, 要从单例与原型 Bean 分别进行说明.
原型 Bean
对于原型 Bean, 每次创建一个新对象, 也就是线程之间并不存在 Bean 共享, 自然是不会有线程安全的问题.
单例 Bean
对于单例 Bean, 所有线程都共享一个单例实例 Bean, 因此是存在资源的竞争.
如果单例 Bean, 是一个无状态 Bean, 也就是线程中的操作不会对 Bean 的成员执行查询以外的操作, 那么这个单例 Bean 是线程安全的. 比如 Spring mvc 的 Controller,Service,Dao 等, 这些 Bean 大多是无状态的, 只关注于方法本身.
对于有状态的 bean,Spring 官方提供的 bean, 一般提供了通过 ThreadLocal 去解决线程安全的方法, 比如 RequestContextHolder,TransactionSynchronizationManager,LocaleContextHolder 等.
使用 ThreadLocal 的好处
使得多线程场景下, 多个线程对这个单例 Bean 的成员变量并不存在资源的竞争, 因为 ThreadLocal 为每个线程保存线程私有的数据. 这是一种以空间换时间的方式.
当然也可以通过加锁的方法来解决线程安全, 这种以时间换空间的场景在高并发场景下显然是不实际的.
来源: http://www.jianshu.com/p/4db5f16f83a5