標籤:

Spring Bean作用域、懶載入和自動裝配

現在的Java工程的DI都是自動裝備,使用註解@Autowired與@Resource,現在談談兩者的關係。

兩者都可以寫在欄位或set方法上,如果不使用註解,那麼必須有set方法。

前者默認按類型裝配,默認情況下要求bean必須存在,否則拋出異常。如果允許不存在,那麼可寫為@Autowired(required=false) 。如果同一類型有多個bean,那麼聯合使用 @Qualifier("xxx")

後者默認按照名稱裝備,當註解寫在欄位上時,默認取欄位名進行按照名稱查找,如果註解寫在set方法上默認取屬性名進行裝配。如果安裝名稱不能找到bean,那麼會按照類型裝配。需要注意的是,如果name屬性被指定,那麼只能按照名稱來裝配,比如@Resource(name = "xxx")

那麼具體實現的原理是什麼呢?註解是一個標註作用,Spring會掃描bean相關的註解,發現之後利用反射技術來裝備。

Spring容器管理bean,不僅可以完成Bean的實例化,還可以為Bean指定特定的作用域.

singleton:單例模式,在整個Spring IoC容器中,使用singleton定義的Bean將只有一個實例(默認模式)

prototype:原型模式,每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean實例.

request:在一次HTTP請求中,一個bean定義對應一個實例;即每次HTTP請求將會有各自的bean實例, 它們依據某個bean定義創建而成。該作用域僅在基於web的Spring ApplicationContext情形下有效。

session:在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext情形下有效。

globalSession:在一個全局的HTTP Session中,一個bean定義對應一個實例。典型情況下,僅在使用portlet context的時候有效。該作用域僅在基於web的Spring ApplicationContext情形下有效

最常用的是singleton和prototype。根據經驗,對有狀態的bean應該使用prototype作用域,而對無狀態的bean則應該使用singleton作用域。常見一個singleton bean內包含一個prototype bean,這時候prototype bean應該如下定義:

@Component@Scope(value="prototype", proxyMode=ScopedProxyMode.TARGET_CLASS)public class Demo

這時的bean是一個CGLib生產的代理。如果該類有介面,也可使用延遲初始化

<bean id="lazy" class="com.foo.ExpensiveToCreateBean" lazy-init="true">

或者註解@Lazy。如果延遲初始化的bean在配置的某個地方被注入到了一個非延遲初始化singleton bean裡面,那麼這個bean不會被延遲初始化。

推薦閱讀:

史上最簡單的SpringCloud教程 | 第二篇:服務消費者(rest + ribbon)
Spring 數據訪問(DAO層) 總結
Spring核心技術原理-(1)為什麼要有Spring?
Spring探秘,妙用BeanPostProcessor
如何理解 ssh 三大框架?

TAG:Spring |