引用其它 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的一些细节,如果不明白可以先看看前面几篇博客