天天看點

Spring Bean的prototype無用的解決

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)
      

 這樣即使是在單例裡面使用,每次擷取多例對象也會拿到一個新的。