1. 程式人生 > >Spring中Bean定義、作用域、管理問題

Spring中Bean定義、作用域、管理問題

一、Bean的定義

<beans…/>元素是Spring配置檔案的根元素,<beans…/>元素可以包含多個<bean…/>子元素,每個<bean…/>元素可以定義一個Bean例項,每一個Bean對應Spring容器裡的一個Java例項定義Bean時通常需要指定兩個屬性。

  • Id:確定該Bean的唯一識別符號,容器對Bean管理、訪問、以及該Bean的依賴關係,都通過該屬性完成。Bean的id屬性在Spring容器中是唯一的。

  • Class:指定該Bean的具體實現類。注意這裡不能使介面。通常情況下,Spring會直接使用new關鍵字建立該Bean的例項,因此,這裡必須提供Bean實現類的類名。

Spring容器集中管理Bean的例項化,Bean例項可以通過BeanFactory的getBean(String beanid)方法得到。BeanFactory是一個工廠,程式只需要獲取BeanFactory引用,即可獲得Spring容器管理全部例項的引用。程式不需要與具體例項的實現過程耦合。大部分Java EE應用裡,應用在啟動時,會自動建立Spring容器,元件之間直接以依賴注入的方式耦合,甚至無須主動訪問Spring容器本身。

當我們在配置檔案中通過方法配置一個Bean時,這樣就需要該Bean實現類中必須有一個無參構造器。

二、容器中Bean的作用域

當通過Spring容器建立一個Bean例項時,不僅可以完成Bean例項的例項化,還可以為Bean指定特定的作用域。

Spring支援5種作用域:

  • Singleton:單例模式。在整個SpringIoC容器中,使用singleton定義的Bean將只有一個例項,這是預設的配置。
  • Prototype:原型模式。每次通過容器的getBean方法獲取prototype定義的Bean時,都將產生一個新的Bean例項。
  • request:對於每次HTTP請求,使用request定義的Bean都將產生一個新的例項,即每次HTTP請求都會產生不同的Bean例項。當然只有在WEB應用中使用Spring時,該作用域才真正有效。
  • session:對於每次HTTPSession,使用session定義的Bean都將產生一個新的例項時,即每次HTTP Session都將產生不同的Bean例項。同HTTP一樣,只有在WEB應用才會有效。
  • global session:每個全域性的HTTPSession對應一個Bean例項。僅在portlet Context的時候才有效。

比較常用的singleton和prototype。如果一個Bean例項被設定為singleton,那麼每次請求該Bean時都會獲得相同的例項。容器負責跟蹤Bean例項的狀態,負責維護Bean例項的生命週期行為。如果一個Bean例項被設定為prototype,那麼每次請求該di的Bean,Spring都會建立一個新的Bean例項返回給程式,在這種情況下,Spring容器僅僅使用new關鍵字建立Bean例項,一旦建立成功,容器將不會再跟蹤例項,也不會維護Bean例項的狀態。

如果我們不指定Bean的作用域,則Spring會預設使用singleton作用域。設定Bean的作用域是通過scope屬性來指定。可以接受Singleton、prototype、request、session、global session 5個值。

三、Spring中Bean的管理問題

首先,配置檔案中定義的bean並不是都在啟動時例項化。 < bean id=“accountService” class=“com.foo.DefaultAccountService” scope=“singleton”/> 注意bean有一個屬性scope,只有在scope沒有配置或配置為如上時,啟動時才例項化。(如果一個singleton的bean依賴一個prototype的bean,那麼這個prototype的bean在singleton的bean例項化時也會例項化。 如果定義為scope="prototype"那麼只有在這個bean被使用時,才例項化,而且每次都是一個新物件,多例。

其次,在配置檔案中宣告bean使得spring可以管理這些bean,比如宣告式事物功能,就需要你的bean在配置檔案中配置。在例項化時spring會為你宣告的bean生成一個代理物件,代理物件在呼叫bean的方法前後加上事務控制邏輯。 備註:spring管理bean這樣在bean初始化過程中,spring可以做很多事情,比如你寫一個pojo,spring通過配置就能讓他成為rmi,就是在例項化過程,對這個pojo做了更多的處理,不只是簡單的new一個物件出來。 在比如只有spring管理的bean才支援spring的AOP機制。可以使用Aspectj和spring整合,對非spring管理的bean施加AOP

再次,減少程式碼中依賴耦合。 同樣的在配置檔案中我們可以ref另外一個bean,這樣做又是為什麼呢?(我們同樣可以使用時new一個這個例項) 回答: 把依賴關係定義在配置檔案中。 不要再程式碼中表現依賴關係,這樣在依賴關係有變化的情況下,可以通過配置檔案的修改達到目的,而不需要修改程式碼。