Spring(三)屬性配置細節

weixin_33912445發表於2018-06-24

一、字面值

字面值:可用字串表示的值,可以通過 <value> 元素標籤或 value 屬性進行注入。

基本資料型別及其封裝類、String 等型別都可以採取字面值注入的方式

若字面值中包含特殊字元,可以使用 <![CDATA[]]> 把字面值包裹起來。

2058461-0fb915f3c1e86674.png
2058461-ca7884ce9a694359.png

二、引用其它 Bean

組成應用程式的 Bean 經常需要相互協作以完成應用程式的功能. 要使 Bean 能夠相互訪問, 就必須在 Bean 配置檔案中指定對 Bean 的引用

在 Bean 的配置檔案中, 可以通過 <ref> 元素或 ref 屬性為 Bean 的屬性或構造器引數指定對 Bean 的引用.

也可以在屬性或構造器裡包含 Bean 的宣告, 這樣的 Bean 稱為內部 Bean

(1)通過ref屬性引用Bean

2058461-96108f95b00a611f.png
2058461-d0ae310205199ba0.png

(2)內部Bean

當 Bean 例項僅僅給一個特定的屬性使用時, 可以將其宣告為內部 Bean. 內部 Bean 宣告直接包含在或 元素裡, 不需要設定任何 id 或 name 屬性

內部 Bean 不能使用在任何其他地方

2058461-08c070523f71a236.png
2058461-bfbb92191bbf3e44.png

三、注入引數詳解:null 值和級聯屬性

可以使用專用的 <null/> 元素標籤為 Bean 的字串或其它物件型別的屬性注入 null 值

Spring 支援級聯屬性的配置。

(1)<null/>

2058461-a69da4d9b209e452.png
2058461-bad55d07128cea7f.png
<

(2)級聯屬性的配置

2058461-f675136b9234a2c3.png

四、集合屬性

在 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 屬性.

(1)list

2058461-04628db678246fc9.png


2058461-81f01932bb8b7208.png
2058461-43a379e9ff0ce82e.png

(2)map

2058461-a7d77ecf647feb13.png
2058461-8bc6c4d14bc6b403.png
2058461-b5c824f37be62255.png

(3)Properties

2058461-22859c2cac0e8b48.png
2058461-bd9a74bfce72777c.png
2058461-a74f4c2025eeaf8e.png

五、使用 utility scheme 定義集合

使用基本的集合標籤定義集合時, 不能將集合作為獨立的 Bean 定義, 導致其他 Bean 無法引用該集合, 所以無法在不同 Bean 之間共享集合.

可以使用 util schema 裡的集合標籤定義獨立的集合 Bean. 需要注意的是, 必須在 <beans> 根元素裡新增 util schema 定義

2058461-58b9fada2157b1dc.png
2058461-d531f7002baf32d3.png
2058461-81f00704d152f503.png

六、使用 p 名稱空間

為了簡化 XML 檔案的配置,越來越多的 XML 檔案採用屬性而非子元素配置資訊。Spring 從 2.5 版本開始引入了一個新的 p 名稱空間,可以通過 <bean> 元素屬性的方式配置 Bean 的屬性。

使用 p 名稱空間後,基於 XML 的配置方式將進一步簡化

2058461-fa0885241a37cb5b.png
2058461-556d579d3857fab1.png
2058461-3f5029985bb21420.png

七、XML 配置裡的 Bean 自動裝配

Spring IOC 容器可以自動裝配 Bean. 需要做的僅僅是在 的 autowire 屬性裡指定自動裝配的模式

byType(根據型別自動裝配): 若 IOC 容器中有多個與目標 Bean 型別一致的 Bean. 在這種情況下, Spring 將無法判定哪個 Bean 最合適該屬性, 所以不能執行自動裝配.

byName(根據名稱自動裝配): 必須將目標 Bean 的名稱和屬性名設定的完全相同.

constructor(通過構造器自動裝配): 當 Bean 中存在多個構造器時, 此種自動裝配方式將會很複雜. 不推薦使用

(1)在沒有使用自動裝配

2058461-774e5f78600dec1d.png
2058461-737b43993b4b1485.png
2058461-f255025174414532.png
2058461-b9a38b9ad8ee4a6e.png
2058461-7268277ad3c25086.png

(2)使用自動裝配

2058461-4045f1f7a57b0282.png

得到的輸出一樣

byName根據bean的名字和當前bean的setter風格的屬性名自動裝配,若有匹配的則進行自動裝配,若沒有匹配的,則不裝配。

2058461-22aee062bb4b3f4f.png
2058461-425c76701843ec62.png

byType根據bean的型別和當前Bean的屬性的型別進行自動裝配

2058461-0706f0c53f0153c9.png
2058461-3fbda7a409f53a54.png

若IOC容器中有1個以上的型別匹配的bean,則拋異常

2058461-8c93b26b995f0515.png
2058461-06eb3235f1365ffd.png

八、XML 配置裡的 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

2058461-3eb3f4d92dc83638.png
2058461-8282281c59be542d.png

第一個bean設定的abstract 屬性為 true,這樣的bean不能被IOC容器例項化,只用來被繼承配置

2058461-ea9e63040a090e41.png
2058461-98485affc8354a23.png

忽略父 Bean 的 class 屬性, 讓子 Bean 指定自己的類

2058461-4f915d2ec12fd191.png
2058461-4c6b578996c54655.png
2058461-2e4b51595fe4c85f.png

十、依賴 Bean 配置

Spring 允許使用者通過 depends-on 屬性設定 Bean 前置依賴的Bean,前置依賴的 Bean 會在本 Bean 例項化之前建立好

如果前置依賴於多個 Bean,則可以通過逗號,空格或的方式配置 Bean 的名稱

2058461-ec88bff7f3749f14.png

十一、Bean 的作用域

在 Spring 中, 可以在 <bean> 元素的 scope 屬性裡設定 Bean 的作用域.

預設情況下, Spring 只為每個在 IOC 容器裡宣告的 Bean 建立唯一一個例項, 整個 IOC 容器範圍內都能共享該例項:所有後續的 getBean() 呼叫和 Bean 引用都將返回這個唯一的 Bean 例項.該作用域被稱為 singleton, 它是所有 Bean 的預設作用域.

2058461-7739cd5de269ddc7.png

(1)singleton

2058461-19878e5a99f34c2f.png
2058461-af2d1e2f9cecbcea.png

(2)prototype

2058461-fd9f2abcc11a3ccd.png
2058461-82f332eee7a2ac08.png
2058461-d671d35d2495dfda.png

十二、使用外部屬性檔案

在配置檔案裡配置 Bean 時, 有時需要在 Bean 的配置裡混入系統部署的細節資訊(例如: 檔案路徑, 資料來源配置資訊等). 而這些部署細節實際上需要和 Bean 配置相分離

Spring 提供了一個 PropertyPlaceholderConfigurer 的 BeanFactory 後置處理器, 這個處理器允許使用者將 Bean 配置的部分內容外移到屬性檔案中. 可以在 Bean 配置檔案裡使用形式為 ${var} 的變數, PropertyPlaceholderConfigurer 從屬性檔案里載入屬性, 並使用這些屬性來替換變數.

Spring 還允許在屬性檔案中使用 ${propName},以實現屬性之間的相互引用。

方式一:

(1)匯入c3p0和MySQL驅動包

2058461-32bad868e985e913.png

(2)設定使用者名稱,密碼,驅動類,和資料庫的地址

2058461-3069327fa4e29285.png

(3)獲取資料庫的連線

2058461-934738903f523113.png

方式二:

(4)db.properties

2058461-b234e50d0a48e033.png

(5)匯入屬性檔案,使用外部屬性檔案的屬性

2058461-b0c63d4bfe33c996.png

(6)資料庫連線正常。

十三、Spring表示式語言:SpEL

Spring 表示式語言(簡稱SpEL):是一個支援執行時查詢和操作物件圖的強大的表示式語言。

語法類似於 EL:SpEL 使用 #{…} 作為定界符,所有在大框號中的字元都將被認為是 SpEL

SpEL 為 bean 的屬性進行動態賦值提供了便利

通過 SpEL 可以實現:

①、通過 bean 的 id 對 bean 進行引用

②、呼叫方法以及引用物件中的屬性

③、計算表示式的值

④、正規表示式的匹配

2058461-ac00a24f571e5e24.png
2058461-0423e3ed9b84fcbc.png

十四、IOC 容器中 Bean 的生命週期方法

Spring IOC 容器可以管理 Bean 的生命週期, Spring 允許在 Bean 生命週期的特定點執行定製的任務.

Spring IOC 容器對 Bean 的生命週期進行管理的過程:

①、通過構造器或工廠方法建立 Bean 例項

②、為 Bean 的屬性設定值和對其他 Bean 的引用

③、呼叫 Bean 的初始化方法

④、Bean 可以使用了

⑤、當容器關閉時, 呼叫 Bean 的銷燬方法

在 Bean 的宣告裡設定 init-methoddestroy-method 屬性, 為 Bean 指定初始化和銷燬方法.

2058461-763c05ac96e49638.png
2058461-e20b4ce1fdf9f8dd.png
2058461-ebb65d8984aeb1eb.png

十五、建立 Bean 後置處理器

Bean 後置處理器允許在呼叫初始化方法前後對 Bean 進行額外的處理.

Bean 後置處理器對 IOC 容器裡的所有 Bean 例項逐一處理, 而非單一例項. 其典型應用是: 檢查 Bean 屬性的正確性或根據特定的標準更改 Bean 的屬性.

對Bean 後置處理器而言, 需要實現 BeanPostProcessor介面. 在初始化方法被呼叫前後, Spring 將把每個 Bean 例項分別傳遞給上述介面的以下兩個方法:

postProcessBeforeInitialization

postProcessAfterInitialization

新增 Bean 後置處理器後 Bean 的生命週期

Spring IOC 容器對 Bean 的生命週期進行管理的過程:

1、通過構造器或工廠方法建立 Bean 例項

2、為 Bean 的屬性設定值和對其他 Bean 的引用

3、將 Bean 例項傳遞給 Bean 後置處理器的 postProcessBeforeInitialization 方法

4、呼叫 Bean 的初始化方法

5、將 Bean 例項傳遞給 Bean 後置處理器的 postProcessAfterInitialization方法

6、Bean 可以使用了

7、當容器關閉時, 呼叫 Bean 的銷燬方法

2058461-44538aec4a4829b4.png
2058461-cb87a0a5e7f74f77.png
2058461-0a17a03b0e839995.png

十六、通過呼叫靜態工廠方法建立 Bean

呼叫靜態工廠方法建立 Bean是將物件建立的過程封裝到靜態方法中. 當客戶端需要物件時, 只需要簡單地呼叫靜態方法, 而不同關心建立物件的細節.

要宣告通過靜態方法建立的 Bean, 需要在 Bean 的 class 屬性裡指定擁有該工廠的方法的類, 同時在 factory-method 屬性裡指定工廠方法的名稱. 最後, 使用 <constrctor-arg> 元素為該方法傳遞方法引數.

(1)Car.java

2058461-001ec4794426619a.png

(2)建立靜態工廠方法

2058461-751e3392c39f1c70.png

(3)通過靜態方法來配置Bean

class屬性:指向靜態工廠方法的全類名

factory-method:指向靜態工廠方法的名字

constructor-arg:如果工廠方法需要傳入引數,則使用constructor-arg來配置引數

2058461-e539eeb9d27069bf.png

(4)測試一下

2058461-65345f3164d3e19f.png

十七、通過呼叫例項工廠方法建立 Bean

例項工廠方法: 將物件的建立過程封裝到另外一個物件例項的方法裡. 當客戶端需要請求物件時, 只需要簡單的呼叫該例項方法而不需要關心物件的建立細節.

要宣告通過例項工廠方法建立的 Bean

①、在 bean 的 factory-bean 屬性裡指定擁有該工廠方法的 Bean

②、在 factory-method 屬性裡指定該工廠方法的名稱

③、使用 construtor-arg 元素為工廠方法傳遞方法引數

2058461-15008d9b605ca406.png
2058461-afd50b38c227831b.png
2058461-0dc6c6bbe10590b0.png

十八、實現 FactoryBean 介面在 Spring IOC 容器中配置 Bean

Spring 中有兩種型別的 Bean, 一種是普通Bean, 另一種是工廠Bean, 即FactoryBean.

工廠 Bean 跟普通Bean不同, 其返回的物件不是指定類的一個例項, 其返回的是該工廠 Bean 的 getObject 方法所返回的物件

2058461-b45703a16fb0b5fc.png
2058461-8b988b34759ccb70.png
2058461-67ea65e6ed5eb19a.png

相關文章