Spring中的Bean配置
一.內容提要
- IOC & DI 概述
- 配置bean:
- 配置形式:基於XML文件的方式;基於注解的方式
- Bean的配置方式:通過全類名(反射)、通過工廠方法(靜態工廠方法 & 實例工廠方法)、FactoryBean
- IOC 容器 BeanFactory & ApplicationContext 概述
- 依賴注入的方式:屬性注入;構造器注入
- 注入屬性值細節
- 自動轉換
- bean 之間的關系:繼承;依賴
- bean 的作用域:singleton;prototype;WEB 環境作用域
- 使用外部屬性文件
- spEL
- IOC 容器中 Bean 的生命周期
- Spring 4.x 新特性:泛型依賴注入
二.IOC 和 DI
- IOC(Inversion of Control):其思想是反轉資源獲取的方向.傳統的資源查找方式要求組件向容器發起請求查找資源.作為回應,容器適時的返回資源.而應用了IOC之后,則是容器主動地講資源推給它所管理的組件,組件所要做的僅是選擇一種合適的方式來接受資源.這種行為也被稱為查找的被動形式.
- DI(Dependency Injection)一IOC的另一種表達方式:既組件以一些預先定義好的方式(例如:setter方法)接收來自如容器的資源注入.相對於IOC而言,這種表述更直接
三.在Spring的IOC容器里配置Bean
- 在xml文件中通過bean節點來配置bean
<!-- 通過全類名的方式來配置bean --> <bean id="helloWorld" class="com.yangxiao.spring.beans.HelloWorld"> </bean>
-
id:Bean的名稱
- 在IOC容器中必須是唯一的
- 若id沒有指定,Spring自動將權限定性類名作為Bean的名字
- id可以指定多個名字,名字之間可用逗號、分號、或空格分隔
四.Spring容器
- 在Spring IOC容器讀取Bean配置創建Bean實例之前,必須對它進行實例化,只有在容器實例化后,才可以從IOC容器里獲取Bean實例並使用.
- Spring提供了兩種類型的IOC容器實現
- BeanFactory IOC容器的基本實現
- ApplicationContext提供了更多的高級特性,是BeanFactory的子接口
- BeanFactory是Spring 框架的基礎設置,面向Spring本身;ApplicationContext面向使用 Spring框架的開發者,幾乎所有的應用場合都直接使用ApplicationContext而非底層的BeanFactory
- 無論使用何種方式,配置文件是相同的
五.ApplicationContext
- ApplicationContext的主要實現類:
- ClassPathXmlApplicationContext:從類路徑下加載配置文件
- FileSystemXmlApplicationContext:從文件系統中加載配置文件
- ConfigurableApplicationContext擴展於ApplicationContext,新增加兩個只主要方法:refresh()和close(),讓ApplicationContext具有啟動、刷新和關閉上下文的能力
- ApplicationContext在初始化上下文時就實例化所有單例的Bean
- WebApplicationContext是專門為WEB應用而准備的,它允許從相對於WEB根目錄的路徑中完成初始化工作
六.依賴注入的方式
- Spring支持3中依賴注入的方式
- 屬性注入
- 構造器注入
- 工廠方法注入(很少使用,不推薦)
屬性注入
- 屬性注入即通過setter 方法注入Bean 的屬性值或依賴的對象
- 屬性注入使用<property>元素,使用name屬性指定Bean的屬性名稱,value屬性或<value>子節點指定屬性值
- 屬性注入式實際應用中最常用的注入方式
構造方法注入
- 通過構造方法注入Bean 的屬性值或依賴的對象,它保證了Bean 實例在實例化后就可以使用.
- 構造器注入在<constructor-arg>元素里聲明屬性,<constructor-arg>中沒有那么屬性
字面值
- 字面值:可用字符串表示的值,可以通過<value>元素標簽或value屬性進行注入.
- 基本數據類型及其封裝類、String等類型都可以采取字面值注入的方式.
- 若字面值中含特殊字符,可以使用<![CDATA[]]>把字面值包裹起來
引用其它Bean
- 組成應用程序的Bean經常需要相互協作以完成應用程序的功能,要使Bean能夠相互訪問,就必須在Bean配置文件中指定對Bean的引用
- 在Bean的配置文件中,可以通過<ref>元素或ref屬性為Bean的屬性或構造器參數指定對Bean的引用
- 也可以在屬性或構造器里包含Bean的聲明,這樣的Bean稱為內部Bean.
注入參數詳解:null值和級聯屬性
- 可以使用專用的<null/>元素標簽為Bean的字符串或其它對象類型的屬性注入null值
- 和Strusts、Hibernate等框架一樣,Spring支持級聯屬性的配置.
集合屬性
- 在Spring中可以通過一組內置的xml標簽(例如:<list>,<set>或<map>)來配置集合屬性.
- 配置java.util.List類型的屬性,需要指定<list>標簽,在標簽里包含一些元素,這些標簽可以通過<value>指定簡單的常量值,通過<ref>指定對其他Bean的引用,通過<bean>指定內置Bean定義,通過<null/>指定空元素,甚至可以內嵌其他集合.
- 數組的定義和List一樣,都是用<list>
- 配置java.util.Set需要使用<set>標簽,定義元素的方法與List一樣
- Java.util.Map通過<map>標簽定義,<map>標簽里可以使用多個<entry>作為字標簽.每個條目包含一個鍵和一個值
- 必須在<key>標簽里定義鍵
- 因為鍵和值的類型沒有限制,所以可以自由地位它們指定<value>,<ref>,<bean>或<null>元素
- 可以將Map的鍵和值作為<entry>的屬性定義:簡單常量使用key和value來定義;Bean引用通過key-ref和value-ref屬性定義
- 使用<props>定義java.util.Properties,該標簽使用多個<prop>作為子標簽,每個<prop>標簽必須定義key屬性
使用utility scheme 定義集合
- 使用基本的集合標簽定義集合時,不能將集合作為獨立的Bean定義,導致其他Bean無法引用該集合,所以無法在不同Bean之間共享集合
- 可以使用util schema 里的幾個標簽定義獨立的集合Bean.需要注意的是,必須在<beans>根元素里添加util schema 定義
使用p命名空間
- 為了簡化XML文件的配置,越來越多的XML文件采用屬性而非子元素配置信息.
- Spring從2.5版本開始引入一個新的p命名空間,可以通過<bean>元素屬性的方式配置Bean的屬性.
- 使用p命名空間后,基於XML的配置方式將進一步簡化
七.自動裝配
XML配置里的 Bean 自動裝配
- SpringIOC 容器可以自動裝配Bean.需要做的僅僅是在<bean>的autowire屬性里指定自動裝配的模式
- byType(根據類型自動裝配):若IOC容器中有多個與目標Bean類型一致的Bean,在這種情況下,Spring將無法判定哪個Bean最合適該屬性,在這種情況下,Spring將無法判定哪個Bean最合適該屬性,所以不能執行自動裝配.
- byName(根據名稱自動裝配):必須將目標Bean的名稱和屬性設置的完全相同
- constructor(通過構造器自動裝配):當Bean中存在多個構造器時,此種自動裝配方式將會很復雜,不推薦使用.
自動裝配的缺點
- 在Bean配置文件里設置autowire屬性進行自動裝配將會裝配Bean的所有屬性,然而,若只希望裝配個別屬性時,autowire屬性就不夠靈活了.
- autowire屬性要么根據類型自動裝配,要么根據名稱自動裝配,不能兩者兼而有之.
- 一般情況下,在實際的項目中很少使用自動裝配功能,因為和自動裝配功能所帶來的好處比起來,明確清晰的配置文檔更有說服力一些.
八.繼承 Bean 配置
- Spring允許繼承 bean 的配置,被繼承的bean稱為父bean.繼承這個父 Bean 的 Bean 稱為子 Bean
- 子Bean 從父Bean 中繼承配置,包括Bean 的屬性配置
- 子Bean也可以覆蓋從父Bean 繼承過來的配置
- 父Bean可以作為配置模板,也可以作為Bean實例.若只想把父Bean作為模板,可以設置<bean>的abstract屬性為true,這樣Spring將不會實例化這個Bean
- 並不是<bean>元素里的所有屬性都會被繼承,比如:autowire,abstract等
- 也可以忽略父Bean 的 class 屬性,讓子Bean 指定自己的類,而共享相同的屬性配置,但此時abstract必須設為true
依賴Bean配置
- Spring允許用戶通過depends-on 屬性設定Bean前置依賴的Bean,前置依賴的Bean 會在本Bean 實例化之前創建好
- 如果前置依賴於多個Bean,則可以通過逗號,空格或的方式配置Bean 的名稱
九.使用外部屬性文件
- 在配置文件里配置Bean 時,有時需要在Bean 的配置混入系統部署的細節信息(例如:文件的路徑,數據源配置信息等),而這些部署細節實際上需要和Bean配置相分離
- Spring 提供了一下PropertyPlaceholderConfigurer的BeanFactory后置處理器,這個處理器允許用戶將Bean配置的部分內容外移到屬性文件中.可以在Bean配置文件里使用形式為${var}的變量,PropertyPlaceholderConfigurer從屬性文件里加載屬性,並使用這些屬性來替換變量.
- Spring還允許在屬性文件中使用${propName},以實現屬性之間的相互引用.
十.Spring表達式語言:SpEL
- Spring表達式語言(簡稱SpEL):是一個支持運行時查詢和操作對象圖的強大的表達式語言.
- 語法類似於EL:SpEL使用#{...}作為定界符,所有在大括號中的字符都將被認為是SpEL
- SpEL為bean 的屬性進行動態賦值提供了便利
- 通過SpEL可以實現:
- 通過bean 的id 對bean 進行引用
- 調用方法以及引用對象中的屬性
- 計算表達式的值
- 正則表達式的匹配