Spring Bean 配置細節
引用其它 Bean
•組成應用程式的 Bean 經常需要相互協作以完成應用程式的功能. 要使 Bean 能夠相互訪問, 就必須在 Bean 配置檔案中指定對 Bean 的引用
•在 Bean 的配置檔案中, 可以通過 <ref> 元素或 ref 屬性為 Bean 的屬性或構造器引數指定對 Bean 的引用.
如我們構造一個Person類
public class Person { private String name; private int age; private Car car; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public Car getCar() { return car; } public void setCar(Car car) { this.car = car; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", car=" + car + '}'; } }
在bean中通過ref建立bean之間的聯絡
<bean id="person" class="com.spring.Person"> <property name="name" value="Tom"></property> <property name="age" value="24"></property> <!--可以使用property 的ref 屬性建立bean之間的引用關係--> <property name="car" ref="car2"></property> </bean>
Person person = (Person) ctx.getBean("person");
System.out.println(person);
呼叫該bean可以看到程式輸出
Person{name='Tom', age=24, car=Car{brand='Baoma', corp='Tianjin', price=0.0, maxSpeed=200}}
•也可以在屬性或構造器裡包含 Bean 的宣告, 這樣的 Bean 稱為內部 Bean
<bean id="person" class="com.spring.Person"> <property name="name" value="Tom"></property> <property name="age" value="24"></property> <!--可以使用property 的ref 屬性建立bean之間的引用關係--> <!--<property name="car" ref="car2"></property>--> <!--使用內部bean--> <property name="car"> <bean class="com.spring.Car"> <constructor-arg value="Ford"></constructor-arg> <constructor-arg value="Changan"></constructor-arg> <constructor-arg value="200000"></constructor-arg> </bean> </property> </bean>
內部bean不能被外部引用,只能在內部使用
•當 Bean 例項僅僅給一個特定的屬性使用時, 可以將其宣告為內部 Bean. 內部 Bean 宣告直接包含在 <property> 或 <constructor-arg> 元素裡, 不需要設定任何 id 或 name 屬性
•內部 Bean 不能使用在任何其他地方
注入引數詳解:null 值和級聯屬性
•可以使用專用的 <null/> 元素標籤為 Bean 的字串或其它物件型別的屬性注入 null 值
•和 Struts、Hiberante 等框架一樣,Spring 支援級聯屬性的配置。
<bean id="person2" class="com.spring.Person">
<constructor-arg value="Jerry"></constructor-arg>
<constructor-arg value="25"></constructor-arg>
<!--<constructor-arg ref="car"></constructor-arg>-->
<!--測試賦值null-->
<constructor-arg><null></null></constructor-arg>
</bean>
用該方法,此時給person2這個物件賦的car值為null
Person{name='Jerry', age=25, car=null}
集合屬性
假設一個person擁有兩輛車,我們現在構造一個Person類,其屬性Car為list型別
package com.collection;
import java.util.List;
public class Person {
private String name;
private int age;
private List<Car> cars;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public List<Car> getCars() {
return cars;
}
public void setCars(List<Car> cars) {
this.cars = cars;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", cars=" + cars +
'}';
}
}
更改配置檔案
<!--測試如何配置集合屬性-->
<bean id="person3" class="com.collection.Person">
<property name="name" value="Mike"></property>
<property name="age" value="23"></property>
<property name="cars">
<list>
<!--cars是一個集合型別-->
<ref bean="car"></ref>
<ref bean="car2"></ref>
</list>
</property>
</bean>
注意:其中ref指向的bean,其car和car2必須和Person在同一個包下
執行
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) ctx.getBean("person3");
System.out.println(person);
我們看看執行結果
Person{name='Mike', age=23, cars=[Car{brand='Audi', corp='ShangHai', price=300000.0, maxSpeed=0}, Car{brand='Baoma', corp='Tianjin', price=0.0, maxSpeed=200}]}
•在 Spring中可以通過一組內建的 xml 標籤(例如: <list>, <set> 或 <map>) 來配置集合屬性.
•配置 java.util.List 型別的屬性, 需要指定 <list> 標籤, 在標籤裡包含一些元素. 這些標籤可以通過 <value> 指定簡單的常量值, 通過 <ref> 指定對其他 Bean 的引用或者可以通過構造方法注入,具體的如何通過構造方法注入可參考上篇部落格. 通過<bean> 指定內建 Bean 定義. 通過 <null/> 指定空元素. 甚至可以內嵌其他集合.
•陣列的定義和 List 一樣, 都使用 <list>
Java.util.Map
•配置 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 屬性定義
package com.collection;
import java.util.Map;
public class NewPerson {
private String name;
private int age;
private Map<String,Car> cars;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Map<String, Car> getCars() {
return cars;
}
public void setCars(Map<String, Car> cars) {
this.cars = cars;
}
@Override
public String toString() {
return "NewPerson{" +
"name='" + name + '\'' +
", age=" + age +
", cars=" + cars +
'}';
}
}
我們再看看配置檔案,使用map節點及map的entry子節點配置Map型別的成員變數
<bean id="newPerson" class="com.collection.NewPerson">
<property name="name" value="Rose"></property>
<property name="age" value="28"></property>
<property name="cars">
<map>
<entry key="AA" value-ref="car"></entry>
<entry key="BB" value-ref="car2"></entry>
</map>
</property>
</bean>
看執行結果
NewPerson{name='Rose', age=28, cars={AA=Car{brand='Audi', corp='ShangHai', price=300000.0, maxSpeed=0}, BB=Car{brand='Baoma', corp='Tianjin', price=0.0, maxSpeed=200}}}
•使用 <props> 定義 java.util.Properties, 該標籤使用多個 <prop> 作為子標籤. 每個 <prop> 標籤必須定義 key 屬性.
定義一個NewPerson類,其Car型別使用Map型別
新建Properties類
import java.util.Properties;
public class DataSource {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "DataSource{" +
"properties=" + properties +
'}';
}
}
配置,使用props和prop子節點為Properties屬性賦值
<!--配置Properties屬性值-->
<bean id="dataSource" class="com.collection.DataSource">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">1234</prop>
<prop key="jdbcUrl">jdbc:mysql://test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
執行結果
DataSource{properties={driverClass=com.mysql.jdbc.Driver, user=root, password=1234, jdbcUrl=jdbc:mysql://test}}
如何將集合的配置拿出來,希望它也配置成一個Bean的方式
使用 utility scheme 定義集合
•使用基本的集合標籤定義集合時, 不能將集合作為獨立的 Bean 定義, 導致其他 Bean 無法引用該集合, 所以無法在不同 Bean 之間共享集合.
•可以使用 util schema 裡的集合標籤定義獨立的集合 Bean. 需要注意的是, 必須在 <beans> 根元素裡新增 util schema 定義
如配置檔案寫成
<!--配置單例的集合bean,以供多個bean引用-->
<util:list id="cars">
<ref bean="car"></ref>
<ref bean="car2"></ref>
</util:list>
<bean id="person4" class="com.collection.Person">
<property name="name" value="Jack"></property>
<property name="age" value="29"></property>
<property name="cars" ref="cars"></property>
</bean>
此時再執行結果如下
Person{name='Jack', age=29, cars=[Car{brand='Audi', corp='ShangHai', price=300000.0, maxSpeed=0}, Car{brand='Baoma', corp='Tianjin', price=0.0, maxSpeed=200}]}
使用 p 名稱空間
•為了簡化 XML 檔案的配置,越來越多的 XML 檔案採用屬性而非子元素配置資訊。
•Spring 從 2.5 版本開始引入了一個新的 p 名稱空間,可以通過 <bean> 元素屬性的方式配置 Bean 的屬性。
•使用 p 名稱空間後,基於 XML 的配置方式將進一步簡化
<!--通過p名稱空間為bean的屬性賦值,需先匯入p名稱空間,相對於傳統的配置方式更加簡潔-->
<bean id="person5" class="com.collection.Person" p:age="30" p:name="Queen" p:cars-ref="cars"></bean>
執行結果
Person{name='Queen', age=30, cars=[Car{brand='Audi', corp='ShangHai', price=300000.0, maxSpeed=0}, Car{brand='Baoma', corp='Tianjin', price=0.0, maxSpeed=200}]}
注:該部落格主要說明了配置bean的一些細節,如果不明白可以先看看前面幾篇部落格