Spring5系列(六) | Controller到底线程安全么

简介: Spring5系列(六) | Controller到底线程安全么

本篇文章比较简单,主要介绍下关于对象的scope, 其实一直有一道比较经典的面试题,问的是springMVC中的Controller是单例的么?我们就从这道题来引申出来。


我们在学习java基础的时候,都会学到一种设计模式,叫做单例设计模式。什么叫做单例设计模式呢,就是要保证我们创建出来的对象永远只有一个。为什么要这样呢,主要目的就是为了合理的利用内存。有些比较重量级的对象其实创建一次就可以了,那么我们就可以使用单例设计模式。什么样的情况不能使用单例呢,那就是存在线程安全的问题的类,或者说存在共享资源可能被多个线程进行操作时,就不能使用单例设计模式。关于单例设计模式的实现方式这里就不展开了。


我们前面在讲解FactoryBean这个接口的时候,提到过里边有三个需要实现的方法,最常用的方法是getObject(),这个也是最核心的方法,用来获取复杂对象。其中还有一个方法叫做boolean isSingleton();这个方法返回布尔类型值,如果返回结果为true, 代表会返回一个单例对象,也就是多次获取都是同一个对象。如果返回的false, 多次获取,每次都是新的对象。这是FactoryBean为我们提供的方法,那么我们正常的被spring管理的对象能否像isSingleton() 方法一样,可以控制对象的创建次数呢。当然是可以的,通过<bean> 标签中的scope属性来指定。我们以之前的User类为例。


<beanid="user"class="com.xxx.User"scope="singleton"/>


这个时候我们创建出来的对象就是单例的,不管调用多少次,得到的都是同一个对象。我们可以在测试类中演示。


ApplicationContextctx=newClassPathXmlApplicationContext("/applicationContext.xml");
Useru1= (User)ctx.getBean("user");
Useru2= (User)ctx.getBean("user");
System.out.println(u1);
System.out.println(u2);


观察结果可以发现打印的地址值是一样的,代表是同一个对象。那么如果我们想要非单例对象,也就是每次获取都是一个新的对象该如何处理呢,只需把scope改为prototype。


<beanid="user"class="com.xxx.User"scope="prototype"/>


再次执行上面的测试方法打印地址不同,说明是不同对象。

这里要注意,scope的默认值是singleton。也就是在不指定scope的情况下得到的也是单例对象。


那么对于使用工厂创建的对象如何指定呢。

  1. 对于实现FactoryBean的工厂,通过实现isSingleton() 方法指定
  2. 对于实例工厂和静态工厂,也是通过scope来指定。

如果不清楚什么是实例工厂和静态工厂,快去看下我的上一篇文章。 那么我们在来讲解下,到底什么样的对象用单例,什么时候不用单例呢?


单例的,一般就是比较耗资源的,且没有线程安全问题的,比如

  1. sqlSessionFactory
  2. DAO
  3. Service


对于非单例的:像数据库的连接和会话,对于每个线程之间需要有一定隔离性,否则事务胡乱提交会产生问题的,就需要使用非单例。比如:

  1. Connection
  2. SqlSession | Session
  3. Struts2 ACtion


好了最后,我们再回到最初的问题,spring中的Controller是单例的么? 答案是肯定的,因为Controller也是spring管理的一个Bean, 默认就是单例的。那继续提问, Controller是线程安全的么, 其实并不是,由于单例的模式,就会被多个线程同时使用,所以我们要尽量避免在Controller中定义成员变量,以免引发线程安全问题。

好了本篇文章就介绍到这里。喜欢的话,收藏加关注,学习不迷路。


目录
相关文章
|
1月前
|
安全 Java 开发者
Spring容器中的bean是线程安全的吗?
Spring容器中的bean默认为单例模式,多线程环境下若操作共享成员变量,易引发线程安全问题。Spring未对单例bean做线程安全处理,需开发者自行解决。通常,Spring bean(如Controller、Service、Dao)无状态变化,故多为线程安全。若涉及线程安全问题,可通过编码或设置bean作用域为prototype解决。
34 1
|
4月前
|
Java Spring
spring多线程实现+合理设置最大线程数和核心线程数
本文介绍了手动设置线程池时的最大线程数和核心线程数配置方法,建议根据CPU核数及程序类型(CPU密集型或IO密集型)来合理设定。对于IO密集型,核心线程数设为CPU核数的两倍;CPU密集型则设为CPU核数加一。此外,还讨论了`maxPoolSize`、`keepAliveTime`、`allowCoreThreadTimeout`和`queueCapacity`等参数的设置策略,以确保线程池高效稳定运行。
410 10
spring多线程实现+合理设置最大线程数和核心线程数
|
8月前
|
安全 Java Spring
Spring框架中的单例Bean是线程安全的吗?
Spring框架中的单例Bean是线程安全的吗?
97 1
|
6月前
|
Java Spring
spring boot 中默认最大线程连接数,线程池数配置查看
spring boot 中默认最大线程连接数,线程池数配置查看
408 4
|
6月前
|
Java Spring 容器
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
Spring boot 自定义ThreadPoolTaskExecutor 线程池并进行异步操作
297 3
|
5月前
|
安全 Java C#
Spring创建的单例对象,存在线程安全问题吗?
Spring框架提供了多种Bean作用域,包括单例(Singleton)、原型(Prototype)、请求(Request)、会话(Session)、全局会话(GlobalSession)等。单例是默认作用域,保证每个Spring容器中只有一个Bean实例;原型作用域则每次请求都会创建一个新的Bean实例;请求和会话作用域分别与HTTP请求和会话绑定,在Web应用中有效。 单例Bean在多线程环境中可能面临线程安全问题,Spring容器虽然确保Bean的创建过程是线程安全的,但Bean的使用安全性需开发者自行保证。保持Bean无状态是最简单的线程安全策略;
|
6月前
|
安全 Java 数据库连接
Spring Boot 优雅关机时异步线程安全优化
Spring Boot 优雅关机时异步线程安全优化
148 1
|
7月前
|
Java API Spring
Spring对多线程支持
Spring对多线程支持
|
6月前
|
Java BI 调度
在Spring Boot中实现多线程任务调度
在Spring Boot中实现多线程任务调度
|
7月前
|
监控 安全 Java
Spring Boot优雅Shutdown时异步线程安全优化
Spring Boot优雅Shutdown时异步线程安全优化