springboot单例模式与线程安全

springboot 默认采用的是单例模式,若要使用原型模式,添加@Scope("prototype") 注解,该注解的作用是将该类变成多例模式。

 

在@RestController下,一般都是@AutoWired一些Service,由于这些Service都是单例,对于在Controller中调用他们的方法,由于方法在JVM中属于栈操作,对于每一个线程来说,栈都是独立的,所以是线程安全的。

然而

如果我们在controller或者service上定义了一个类的实例,如 private Company company = new Company(); 而在@RequestMapping方法中去用到了他, 这里就存在并发线程安全的问题

------------------------------------------

假如

若父类加了@Scope("prototype")注解,子类controller并没有加该注解,会怎样呢?该注解是否还有意义?

再比如,在service上加上@Scope("prototype")注解,但调用的controller没有加@Scope("prototype")注解,那么会出现什么样的结果呢?

先说父类上加了@Scope("prototype")注解,子类上没有加这种情况。结果是,同一子类继承的为同一父类,不同子类继承为不同父类。理解一下,很简单,因为springboot为单例模式,所以子类为单例,那么只有一个子类,父类肯定是一样的。所以,不同线程过来使用的为同一变量,就会有问题。

同理:在service上标注@Scope("prototype")注解,那在同一个controller里,该service还是同一个,也就是说还是单例的,在不同的controller里 是不同的。

 

解决方法:

1、在controller的类和子类上,在service上 都加上@Scope("prototype")注解。

这样做的好处是简单。坏处也同样明显,因为是多例的,那么就会产生大量的实体类,占用大量内存,若是回收不及时,有可能会出现内存溢出。

2、是将变量私有化,比如使用线程变量,对变量加锁等,技术上会复杂一些,而且调试不太好调试。说不定那些地方就会出现问题,毕竟是老代码。

3、将该类转换为拦截器,将变量放入request里,用的时候取出来。

转:https://blog.csdn.net/weixin_38342534/article/details/86690166

你可能感兴趣的:(java,web)