我们知道Spring中的Bean默认都是单例的,也就是singleton。另外一个常用的是prototype(原型),可以通过它实现多例模式。但是请问,直接使用@Scope注解加上prototype直接就能实现多例吗?参考下面的代码:
MyService Bean:
1 |
|
MyController Bean:
1 |
|
上面定义了两个Bean,一个是服务,一个是控制器。我们把服务通过自动注入的方式注入控制器。
请问上面的实现方式可以确保实现多例模式吗?
有的朋友可能认为,我已经使用了@Scope(value="prototype")
,理当直接就是多例模式,每次访问/rest/me API的时候都能创建新的Bean,打印不同的结果。但是事实真的如此吗?
实际上看到的输出是:
1 | num:1次请求,com.xqtony.bean.scope.prototype.service.MyService@6bc394d2 |
实际上,并没有实现多例!我们的运行结果会发现,两次请求打印出来的结果是一样的。原因是什么?是因为我们没有指定ScopeProxyMode。
ScopeProxyMode的值有: Default, NO, TARGET_CLASS, INTERFACE。
如果希望在这个例子中实现多例,必须加上ScopeProxyMode.TARGET_CLASS
。
MyService Bean:
1 |
|
这时候会发现,service2和service一个是新创建了对象,另一个没有。
1 | num:0次请求, service没加 ScopeProxyModecom.xqtony.bean.scope.prototype.service.MyService@2a80117c |
为什么我们知道要使用TARGET_CLASS
呢?因为proxyMode的默认值是Default,而在源码中是这样描述的:
1 | /** |
可见在使用Prototype(原型)的时候,是不应该使用DEFAULT的。
完整的项目代码请参考我的代码仓库:
参考:
springboot中怎么获取多例(prototype)
spring的scope为prototype的bean的正确使用方法
原文链接: https://xqtony.github.io/2023/09/26/spring-bean-prototype-issue/
版权声明: 转载请注明出处.