I. Spring Bean 的配置形式
1. 基于 XML 文件的方式
在上一节Spring Introduction中的hello world 示例中,已经用到了xml的方式去配置一个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="helloBean" class="org.lovian.sping.bean.HelloBean">
<property name="name" value="Sping"></property>
</bean>
</beans>
- class: bean的全类名,通过反射的方式在 IOC 容器中创建 bean,所以要求 Bean 中必须有无参构造器
- id: 用来标识容器中的bean, id在IOC容器中是唯一的; 如果 id 没有被指定,那么 Spring 自动将权限定性类名作为 Bean的名字; id可以指定多个名字,名字之间可以用逗号,分号,或者空格来分隔
2. 基于注解的方式
II. Bean的配置方式
- 通过全类名反射
- 通过工厂方法(静态工厂方法和实例工厂方法)
- 通过 BeanFactory
III. 依赖注入的方式
- 属性注入
- 构造器注入
- 工厂方法注入(很少使用)
1. 属性注入
- 属性注入即通过 setter 方法注入 Bean 的属性值或依赖的对象
- 属性注入使用
<property>
元素,使用name
属性指定 Bean 的属性名称,value
属性或者<value>
子节点指定属性值 - 属性注入是实际应用中最常用的注入方式
2. 构造方法注入
- 通过构造方法注入 Bean 的属性值或者依赖的对象,它保证了 Bean 实例在实例化后就可以使用
- 构造器注入在
<constructor-arg>
元素里声明属性,注意<constructor-arg>
中没有name属性
使用构造方法注入示例: 首先创建一个类 Car,创建4个属性和有参构造器
package org.lovian.sping.bean;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Car {
private String brand;
private String model;
private String price;
private String maxSpeed;
public Car(String brand, String model, String price, String maxSpeed) {
this.brand = brand;
this.model = model;
this.price = price;
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", model='" + model + '\'' +
", price='" + price + '\'' +
", maxSpeed='" + maxSpeed + '\'' +
'}';
}
}
然后在 xml 配置文件中,以 constructor-arg 的方式声明一个 Car 的 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 class="org.lovian.sping.bean.Car">
<constructor-arg value="AUDI"></constructor-arg>
<constructor-arg value="A6L"></constructor-arg>
<constructor-arg value="480000"></constructor-arg>
<constructor-arg value="220"></constructor-arg>
</bean>
</beans>
然后通过 getBean(Class.class)
方式去获得这个bean
package org.lovian.sping.demo;
import org.lovian.sping.bean.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Demo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
Car car = applicationContext.getBean(Car.class);
System.out.println(car.toString());
}
}
打印出的结果如下:
Apr 07, 2018 4:04:11 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@619a5dff: startup date [Sat Apr 07 16:04:11 CST 2018]; root of context hierarchy
Apr 07, 2018 4:04:11 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/application_context.xml]
Car{brand='AUDI', model='A6L', price='480000', maxSpeed='220'}
Process finished with exit code 0
我们可以看到在 xml 文件中声明的属性值都被打印了出来,说明这个bean被成功的取到了。
注意!
如果通过 class 去获得bean, 那么在xml配置中,这个class对应的bean只能有一个,如果由多个,那么只能使用 id 的方式去获取这个bean。
但是对于一个Bean类来说,是可以由多个构造器的,也就是构造方法重载,那仅仅通过构造器参数的顺序去给每一个参数赋值,就有可能造成歧义,容器不知道把哪个值赋给哪个参数,那么这时候就可以通过constructor-arg
的 index
属性和 type
属性来规定我们声明参数的顺序,示例如下:
我们修改一下 Car 这个类,给两个构造器
package org.lovian.sping.bean;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Car {
private String brand;
private String model;
private int price;
private double maxSpeed;
public Car(String brand, String model, int price) {
this.brand = brand;
this.model = model;
this.price = price;
}
public Car(String brand, String model, double maxSpeed) {
this.brand = brand;
this.model = model;
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car{" +
"brand='" + brand + '\'' +
", model='" + model + '\'' +
", price='" + price + '\'' +
", maxSpeed='" + maxSpeed + '\'' +
'}';
}
}
然后在 application_context.xml 中定义两个 bean, 使用index
和type
去声明构造器参数的顺序使得两个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="Audi A6L" class="org.lovian.sping.bean.Car">
<constructor-arg value="AUDI" index="0"></constructor-arg>
<constructor-arg value="A6L" index="1"></constructor-arg>
<constructor-arg value="220" type="double"></constructor-arg>
</bean>
<bean id="BMW 525" class="org.lovian.sping.bean.Car">
<constructor-arg value="BMW" type="java.lang.String"></constructor-arg>
<constructor-arg value="525" type="java.lang.String"></constructor-arg>
<constructor-arg value="400000" type="int"></constructor-arg>
</bean>
</beans>
执行 main 方法
package org.lovian.sping.demo;
import org.lovian.sping.bean.Car;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Demo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
Car audi = (Car) applicationContext.getBean("Audi A6L");
System.out.println(audi.toString());
Car bmw = (Car) applicationContext.getBean("BMW 525");
System.out.println(bmw.toString());
}
}
结果如下
Apr 07, 2018 4:40:49 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@619a5dff: startup date [Sat Apr 07 16:40:49 CST 2018]; root of context hierarchy
Apr 07, 2018 4:40:49 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/application_context.xml]
Car{brand='AUDI', model='A6L', price='0', maxSpeed='220.0'}
Car{brand='BMW', model='525', price='400000', maxSpeed='0.0'}
Process finished with exit code 0
IV. 注入属性值的细节
1.字面值
字面值
:可以用字符串表示的值,可以通过<value>
元素标签或者value
属性进行注入基本数据类型及其封装类、String 等类型都可以采取字面值注入的方式
- 如果字面值中包含特殊字符,可以使用
<![CDATA[]]>
把字面值包裹起来
那我们对上一节的 Car 的例子中的 xml 文件做一下修改,让其中一个 String 值包含左右尖括号,它们在 xml 中属于特殊字符,那么就用使用 <![CDATA[]]>
将这个值括起来, 否则就会报错
<?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="Audi A6L" class="org.lovian.sping.bean.Car">
<constructor-arg value="AUDI" index="0"></constructor-arg>
<constructor-arg value="A6L" index="1"></constructor-arg>
<constructor-arg value="220" type="double"></constructor-arg>
</bean>
<bean id="BMW 525" class="org.lovian.sping.bean.Car">
<constructor-arg type="java.lang.String">
<value>BWM</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<!-- include special character "<" and ">", use <![CDATA[xxxxx]]> -->
<value><![CDATA[<525>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>400000</value>
</constructor-arg>
</bean>
</beans>
2. 引用其他的 bean
通过 value 字面值我们可以给bean的设置一些标准类型属性的值,那么如果 bean 和 bean 之间存在着引用关系,这又该怎么处理呢?
- 组成应用程序的 Bean 经常需要相互写作以完成应用程序的功能,要使得 Bean 能够相互访问,就必须在 Bean 配置文件中指定对 Bean 的引用
- 在 Bean 的配置文件中,可以通过
<ref>
元素或者ref
属性为 Bean的属性或者构造器参数指定对 Bean 的引用 - 当Bean 实例仅仅给一个特定属性使用时,可将其声明为
内部 Bean
- 在
属性或者构造器中包含 Bean 的声明
- 内部 Bean 声明直接包含在
<property>
或者<constructor-arg>
元素里 - 不需要设置任何 id 或者 name 属性
内部 Bean 不能被外部引用
,只能在内部使用
- 在
来做个示例,代码如下:
定义一个 Person 类,包含 Car 的引用
package org.lovian.sping.bean;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Person {
private String name;
private int age;
private Car car;
public Person() {
}
public Person(String name, int age, Car car) {
this.name = name;
this.age = age;
this.car = car;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public void setCar(Car car) {
this.car = car;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age='" + age + '\'' +
", car=" + car +
'}';
}
}
然后我们在application_context.xml中加入 Person类的 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="Audi A6L" class="org.lovian.sping.bean.Car">
<constructor-arg value="AUDI" index="0"></constructor-arg>
<constructor-arg value="A6L" index="1"></constructor-arg>
<constructor-arg value="220" type="double"></constructor-arg>
</bean>
<bean id="BMW 525" class="org.lovian.sping.bean.Car">
<constructor-arg type="java.lang.String">
<value>BWM</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<!-- include special character "<" and ">", use <![CDATA[xxxxx]]> -->
<value><![CDATA[<525>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>400000</value>
</constructor-arg>
</bean>
<bean id="lovian" class="org.lovian.sping.bean.Person">
<constructor-arg type="java.lang.String">
<value>Lovian</value>
</constructor-arg>
<constructor-arg type="int">
<value>25</value>
</constructor-arg>
<constructor-arg type="org.lovian.sping.bean.Car">
<!--use ref tag-->
<ref bean="BMW 525"></ref>
</constructor-arg>
</bean>
<bean id="zhshpeng" class="org.lovian.sping.bean.Person">
<property name="name">
<value>zhshpeng</value>
</property>
<property name="age">
<value>24</value>
</property>
<!-- use ref attribute -->
<property name="car" ref="Audi A6L"></property>
</bean>
</beans>
然后执行代码
package org.lovian.sping.demo;
import org.lovian.sping.bean.Car;
import org.lovian.sping.bean.Person;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Demo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
Person lovian = (Person) applicationContext.getBean("lovian");
System.out.println(lovian.toString());
Person zhshpeng = (Person) applicationContext.getBean("zhshpeng");
System.out.println(zhshpeng.toString());
}
}
结果如下:
Apr 07, 2018 5:24:21 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@619a5dff: startup date [Sat Apr 07 17:24:21 CST 2018]; root of context hierarchy
Apr 07, 2018 5:24:21 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/application_context.xml]
Person{name='Lovian', age='25', car=Car{brand='BWM', model='<525>', price='400000', maxSpeed='0.0'}}
Person{name='zhshpeng', age='24', car=Car{brand='AUDI', model='A6L', price='0', maxSpeed='220.0'}}
我们可以看到,在使用了 ref
属性或者 <ref>
标签之后,是可以将 Car 的 bean 对象和 Person 的 bean 对象建立起引用关系。
Bean的配置是可以嵌套的,下面我们演示一些内部 Bean
的声明,我们在上面的 aplication_context.xml 中加入一个bean的声明:在一个 Person Bean 中,直接声明一个 Car Bean。
<bean id="sq" class="org.lovian.sping.bean.Person">
<property name="name" value="sq"/>
<property name="age" value="23"/>
<property name="car">
<bean class="org.lovian.sping.bean.Car">
<constructor-arg value="Tesla" type="java.lang.String"/>
<constructor-arg value="S3" type="java.lang.String"/>
<constructor-arg value="700000" type="int"/>
</bean>
</property>
</bean>
然后在main方法中获取这个 bean
public class Demo {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
Person lovian = (Person) applicationContext.getBean("lovian");
System.out.println(lovian.toString());
Person zhshpeng = (Person) applicationContext.getBean("zhshpeng");
System.out.println(zhshpeng.toString());
Person sq = (Person) applicationContext.getBean("sq");
System.out.println(sq.toString());
}
}
我们可以看到结果如下:
Apr 07, 2018 5:35:26 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@619a5dff: startup date [Sat Apr 07 17:35:26 CST 2018]; root of context hierarchy
Apr 07, 2018 5:35:26 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [config/application_context.xml]
Person{name='Lovian', age='25', car=Car{brand='BWM', model='<525>', price='400000', maxSpeed='0.0'}}
Person{name='zhshpeng', age='24', car=Car{brand='AUDI', model='A6L', price='0', maxSpeed='220.0'}}
Person{name='sq', age='23', car=Car{brand='Tesla', model='S3', price='700000', maxSpeed='0.0'}}
Process finished with exit code 0
3. null 值和级联属性
- 可以使用专用的
<null/>
元素标签为 Bean 的字符串或者其他对象类型的属性注入 null 值(但实际java引用对象的默认值就是 null,所以意义不大) - 和 Structs、Hibernate 框架一样,
Spring 支持级联属性的配置
;为级联属性赋值,属性必须先要初始化后,才可以为级联属性赋值
下面是级联属性配置的例子,在上面的例子中,Car的构造器只有三个参数,那么我们在配置 Person bean的时候,给其引用的 Car bean 另外一个属性赋值,xml实例如下,我们修改一些 zhshpeng 这个bean,给它加入 car.maxSpeed
:
<bean id="zhshpeng" class="org.lovian.sping.bean.Person">
<property name="name">
<value>zhshpeng</value>
</property>
<property name="age">
<value>24</value>
</property>
<!-- use ref attribute -->
<property name="car" ref="Audi A6L"></property>
<property name="car.maxSpeed">
<value>250</value>
</property>
</bean>
注意:
- 必须要先在 person bean 中声明 car bean,才能给 car 的属性赋值
- 如果不先声明 car bean,那么Spring不会自动创建一个 car 的 bean 对象,会报错
- 在 Person 类中必须要由 car 属性的 getter 方法,并且 Car 类中要有 maxSpeed 的 setter 方法才可以,否则会报错。
执行结果如下:
Person{name='zhshpeng', age='24', car=Car{brand='AUDI', model='A6L', price='0', maxSpeed='250.0'}}
4.集合属性
在 Java 中集合有 Collection 和 Map,同样的 Spring 也支持集合属性,在 Spring中可以通过一组内置的 xml 标签(例如: <list>
, <set>
或 <map>
) 来配置集合属性
对于 List, Array 和 Set的集合属性:
- 配置
java.util.List
类型的属性, 需要指定<list>
标签, 在标签里包含一些元素. 这些标签可以通过<value>
指定简单的常量值, 通过<ref>
指定对其他 Bean 的引用. 通过<bean>
指定内置 Bean 定义. 通过<null/>
指定空元素. 甚至可以内嵌其他集合. - 数组
Array
的定义和List
一样, 都使用<list>
- 配置
java.util.Set
需要使用<set>
标签, 定义元素的方法与 List 一样.
集合属性示例如下,先重新写一个类 Person, 包括了一个 List<Car>
成员变量:
package org.lovian.sping.bean.collections;
import org.lovian.sping.bean.Car;
import java.util.List;
/**
* Author: PENG Zhengshuai
* Date: 4/7/18
* lovian.org
*/
public class Person {
private String name;
private int age;
private List<Car> cars;
public Person() {
}
public Person(String name, int age, List<Car> cars) {
this.name = name;
this.age = age;
this.cars = 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 +
'}';
}
}
那么接下来就需要在 application_context.xml 中配置这个 Person 类的bean,并让它拥有两个我们之前配置好的 Car bean 对象
<bean id="Tom" class="org.lovian.sping.bean.collections.Person">
<property name="name" value="Tom" />
<property name="age" value="18"/>
<property name="cars">
<list>
<ref bean="BMW 525"/>
<ref bean="Audi A6L"/>
</list>
</property>
</bean>
执行 main 方法:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
Person tom = (Person) applicationContext.getBean("Tom");
System.out.println(tom.toString());
}
打印结果如下:
Person{name='Tom', age=18, cars=[Car{brand='BWM', model='<525>', price='400000', maxSpeed='0.0'}, Car{brand='AUDI', model='A6L', price='0', maxSpeed='250.0'}]}
从这个结果来看,我们用了 <list>
来给 Person 类中 List<Car>
成员变量添加了两个值。但实际上我们并没有显式的让这个成员变量初始化,Spring 自动的给 new 出了一个 List 对象,并把关联的两个 Car 对象添加了进去。
对于 Map 和 Properties 的集合属性:
Java.util.Map
通过<map>
标签定义,<map>
标签里可以使用多个<entry>
作为子标签. 每个条目包含一个键和一个值- 必须在
<key>
标签里定义键 - 因为键和值的类型没有限制, 所以可以自由地为它们指定
<value>
,<ref>
,<bean>
或<null/>
元素 - 可以将 Map 的键和值作为
<entry>
的属性定义: 简单常量使用key
和value
来定义; Bean 引用通过key-ref
和value-ref
属性定义 - 使用
<props
> 定义java.util.Properties
, 该标签使用多个<props>
作为子标签. 每个<property>
标签必须定义 key 属性
示例如下,同样新建一个包含 Map 成员变量的 MapPerson 类:
package org.lovian.sping.bean.collections;
import org.lovian.sping.bean.Car;
import java.util.Map;
/**
* Author: PENG Zhengshuai
* Date: 4/8/18
* lovian.org
*/
public class MapPerson {
private String name;
private int age;
private Map<String, Car> cars;
public MapPerson() {
}
public MapPerson(String name, int age, Map<String, Car> cars) {
this.name = name;
this.age = age;
this.cars = 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 "MapPerson{" +
"name='" + name + '\'' +
", age=" + age +
", cars=" + cars +
'}';
}
}
接下来就在application_context.xml中添加 MapPerson bean的定义:
<bean id="Jerry" class="org.lovian.sping.bean.collections.MapPerson">
<property name="name" value="Jerry"/>
<property name="age" value="17"/>
<property name="cars">
<map>
<entry key="First Car" value-ref="Audi A6L"/>
<entry key="Second Car" value-ref="BMW 525"/>
</map>
</property>
</bean>
我们在 Map 中定义了两条 entry, key 是一个 String, 而 value 则是一个 bean 的引用,执行一下 main 方法看看结果:
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("config/application_context.xml");
MapPerson jerry = (MapPerson) applicationContext.getBean("Jerry");
System.out.println(jerry.toString());
}
结果如下:
MapPerson{name='Jerry', age=17, cars={First Car=Car{brand='AUDI', model='A6L', price='0', maxSpeed='250.0'}, Second Car=Car{brand='BWM', model='<525>', price='400000', maxSpeed='0.0'}}}
我们可以看到和 List 的示例一样,Map 被初始化且添加了两个键值对。而对于java.util.Properties
用法和java.util.Map
相似,xml示例如下:
<bean id="properties" class="xxxxxxx">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">pna</prop>
</props>
</property>
</bean>
5.使用 Utility Schema 定义集合
由于使用基本的集合标签定义集合时, 不能将集合作为独立的 Bean
定义, 导致其他 Bean
无法引用该集合, 所以无法在不同 Bean
之间共享集合.就如上小节的例子中,我们在 Person 或者是 MapPerson 的 bean 中定义了集合的成员变量,但这些集合是无法被其他 bean 所引用的,如果由其他类需要引用这些集合,那怎么处理?
可以使用 utility schema
里的集合标签定义独立的集合 Bean
. 需要注意的是, 必须在 <beans>
根元素里添加 utility schema
定义。通俗的来说,就是把我们之前定义的那些集合单独拿出来,当作一个 bean 来配置,也就是说,我们需要配置单例的集合 bean,从而供多个 bean 进行引用
示例如下,我们在 application_context.xml 中添加一个 util:list
和一个集合 Person bean
<util:list id="bba-cars">
<ref bean="BMW 525"/>
<ref bean="Audi A6L"/>
<bean id="Benz C200" class="org.lovian.sping.bean.Car">
<constructor-arg value="BENZ" type="java.lang.String"/>
<constructor-arg value="C200" type="java.lang.String"/>
<constructor-arg value="240" type="double"/>
<property name="price" value="300000"/>
</bean>
</util:list>
<bean id="Jack" class="org.lovian.sping.bean.collections.Person">
<property name="name" value="Jack" />
<property name="age" value="23"/>
<property name="cars">
<ref bean="bba-cars"/>
</property>
</bean>
注意需要在<beans>
的属性中加入下面的util 命名空间
xmlns:util="http://www.springframework.org/schema/util"
这里我们可以看到,Person中本来应该设置 List<Car>
的地方,我们引用了上面 util:list
定义的 bean,执行一些 main 方法得到结果如下:
Person{name='Jack', age=23, cars=[Car{brand='BWM', model='<525>', price='400000', maxSpeed='0.0'}, Car{brand='AUDI', model='A6L', price='0', maxSpeed='250.0'}, Car{brand='BENZ', model='C200', price='300000', maxSpeed='240.0'}]}
V. 使用 p 命名空间
为了简化 XML 文件的配置,越来越多的 XML 文件采用属性而非子元素配置信息。从 Sping 2.5 版本开始引入了一个新的 p 命名空间(p namespace)
,可以通过 <bean>
元素属性的方式来配置 Bean 的属性,我们可以可以把上面那个 Jack
那个 bean 改写成如下方式:
<bean id="Rose" class="org.lovian.sping.bean.collections.Person" p:name="Rose" p:age="22" p:cars-ref="bba-cars"/>
注意在 <beans>
的属性里应该加入下面的p 命名空间
xmlns:p="http://www.springframework.org/schema/p"
Share this on