spring 的bean預設是單例,這個用spring的人基本都知道。
如果需要多個執行個體,又要使用ioc怎麼辦呢?
當然是使用@Scope注解,指明ConfigurableBeanFactory.SCOPE_PROTOTYPE了。
/**
* Scope identifier for the standard singleton scope: "singleton".
* Custom scopes can be added via {@code registerScope}.
* @see #registerScope
*/
String SCOPE_SINGLETON = "singleton";
/**
* Scope identifier for the standard prototype scope: "prototype".
* Custom scopes can be added via {@code registerScope}.
* @see #registerScope
*/
String SCOPE_PROTOTYPE = "prototype";
但是在使用過程中 發現這樣依然是單例。
難道spring的注解不穩定還是我使用有誤?
首先推敲一下,為什麼我們擷取到的執行個體每次都一樣。
spring出問題是不太可能了,這麼常見的特性那麼多人都用呢。
如果給一個元件加上
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
每次請求它的執行個體,spring的确會給傳回一個新的。
問題是這個多例對象是被其他單例服務依賴的。
而單例服務初始化的時候,多例對象就已經被建立好了。當你去使用單例服務的時候,多例對象也不會被再次建立了。
那怎麼解決呢?
一個首先想到的方法當然是注入多個,就是寫多個@Autowired。
這樣的确可以。而且如果對單例服務寫多個,他們也是一樣的,隻有對多例的才行。
但是我們的服務絕大多數時候都不知道需要多少多例服務,服務是動态建立的。
是以另一種方法就是使用getBean方法:
@Autowired
private ApplicationContext applicationContext;
applicationContext.getBean()
隻要每次調用getBean就可以獲得一個新服務。
其實spring的@Scope注解提供了在單例服務裡使用多例對象的能力,它提供了一個代理字段
/**
* Specifies whether a component should be configured as a scoped proxy
* and if so, whether the proxy should be interface-based or subclass-based.
* <p>Defaults to {@link ScopedProxyMode#DEFAULT}, which typically indicates
* that no scoped proxy should be created unless a different default
* has been configured at the component-scan instruction level.
* <p>Analogous to {@code <aop:scoped-proxy/>} support in Spring XML.
* @see ScopedProxyMode
*/
ScopedProxyMode proxyMode() default ScopedProxyMode.DEFAULT;
預設是不使用代理建立。我們隻要把它改成使用代理即可:
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)
這樣即使是在單例裡面使用,每次擷取多例對象也會拿到一個新的。