Spring中Bean的安全性问题--面试题
Spring中Bean的安全性
- Spring中的Bean从何而来?
- Spring中什么样的Bean存在线程安全问题?
- 如何处理spring Bean的线程安全问题?
Spring中的Bean从何而来?
Spring中除了很多内置Bean以外,其他的Bean都是通过Spring配置来声明的,然后由Spring容器统一加载。Spring声明配置时会配置以下内容。如:class(全类名)、id(Bean的唯一标识)、Scope(作用域),之后Spring容器根据配置内容使用对应的策略来创建Bean的实例。
因此,Spring 容器中的 Bean 其实都是根据我们自己写的类来创建的实例。所以, Spring 中的 Bean 是否线程安全,跟 Spring 容器无关,只是交由 Spring 容器托管而已。
Spring中什么样的Bean存在线程安全问题?
Spring框架里的bean,在获取实例的时候都是默认的单例模式。
在 Spring 定义的作用域中,其中有 prototype(多例 Bean)和 singleton(单例 Bean)。
- 定义为 prototype 的 Bean,是在每次 getBean 的时候都会创建一个新的对象。
- 定义为 singleton 的 Bean,在 Spring 容器中只会存在一个全局共享的实例。
多例 Bean 每次都会新创建新实例,也就是说线程之间不存在 Bean 共享的问题。因此,多例 Bean 是不存在线程安全问题的。而单例Bean 是所有线程共享的一个实例,因此,就可能会存在线程安全问题。
单例 Bean 又分为无状态 Bean 和有状态 Bean 。
- 无状态Bean:在多线程操作中只会对 Bean 的成员变量进行查询操作,不会修改成员变量的值,这样的 Bean称之为无状态 Bean 。所以,可想而知,无状态的单例 Bean 是不存在线程安全问题的。
- 有状态 Bean :但是在多线程操作中如果需要对 Bean 中的成员变量进行数据更新操作,这样的 Bean 称之为有状态 Bean ,所以,有状态的单例 Bean 就可能存在线程安全问题。
如何处理spring Bean的线程安全问题?
处理有状态的 Bean 的线程安全问题有以下三种方法:
- 将 Bean 的作用域由“singleton”单例改为“prototype”多例 在 Bean
- 对象中避免定义可变的成员变量
- 在类中定义 Thread Local的成员变量,并将需要的可变成员便来给你保存在 Thread Local 中,Thread Local 本身就具备线程隔离的特性,这就相当于为每个线程提供了一个独立的变量副本,每个线程只需要操作自己的线程副本变量,从而解决线程安全问题
如果大家想详细了解一下ThreadLocal可以看一下这个 ThreadLocal保证线程安全-面试题