Spring学习(五)bean装配详解之 【XML方式配置】
本文借鑒:Spring學(xué)習(xí)(特此感謝!)
一、配置Bean的方式及選擇
配置方式
- 在 XML 文件中顯式配置
- 在 Java 的接口和類中實(shí)現(xiàn)配置
- 隱式 Bean 的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配原則
方式選擇的原則
最優(yōu)先:通過隱式 Bean 的發(fā)現(xiàn)機(jī)制和自動(dòng)裝配的原則。
基于約定優(yōu)于配置的原則,這種方式應(yīng)該是最優(yōu)先的
- 好處:減少程序開發(fā)者的決定權(quán),簡(jiǎn)單又不失靈活。
其次:Java 接口和類中配置實(shí)現(xiàn)配置
在沒有辦法使用自動(dòng)裝配原則的情況下應(yīng)該優(yōu)先考慮此類方法
- 好處:避免 XML 配置的泛濫,也更為容易。
- 典型場(chǎng)景:一個(gè)父類有多個(gè)子類,比如學(xué)生類有兩個(gè)子類,一個(gè)男學(xué)生類和女學(xué)生類,通過 IoC 容器初始化一個(gè)學(xué)生類,容器將無法知道使用哪個(gè)子類去初始化,這個(gè)時(shí)候可以使用 Java 的注解配置去指定。
最后:XML 方式配置
在上述方法都無法使用的情況下,那么也只能選擇 XML 配置的方式。
好處:簡(jiǎn)單易懂(當(dāng)然,特別是對(duì)于初學(xué)者)
典型場(chǎng)景:當(dāng)使用第三方類的時(shí)候,有些類并不是我們開發(fā)的,我們無法修改里面的代碼,這個(gè)時(shí)候就通過 XML 的方式配置使用了。
二、通過 XML 配置裝配 Bean
1、XML配置前言
使用 XML 裝配 Bean 需要定義對(duì)應(yīng)的 XML,這里需要引入對(duì)應(yīng)的 XML 模式(XSD)文件,這些文件會(huì)定義配置 Spring Bean 的一些元素,當(dāng)我們?cè)?IDEA 中創(chuàng)建 XML 文件時(shí),會(huì)有友好的提示:
一個(gè)簡(jiǎn)單的 XML 配置文件如下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>這就只是一個(gè)格式文件,引入了一個(gè) beans 的定義,引入了 xsd 文件,它是一個(gè)根元素,這樣它所定義的元素將可以定義對(duì)應(yīng)的 Spring Bean。
2、裝配簡(jiǎn)易值
先來一個(gè)最簡(jiǎn)單的裝配:
<bean id="c" class="pojo.Category"><property name="name" value="測(cè)試" /> </bean>簡(jiǎn)單解釋一下:
?id?屬性是 Spring 能找到當(dāng)前 Bean 的一個(gè)依賴的編號(hào),遵守 XML 語法的 ID 唯一性約束。必須以字母開頭,可以使用字母、數(shù)字、連字符、下劃線、句號(hào)、冒號(hào),不能以/開頭。
???name?屬性也可以定義 bean 元素的名稱,能以逗號(hào)或空格隔開起多個(gè)別名,并且可以使用很多的特殊字符,比如在 Spring 和 Spring MVC 的整合中,就得使用?name?屬性來定義 bean 的名稱,并且使用?/開頭。
?class?屬性顯然就是一個(gè)類的全限定名
?property?元素是定義類的屬性,其中的?name?屬性定義的是屬性的名稱,而?value?是它的值。
?
PS:?從 Spring 3.1 開始,id?屬性也可以是 String 類型了,也就是說?id?屬性也可以使用?/?開頭,而 bean 元素的 id 的唯一性由容器負(fù)責(zé)檢查。
PS:如果?id?和?name?屬性都沒有聲明的話,那么 Spring 將會(huì)采用?“全限定名#{number}”?的格式生成編號(hào)。 例如這里,如果沒有聲明 “id="c"” 的話,那么 Spring 為其生成的編號(hào)就是是“pojo.Category#0”,當(dāng)它第二次聲明沒有?id?屬性的 Bean 時(shí),編號(hào)就是 “pojo.Category#1”,以此類推。
這樣的定義很簡(jiǎn)單,但是有時(shí)候需要注入一些自定義的類,比如之前飲品店的例子,JuickMaker 需要用戶提供原料信息才能完成 juice 的制作:
<!-- 配置 srouce 原料 --> <bean name="source" class="pojo.Source"><property name="fruit" value="橙子"/><property name="sugar" value="多糖"/><property name="size" value="超大杯"/> </bean><bean name="juickMaker" class="pojo.JuiceMaker"><!-- 注入上面配置的id為srouce的Srouce對(duì)象 --><property name="source" ref="source"/> </bean>這里先定義了一個(gè)?name?為 source 的 Bean,然后再制造器中通過?ref?屬性去引用對(duì)應(yīng)的 Bean,而 source 正是之前定義的 Bean 的?name?,這樣就可以相互引用了。
?ref 引用對(duì)象
3、裝配集合
有些時(shí)候我們需要裝配一些復(fù)雜的東西,比如 Set、Map、List、Array 和 Properties 等,為此我們?cè)?Packge【pojo】下新建一個(gè) ComplexAssembly 類:
package pojo;import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set;public class ComplexAssembly {private Long id;private List<String> list;private Map<String, String> map;private Properties properties;private Set<String> set;private String[] array;/* setter and getter */ }這個(gè) Bean 沒有任何的實(shí)際意義,只是為了介紹如何裝配這些常用的集合類:
<bean id="complexAssembly" class="pojo.ComplexAssembly"><!-- 裝配Long類型的id --><property name="id" value="1"/><!-- 裝配List類型的list --><property name="list"><list><value>value-list-1</value><value>value-list-2</value><value>value-list-3</value></list></property><!-- 裝配Map類型的map --><property name="map"><map><entry key="key1" value="value-key-1"/><entry key="key2" value="value-key-2"/><entry key="key3" value="value-key-2"/></map></property><!-- 裝配Properties類型的properties --><property name="properties"><props><prop key="prop1">value-prop-1</prop><prop key="prop2">value-prop-2</prop><prop key="prop3">value-prop-3</prop></props></property><!-- 裝配Set類型的set --><property name="set"><set><value>value-set-1</value><value>value-set-2</value><value>value-set-3</value></set></property><!-- 裝配String[]類型的array --><property name="array"><array><value>value-array-1</value><value>value-array-2</value><value>value-array-3</value></array></property> </bean>總結(jié):
- List 屬性為對(duì)應(yīng)的 <list> 元素進(jìn)行裝配,然后通過多個(gè) <value> 元素設(shè)值
- Map 屬性為對(duì)應(yīng)的 <map> 元素進(jìn)行裝配,然后通過多個(gè) <entry> 元素設(shè)值,只是 entry 包含一個(gè)鍵值對(duì)(key-value)的設(shè)置
- Properties 屬性為對(duì)應(yīng)的 <properties> 元素進(jìn)行裝配,通過多個(gè) <property> 元素設(shè)值,只是 properties 元素有一個(gè)必填屬性 key ,然后可以設(shè)置值
- Set 屬性為對(duì)應(yīng)的 <set> 元素進(jìn)行裝配,然后通過多個(gè) <value> 元素設(shè)值
- 對(duì)于數(shù)組而言,可以使用 <array> 設(shè)置值,然后通過多個(gè) <value> 元素設(shè)值。
上面看到了對(duì)簡(jiǎn)單 String 類型的各個(gè)集合的裝載,但是有些時(shí)候可能需要更為復(fù)雜的裝載,比如一個(gè) List 可以是一個(gè)系列類的對(duì)象,為此需要定義注入的相關(guān)信息,其實(shí)跟上面的配置沒什么兩樣,只不過加入了 ref 這一個(gè)屬性而已。
集合注入總結(jié):
- List 屬性使用 <list> 元素定義注入,使用多個(gè) <ref> 元素的 Bean 屬性去引用之前定義好的 Bean
- Map 屬性使用?<map>?元素定義注入,使用多個(gè)?<entry>?元素的?key-ref?屬性去引用之前定義好的 Bean 作為鍵,而用?value-ref?屬性引用之前定義好的 Bean 作為值
- Set 屬性使用?<set>?元素定義注入,使用多個(gè)?<ref>?元素的?bean?去引用之前定義好的 Bean
4、命名空間裝配
除了上述的配置之外, Spring 還提供了對(duì)應(yīng)的命名空間的定義,只是在使用命名空間的時(shí)候要先引入對(duì)應(yīng)的命名空間和 XML 模式(XSD)文件。
c-命名空間(constructor,配置構(gòu)造器的參數(shù))
c-命名空間是在 Spring 3.0 中引入的,它是在 XML 中更為簡(jiǎn)潔地描述構(gòu)造器參數(shù)的方式,要使用它的話,必須要在 XML 的頂部聲明其模式:
PS:是通過構(gòu)造器參數(shù)的方式
現(xiàn)在假設(shè)我們現(xiàn)在有這么一個(gè)類:
package pojo;public class Student {int id;String name;public Student(int id, String name) {this.id = id;this.name = name;}// setter and getter }在 c-命名空間和模式聲明之后,我們就可以使用它來聲明構(gòu)造器參數(shù)了:
<!-- 引入 c-命名空間之前 --> <bean name="student1" class="pojo.Student"><constructor-arg name="id" value="1" /><constructor-arg name="name" value="學(xué)生1"/> </bean><!-- 引入 c-命名空間之后 --> <bean name="student2" class="pojo.Student"c:id="2" c:name="學(xué)生2"/>c-命名空間屬性名以 “c:” 開頭,也就是命名空間的前綴。接下來就是要裝配的構(gòu)造器參數(shù)名,在此之后如果需要注入對(duì)象的話則要跟上?-ref(如c:card-ref="idCard1",則對(duì) card 這個(gè)構(gòu)造器參數(shù)注入之前配置的名為 idCard1 的 bean)
很顯然,使用 c-命名空間屬性要比使用?<constructor-arg>?元素精簡(jiǎn),并且會(huì)直接引用構(gòu)造器之中參數(shù)的名稱,這有利于我們使用的安全性。
我們有另外一種替代方式:
<bean name="student2" class="pojo.Student" c:_0="3" c:_1="學(xué)生3"/>我們將參數(shù)的名稱替換成了 “0” 和 “1” ,也就是參數(shù)的索引。因?yàn)樵?XML 中不允許數(shù)字作為屬性的第一個(gè)字符,因此必須要添加一個(gè)下劃線來作為前綴。
p-命名空間(property,配置構(gòu)造器的參數(shù))
c-命名空間通過構(gòu)造器注入的方式來配置 bean,p-命名空間則是用setter的注入方式來配置 bean ,同樣的,我們需要引入聲明:
? 然后我們就可以通過 p-命名空間來設(shè)置屬性:
<!-- 引入p-命名空間之前 --> <bean name="student1" class="pojo.Student"><property name="id" value="1" /><property name="name" value="學(xué)生1"/> </bean><!-- 引入p-命名空間之后 --> <bean name="student2" class="pojo.Student" p:id="2" p:name="學(xué)生2"/>我們需要先刪掉 Student 類中的構(gòu)造函數(shù),不然 XML 約束會(huì)提示我們配置?<constructor-arg>?元素。
同樣的,如果屬性需要注入其他 Bean 的話也可以在后面跟上?-ref:
<bean name="student2" class="pojo.Student" p:id="2" p:name="學(xué)生2" p:cdCard-ref="cdCard1"/>util-命名空間
工具類的命名空間,可以簡(jiǎn)化集合類元素的配置,同樣的我們需要引入其聲明(無需擔(dān)心怎么聲明的問題,IDEA會(huì)有很友好的提示):
我們來看看引入前后的變化:?
<!-- 引入util-命名空間之前 --> <property name="list"><list><ref bean="bean1"/><ref bean="bean2"/></list> </property><!-- 引入util-命名空間之后 --> <util:list id="list"><ref bean="bean1"/><ref bean="bean2"/> </util:list>下表提供了 util-命名空間提供的所有元素:
5、引入其他配置文件
在實(shí)際開發(fā)中,隨著應(yīng)用程序規(guī)模的增加,系統(tǒng)中?<bean>?元素配置的數(shù)量也會(huì)大大增加,導(dǎo)致 applicationContext.xml 配置文件變得非常臃腫難以維護(hù)。
解決方案
讓 applicationContext.xml 文件包含其他配置文件即可 使用 <import> 元素引入其他配置文件
【1】在【src】文件下新建一個(gè) bean.xml 文件,寫好基礎(chǔ)的約束,把 applicationContext.xml 文件中配置的 <bean> 元素復(fù)制進(jìn)去
【2】在 applicationContext.xml 文件中寫入
<import resource="bean.xml" />【3】運(yùn)行測(cè)試代碼,仍然能正確獲取到 bean
轉(zhuǎn)載于:https://www.cnblogs.com/riches/p/11520090.html
總結(jié)
以上是生活随笔為你收集整理的Spring学习(五)bean装配详解之 【XML方式配置】的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 终端链接操作redis
- 下一篇: Java8 時間API