在spring IOC容器的配置文件applicationContext.xml裏,有一些配置細節值得一提。咱們將一些問題歸結爲如下幾個專題。java
專題一:字面值問題mysql
配置的bean節點中的值,咱們提出一個概念——字面值。
spring
字面值:可用字符串表示的值.sql
字面值能夠經過 <value> 元素標籤或 value 屬性進行注入。數據庫
基本數據類型及其封裝類、String 等類型均可以採起字面值注入的方式數組
若字面值中包含特殊字符,可使用 <![CDATA[]]> 把字面值包裹起來。app
例如:(本文出自:http://my.oschina.net/happyBKs/blog/478074)eclipse
<?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"> <bean id="car_value_id" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg name="price1"> <value>200000</value> </constructor-arg> <constructor-arg name="name1"> <value><![CDATA[<BM>]]></value> </constructor-arg> </bean> <!-- 若是字面值包括特殊字符,能夠用<![CDATA[ ]]>括起來 --> </beans>
Car定義:ide
package com.happBKs.spring.iocaop.beans; public class Car { String name; double price; public String getName() { return name; } public void setName(String name) { this.name = name; } public double getPrice() { return price; } public void setPrice(double price) { this.price = price; } public Car() { super(); } public Car(String name1, double price1) { super(); this.name = name1; this.price = price1; } @Override public String toString() { return "Car [name=" + name + ", price=" + price + "]"; } }
測試代碼:工具
@Test public void test8() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 Car cBean=(Car)ctx.getBean("car_value_id"); //調用對象方法 System.out.println(cBean); }
結果輸出:
Car [name=<BM>, price=200000.0]
在上例中,屬性值可使用value子節點進行配置。
專題二:bean的屬性是另外一個bean
在bean類的定義中每每存在這樣的狀況, 另類的某個屬性是另外一個bean對象。這樣的狀況,要使得容器可以在自動生成相應對象,應該怎麼作的呢。
首先咱們定義一個Person類,每一個Person有一個Car類型屬性。
package com.happBKs.spring.iocaop.beans; public class Person { String username; Car userCar; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Car getUserCar() { return userCar; } public void setUserCar(Car userCar) { this.userCar = userCar; } public Person(String username, Car userCar) { super(); this.username = username; this.userCar = userCar; } public Person() { super(); } @Override public String toString() { return "Person [username=" + username + ", userCar=" + userCar + "]"; } }
容器配製文件:咱們使用property的ref屬性來引用屬性類型,即創建bean之間的引用關係。
<?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"> <bean id="car_id" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="500000"></constructor-arg> </bean> <bean id="caruser" class="com.happBKs.spring.iocaop.beans.Person"> <property name="username" value="HappyBKs"></property> <property name="userCar" ref="car_id"></property> </bean> </beans>
測試代碼:
@Test public void test9() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 Person pBean=(Person)ctx.getBean("caruser"); //調用對象方法 System.out.println(pBean); }
運行結果:
Person [username=HappyBKs, userCar=Car [name=BM, price=500000.0]]
組成應用程序的 Bean 常常須要相互協做以完成應用程序的功能. 要使 Bean 可以相互訪問, 就必須在 Bean 配置文件中指定對 Bean 的引用
在 Bean 的配置文件中, 能夠經過 <ref> 元素或 ref 屬性爲 Bean 的屬性或構造器參數指定對 Bean 的引用.
也就是說,剛纔的容器配製還能夠寫成:
<bean id="caruser" class="com.happBKs.spring.iocaop.beans.Person"> <property name="username" value="HappyBKs"></property> <property name="userCar"> <ref bean="car_id"/> </property> </bean>
也能夠在屬性或構造器裏包含 Bean 的聲明, 這樣的 Bean 稱爲內部 Bean。
如,上面的例子能夠寫成另外一種內部bean的形式。這種內部bean的形式,不用再有id屬性,由於它不可能被外部引用。
<bean id="caruserB" class="com.happBKs.spring.iocaop.beans.Person"> <property name="username" value="HappyBKs"></property> <property name="userCar"> <bean class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="450000" index="1"></constructor-arg> <constructor-arg value="Volvo" index="0"></constructor-arg> </bean> </property> </bean>
測試代碼:
@Test public void test10() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 Person pBean=(Person)ctx.getBean("caruserB"); //調用對象方法 System.out.println(pBean); }
輸出結果:
Person [username=HappyBKs, userCar=Car [name=Volvo, price=450000.0]]
當 Bean 實例僅僅給一個特定的屬性使用時, 能夠將其聲明爲內部 Bean. 內部 Bean 聲明直接包含在 <property> 或 <constructor-arg> 元素裏, 不須要設置任何 id 或 name 屬性。
內部 Bean 不能使用在任何其餘地方。
專題三:特殊注入參數:null 值
咱們有時須要將bean的某個屬性設置爲null,這在spring容器的配置文件裏面怎麼描述呢?
這就要用到一個特殊的標籤<null/>
<bean id="caruserB" class="com.happBKs.spring.iocaop.beans.Person"> <property name="username" value="HappyBKs"></property> <property name="userCar"> <bean class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="450000" index="1"></constructor-arg> <constructor-arg index="0"><null/></constructor-arg> </bean> </property> </bean>
運行剛纔的test10方法,輸出結果:
Person [username=HappyBKs, userCar=Car [name=null, price=450000.0]]
專題四:特殊注入參數:級聯屬性
另外一種bean中比較特殊的賦值是級聯屬性。什麼叫級聯屬性呢?其實你一看就明白了,就是對象的屬性子對象的屬性。
配置文件中配置bean的屬性時,property標籤不只能直接配置該bean對應的類自身的屬性,並且還能夠直接配置該類的屬性對象向的屬性,即級聯屬性。
<bean id="caruserC" class="com.happBKs.spring.iocaop.beans.Person"> <property name="username" value="HappyBKs"/> <property name="userCar" ref="car_id"/> <property name="userCar.price" value="350000"/> </bean>
測試代碼:
@Test public void test11() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 Person pBean=(Person)ctx.getBean("caruserC"); //調用對象方法 System.out.println(pBean); }
輸出結果:
Person [username=HappyBKs, userCar=Car [name=BM, price=350000.0]]
固然,若是配置的bean中前面用構造器注入,也能夠同時使用級聯屬性賦值。
<bean id="caruserC" class="com.happBKs.spring.iocaop.beans.Person"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="500000"></constructor-arg> <property name="userCar.price" value="350000"/> </bean>
可是有一個十分須要注意的問題:這裏的級聯屬性被賦值的前提是級聯屬性所屬的對象屬性已經被屬性注入或構造器注入賦值,不然會報異常。這一點與struts2不一樣,struts2這種狀況會爲級聯屬性所屬對象自動生成實例,而spring不行。
專題五:集合屬性
在類的屬性中每每又一些屬性是集合性質的類型,如List、Set、Map等,或者是一個數組類型。
在Spring中,這樣的類在容器中應該如何配置呢?
在 Spring中能夠經過一組內置的 xml 標籤(例如: <list>, <set> 或 <map>) 來配置集合屬性.
配置 java.util.List 類型的屬性, 須要指定 <list> 標籤, 在標籤裏包含一些元素. 這些標籤能夠經過 <value> 指定簡單的常量值, 經過 <ref> 指定對其餘 Bean 的引用. 經過<bean> 指定內置 Bean 定義. 經過 <null/> 指定空元素. 甚至能夠內嵌其餘集合。
數組的定義和 List 同樣, 都使用 <list>。
配置 java.util.Set 須要使用 <set> 標籤, 定義元素的方法與 List 同樣。
List集合屬性
那咱們如今來看一個List的例子。
咱們定義一個RichPerson類:它有一個userCars屬性是List類型。
package com.happBKs.spring.iocaop.beans; import java.util.List; public class RichPerson { String username; List<Car> userCars; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public List<Car> getUserCars() { return userCars; } public void setUserCars(List<Car> userCars) { this.userCars = userCars; } public RichPerson(String username, List<Car> userCars) { super(); this.username = username; this.userCars = userCars; } public RichPerson() { super(); } @Override public String toString() { return "RichPerson [username=" + username + ", userCars=" + userCars + "]"; } }
在applicationContext.xml中,配置以下信息:
咱們將對應userCars的property標籤里加入<list>標籤
在<list>標籤裏咱們逐個加入bean。
加入方法有多種,這裏使用了兩種:
一種是ref,引用外部的bean。如前三個單元的bean。
另外一種是本身定義內部bean,與前面介紹的內部bean相似。
<?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"> <bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="800000"></constructor-arg> </bean> <bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Volvo"></constructor-arg> <constructor-arg value="500000"></constructor-arg> </bean> <bean id="richPerson1" class="com.happBKs.spring.iocaop.beans.RichPerson"> <property name="username" value="HappyBKs" /> <property name="userCars"> <list> <ref bean="privateCar1" /> <ref bean="privateCar1" /> <ref bean="privateCar2" /> <bean id="privateCarSecret" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Tank"></constructor-arg> <constructor-arg value="100000000000"></constructor-arg> </bean> </list> </property> </bean> </beans>
測試方法:
@Test public void test12() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 RichPerson pBean=(RichPerson)ctx.getBean("richPerson1"); //調用對象方法 System.out.println(pBean); }
輸出結果:
RichPerson [username=HappyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Tank, price=1.0E11]]]
Map的集合屬性
咱們再看一個Map的集合屬性的例子。
package com.happBKs.spring.iocaop.beans; import java.util.Map; public class RichMapPerson { String username; Map<String,Car> userCars; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Map<String, Car> getUserCars() { return userCars; } public void setUserCars(Map<String, Car> userCars) { this.userCars = userCars; } public RichMapPerson(String username, Map<String, Car> userCars) { super(); this.username = username; this.userCars = userCars; } public RichMapPerson() { super(); } @Override public String toString() { return "RichMapPerson [username=" + username + ", userCars=" + userCars + "]"; } }
配置容器:
<?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"> <bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="800000"></constructor-arg> </bean> <bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Volvo"></constructor-arg> <constructor-arg value="500000"></constructor-arg> </bean> <bean id="richMapPerson1" class="com.happBKs.spring.iocaop.beans.RichMapPerson"> <property name="username" value="HappyBKs" /> <property name="userCars"> <map> <entry key="WorkCar" value-ref="privateCar1"></entry> <entry key="ShoppingCar" value-ref="privateCar2"></entry> </map> </property> </bean> </beans>
不過很惋惜的是entry貌似不支持內部bean的定義,即一下狀況是報錯的,提示不支持此處以bean開頭。
<bean id="richMapPerson1" class="com.happBKs.spring.iocaop.beans.RichMapPerson"> <property name="username" value="HappyBKs" /> <property name="userCars"> <map> <entry key="WorkCar" value-ref="privateCar1"></entry> <entry key="ShoppingCar" value-ref="privateCar2"></entry> <entry key="OXOXCar"> <value type="com.happBKs.spring.iocaop.beans.Car"> <property name="name" value="taxi"></property> <property name="price" value="50000"></property> </value> </entry> </map> </property> </bean>
回到剛纔,測試方法:
@Test public void test13() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 RichMapPerson pBean=(RichMapPerson)ctx.getBean("richMapPerson1"); //調用對象方法 System.out.println(pBean); }
運行結果:
RichMapPerson [username=HappyBKs, userCars={WorkCar=Car [name=BM, price=800000.0], ShoppingCar=Car [name=Volvo, price=500000.0]}]
Properties類的屬性
Properties類型其實能夠算Map類型的子類型:它是HashTable類型的子類噢!
如今咱們來定義一個bean,用來記錄數據庫配置信息:
package com.happBKs.spring.iocaop.beans; import java.util.Properties; public class DataSourceBean { Properties propertiesInfo; public Properties getPropertiesInfo() { return propertiesInfo; } public void setPropertiesInfo(Properties propertiesInfo) { this.propertiesInfo = propertiesInfo; } public DataSourceBean(Properties propertiesInfo) { super(); this.propertiesInfo = propertiesInfo; } public DataSourceBean() { super(); } @Override public String toString() { return "DataSourceBean [propertiesInfo=" + propertiesInfo + "]"; } }
spring IOC容器配置:
<bean id="DataSourceId" class="com.happBKs.spring.iocaop.beans.DataSourceBean"> <property name="propertiesInfo"> <props> <prop key="user">root</prop> <prop key="password"></prop> <prop key="jdbcUrl">jdbc:mysql:///test</prop> <prop key="driverClass">com.mysql.jdbc.Driver</prop> </props> </property> </bean>
測試方法:
@Test public void test14() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 DataSourceBean dBean=(DataSourceBean)ctx.getBean("DataSourceId"); //調用對象方法 System.out.println(dBean); }
輸出結果:
DataSourceBean [propertiesInfo={driverClass=com.mysql.jdbc.Driver, user=root, password=, jdbcUrl=jdbc:mysql:///test}]
集合類型能夠外置(使用 utility scheme 定義集合)
前面提到的這些集合屬性在spring ioc容器配置時,都是能夠做爲外部單元存在的,就像bean存在外部bean和內部bean同樣。
使用基本的集合標籤訂義集合時, 不能將集合做爲獨立的 Bean 定義, 致使其餘 Bean 沒法引用該集合, 因此沒法在不一樣 Bean 之間共享集合.
可使用 util schema 裏的集合標籤訂義獨立的集合 Bean. 須要注意的是, 必須在 <beans> 根元素裏添加 util schema 定義。
咱們以List爲例,看下面例子:
首先咱們須要給applicationContext.xml加入一個命名空間:
能夠用STS、eclipse的編輯工具選擇下面的NameSpace編輯視圖,直接勾選util命名空間。
配置文件Source以下:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="800000"></constructor-arg> </bean> <bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Volvo"></constructor-arg> <constructor-arg value="500000"></constructor-arg> </bean> <util:list id="carsList"> <ref bean="privateCar1" /> <ref bean="privateCar2" /> <bean class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Audi"></constructor-arg> <constructor-arg value="700000"></constructor-arg> </bean> </util:list> <bean id="richPerson2" class="com.happBKs.spring.iocaop.beans.RichPerson"> <property name="username" value="happyBKs"/> <property name="userCars" ref="carsList"></property> </bean> </beans>
除了util:list標籤,spring-util-4.1命名空間中還有其餘集合標籤:
輸出結果:
RichPerson [username=happyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Audi, price=700000.0]]]
專題六:方便的p命名空間
爲了簡化 XML 文件的配置,愈來愈多的 XML 文件採用屬性而非子元素配置信息。
Spring 從 2.5 版本開始引入了一個新的 p 命名空間,能夠經過 <bean> 元素屬性的方式配置 Bean 的屬性。
使用 p 命名空間後,基於 XML 的配置方式將進一步簡化
首先,咱們須要按照以前的方法導入命名空間。
以後,咱們在最後加入一個bean,id爲richPerson3,你發現依賴於p命名空間,如今這個bean只有一行了,十分簡潔。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd"> <bean id="privateCar1" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="BM"></constructor-arg> <constructor-arg value="800000"></constructor-arg> </bean> <bean id="privateCar2" class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Volvo"></constructor-arg> <constructor-arg value="500000"></constructor-arg> </bean> <util:list id="carsList"> <ref bean="privateCar1" /> <ref bean="privateCar2" /> <bean class="com.happBKs.spring.iocaop.beans.Car"> <constructor-arg value="Audi"></constructor-arg> <constructor-arg value="700000"></constructor-arg> </bean> </util:list> <bean id="richPerson3" class="com.happBKs.spring.iocaop.beans.RichPerson" p:username="happyBKs" p:userCars-ref="carsList"/> </beans>
測試方法:
@Test public void test16() { //建立spring IOC容器對象。ClassPathXmlApplicationContext表示配置文件在類路徑下,它是接口ApplicationContext的一個實現類。 ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml"); //從IOC容器中獲取Bean實例 RichPerson pBean=(RichPerson)ctx.getBean("richPerson3"); //調用對象方法 System.out.println(pBean); }
運行結果:
RichPerson [username=happyBKs, userCars=[Car [name=BM, price=800000.0], Car [name=Volvo, price=500000.0], Car [name=Audi, price=700000.0]]]