
面试官经常喜欢问Spring中的bean是不是线程安全的这个问题用来考察对Spring 中Bean作用域的理解,先说结论, Spring中的Bean不是线程安全的 。
Spring容器中的Bean是否线程安全,容器本身并没有提供Bean的线程安全策略,因此可以说Spring容器中的Bean本身不具备线程安全的特性,但是具体还是要结合具体scope的Bean去研究。
Spring 的 bean 作用域(scope)类型有5种:
线程安全这个问题,要从单例与原型Bean分别进行说明。
原型Bean 对于原型Bean,每次创建一个新对象,也就是线程之间并不存在Bean共享,自然是不会有线程安全的问题。
单例Bean 对于单例Bean,所有线程都共享一个单例实例Bean,因此是存在资源的竞争。
如果单例Bean,是一个无状态Bean,也就是线程中的 *** 作不会对Bean的成员执行 查询 以外的 *** 作,那么这个单例Bean是线程安全的。
Spring中的Bean默认是单例模式的,框架并没有对bean进行多线程的封装处理。实际上大部分时间Bean是无状态的(比如Dao) 所以说在某种程度上来说Bean其实是安全的。
但是如果Bean是有状态的 那就需要开发人员自己来进行线程安全的保证,最简单的办法就是改变bean的作用域 把 singleton 改为 protopyte , 这样每次请求Bean就相当于是 new Bean() 这样就可以保证线程的安全了。
有状态就是有数据存储功能 无状态就是不会保存数据
controller、service和dao层本身并不是线程安全的,只是如果只是调用里面的方法,而且多线程调用一个实例的方法,会在内存中复制变量,这是自己的线程的工作内存,是安全的。
想理解原理可以看看《深入理解JVM虚拟机》,222节:
《Java并发编程实战》第322节:
所以其实任何无状态单例都是线程安全的。Spring的根本就是通过大量这种单例构建起系统,以事务脚本的方式提供服务
也可以看看这篇加深理解:[关于Spring的@Controller @Service等的线程安全问题],地址: >public class GetApplicationContext {
private static class ApplicationContextHolder {
// 单例变量
private static ApplicationContext AC = new FileSystemXmlApplicationContext(
"classpath:applicationContextxml");
}
// 私有化的构造方法,保证外部的类不能通过构造器来实例化。
private GetApplicationContext() {
}
// 获取单例对象实例
public static ApplicationContext getInstance() {
if (ApplicationContextHolderAC == null) {
ApplicationContextHolderAC = new FileSystemXmlApplicationContext(
"classpath:applicationContextxml");
}
return ApplicationContextHolderAC;
}
}
获取所有spring自动装配的bean:
<span style="font-size:18px;">//获取spring装配的bean个数GetApplicationContextgetInstance()getBeanDefinitionNames()length;
//逐个打印出spring自动装配的bean。根据我的测试,类名第一个字母小写即bean的名字
for(int i=0;i<33;i++){
Systemoutprintln( GetApplicationContextgetInstance()getBeanDefinitionNames()[i]);
}</span>
然后通过下面的代码获取到spring注解装配的bean供自己使用:
<span style="font-size:18px;">StorageReturnService ossService = (StorageReturnService) GetApplicationContextgetInstance()getBean("storageReturnServiceImpl");</span>你可以不用单例模式
Spring支持如下五种作用域:
singleton: 单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例。
prototype: 每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
request: 对于一次>
ThreadcurrentThread()是得到当前运行的线程名,如果你不停的切换线程自然会变,还有ThreadLocal也是会跟着变的。 你要永远记着,每个线程都有自己对应的ThreadLocal,TL只是Thread的局部变量。
以上就是关于职面 | 面试官:Spring 中的 bean 是线程安全的吗全部的内容,包括:职面 | 面试官:Spring 中的 bean 是线程安全的吗、如何获取spring 注解的bean、spring的bean一般是单例模式,那多线程是怎么解决的等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)