1. 程式人生 > >Spring學習筆記-Spring容器中的Bean

Spring學習筆記-Spring容器中的Bean

1.Spring容器中的Bean

從本質上來看Spring容器就是一個超級大工廠,Bean就是工廠的產品,能產生哪些產品是根據我們配置檔案的配置來的。對於我們開發者來說,使用Spring容器主要做兩件事:1,定義自己的Bean,2配置Bean。對於Spring框架來說,它的作用就是根據配置檔案建立Bean,並呼叫Bean的例項方法完成依賴注入——這就是所謂Ioc容器的本質。
其實Spring框架的本質就是通過XML配置來驅動Java程式碼,這樣把原本有Java程式碼管理的元件之間的耦合關係,提取到了XML中。這樣就方便了日後的升級和維護。

2.Bean的基本定義和Bean別名

元素是Spring容器的根元素,該元素可以指定如下屬性:
default-lazy-init:指定該元素下配置的所有預設的延遲行為。
default-merge:指定該元素下配置的所有預設的merge。
default-autowirt:指定該元素下配置的所有預設的自動裝配行為。
default-autowirt-candidates:指定該元素下所有預設是否是預設裝配的候選Bean。
default-init-method:指定該元素下所有預設的初始化方法。
default-destroy-method:指定該元素下所有預設的回收方法。
以上這些屬性也使用於元素,只不過是需要去掉default而已。如果和配置了相同的屬性,那麼屬性將會覆蓋屬性,也就說說一個相當於全域性變數,一個想定於區域性變數。

3.Spring容器Bean的作用域

當通過Spring容器建立Bean時,不僅可以完成Bean的初始化工作,還可以為Bean指定作用域。在Bean元素新增scope屬性即可配置Bean的作用域。Spring支援一下五種作用域:
1. singleton:單例模式,在整個Spring Ioc容器中,singleton作用域的Bean只會產生一個例項。
2. prototype:通過getBean()方法獲取Bean例項或向其他Bean注入Bean時,Spring Ioc容器都會新new一個Bean例項作為方法返回的Bean或注入的Bean例項。
3. request:對於一次HTTP請求,request作用域只產生一個Bean例項,請求結束時Bean例項將會銷燬。也就說兩次login請求,將會產生兩個userBean。每一次login請求多次呼叫userBean會得到同一個例項。只有在Web應用中使用Spring時,該作用域才有效。
4. session:對於一次HTTP會話,session作用域只產生一個Bean例項,session銷燬時Bean例項將會銷燬。也就是說使用者A和使用者B都請求了查詢操作,將會產生兩個queryBean例項。A使用者多個請求查詢操作,將會產生一個queryBean例項。只有在Web應用中使用Spring時,該作用域才有效。
5. global session:每個全域性的HTTP session對應一個bean例項。在典型的情況下,僅在使用porlet context的時候才有效。只有在Web應用中使用Spring時,該作用域才有效。(可以了理解成jsp的application內建物件作用範圍)

比較常用的是singleton和prototype作用域。對於singleton作用域的Bean,每次通過id獲取Bean都是同一個例項,由Spring負責跟蹤Bean的狀態,維護Bean宣告週期內的行為。對於prototype作用域的Bean,每個通過id獲取Bean都是一個新的Bean例項,Spring會通過new關鍵字建立這個Bean例項,Spring不負責管理維護Bean例項的狀態和行為。如果元素不指定scope屬性將會預設為singleton作用域。prototype作用域會增加系統的開銷,因為每次都需要建立一個物件(申請記憶體、銷燬例項、完成垃圾回收等工作)。singleton作用域的Bean一旦建立成功,就可以重複使用。因此,應該儘量避免使用prototype作用域。

4.配置依賴

Bean的依賴注入通常有兩種形式:
設值注入:通過元素驅動Spring容器呼叫setter方法來注入依賴的Bean。
構造注入:通過元素驅動Spring容器呼叫有引數(引數數元素配置)的建構函式。

BeanFactory和ApplicationContext容器例項化Bean的時機不同:前者是在需要Bean例項時,才會建立Bean。後者是在容器建立ApplicationContext例項時會預先初始化素有的singleton Bean。這樣的做法會在啟動Spring容器時增加系統的開銷,但是一旦建立了所有的singleton Bean,後續獲取Bean的相應會更快。BeanFactory不會在Spring容器啟時例項化Bean,如果Spring Bean 配置檔案有錯誤,會延遲到獲取Bean時才會丟擲,這也給系統帶來了不安全因素。如果我們沒有特殊需要,一般Java EE程式都會使用ApplicationContext作為Spring容器。總的來說:
1,BeanFactory和ApplicationFactory例項化Bean的機制不同。
2,一個是按需建立Bean,一個是啟動時建立所有singleton Bean。
3,如果Bean配置有錯誤,一個是在例項化時才會發現,一個是容器啟動時就會發現。

不是兩種注入方式中的那種注入,都需要為引數傳遞引數值。可以傳遞引數的型別就是java類中成員變數可以定義的型別。也就時我們可以通過兩種注入方法注入Bean例項、注入基本型別、數字、字串、List和Map。所以Spring允許通過以下元素為這兩種注入方法指定引數值:value、ref、bean、list、set、map和props。稍後會對每個元素進行詳細說明。

5.設定普通值

元素用於指定基本型別以及包裝類、String型別的引數值。Spring解析XML中配置的value,然後利用java.beans.PropertyEditor完成型別轉賬:從String型別轉換成對應的引數型別值。元素配置方法如下:
假設Person有個setColor(String color)方法。

        <bean id="person" class="com.ssh.zxy.chapter7_2_2.Person">
            <property name="color" value="黃色"></property>
        </bean>

也可以這樣配置:

        <bean id="person" class="com.ssh.zxy.chapter7_2_2.Person">
            <property name="color">
                <value>黃色</value>
            </property>
        </bean>

這兩種配置目的是一樣的,只不過是寫法不同而已。前者配置更簡潔,後者配置想的臃腫。同理也可這這樣配置value屬性,來為構造器注入字面量。

6.配置合作者Bean

將一個Bean注入到容器的其它Bean例項中,可以使用元素來完成。這裡就沒有什麼好說的了。配置如下:

        <bean id="person" class="com.ssh.zxy.chapter7_2_2.Person">
            <property name="axe" ref="axe"></property>
        </bean>

        <bean id="axe" class="com.ssh.zxy.chapter7_2_2.Axe"></bean>

7.使用自動裝配注入合作者bean

Spring能自動裝配Bean與Bean之間的依賴關係,即無需使用ref顯示的指定依賴的Bean的Id,而是由Spring容器自動查詢XML配置檔案內容,根據某種規則自動注入符合規則的Bean。

自動裝配可以降低XML配置的工作量,但是也降低了依賴關係的透明度和清晰性(我們還需要理解規則,然後肉眼去找符合規則Bean,想想就麻煩)。
autowire、default-autowire屬性可以接受如下值:
no:不適用自動裝配。Bean必須通過ref屬性來定義依賴的bean。
byName:根據setter方法名進行匹配。Spring容器會查詢配置內容中Bean ID名稱符合setter方法名稱去掉set,首字母變成小寫的。如果找到就注入呼叫Bean中。如果沒找到匹配的Bean就不進行任何注入。
byType:根據型別進行匹配。Spring容器會查詢配置內容中Bean型別與setter方法引數型別相同的就進行注入。如果找到多個將會丟擲異常。如果沒找到Bean就不會進行注入。byName是setter方法名與Bean id匹配的策略。byType是settter方法引數型別與Bean型別匹配的策略。

7.1 byName規則

7.2byType規則