基礎
默認情況下变隔,Spring應用上下文中的bean都是單例击困,也就是說不管給定的bean被注入到其他bean多少次吮蛹,每次注入的都是同一個實例方妖。
Spring中定義的作用域:
- 單例(Singleton):整個應用中只創(chuàng)建bean的一個實例
- 原型(Prototype):每次注入或者通過Spring應用上下文獲取的時候狭魂,都會創(chuàng)建一個新的bean實例
- 會話(Session):在Web應用中,為每個會話創(chuàng)建一個bean實例
- 請求(Request):在Web應用中党觅,為每個請求創(chuàng)建一個bean實例
單例是默認作用域雌澄,如果定義其他的作用域,則需要使用@Scope注解杯瞻,它可以與@Component或者@Bean一起使用镐牺。如:
@Component
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class Notepad {……}
如果使用xml來配置,則可以在<bean>標簽的scope屬性中設置魁莉。
會話和請求作用域注入到單例作用域
當一個會話或者請求作用域的bean(BeanSession)要注入到單例作用域的bean(BeanSingle)中時睬涧,會出現(xiàn)一些問題:
- BeanSingle在Spring應用上下文加載的時候創(chuàng)建,此時Spring會試圖將BeanSession注入到BeanSingle中旗唁,而此時BeanSession還不存在(當有用戶進入系統(tǒng)畦浓,創(chuàng)建會話后才會被創(chuàng)建)。
- 系統(tǒng)中可能會存在多個BeanSession检疫,大多數(shù)情況下我們不希望注入一個固定的BeanSession到BeanSingle中讶请,而是當前Session中的那個。
為了解決這個問題屎媳,Spring不會將實際的BeanSession注入到BeanSingle中去夺溢,而是注入一個BeanSession的代理。這個代理會暴露出和BeanSession相同的方法烛谊,BeanSingle會認為它是一個普通的BeanSession风响。
@Scope注解有一個proxyMode屬性,用于配置代理丹禀。有兩種方式:
- ScopeProxyMode.INTERFACES状勤,這表明該代理會實現(xiàn)BeanSession接口,并將調(diào)用 委托給具體的實現(xiàn)bean湃崩。這種方法要求BeanSession是一個接口荧降。
- ScopeProxyMode.TARGET_CLASS接箫,這表明Spring會使用CGLib生成目標類的擴展的方式來創(chuàng)建代理攒读。這種方式適用于BeanSession是具體的類。
感謝您的閱讀辛友!
本賬號已經(jīng)不再更新薄扁,更多文章請移步我的個人博客https://www.zacharyjia.me