目录
上一篇学习了Bean的配置、Spring容器的基本实现、Bean注入值的方式,这一篇在Bean注入值的基础上,扩展的学习一下注入属性的一些技巧。
一、字面值
- 字面值,可用于字符串表示的值,可以通过<value>元素标签或value属性进行注入;
- 基本数据类型及其封装类、String等类型都可以采用字面值注入;
- 若字面值中包含了特殊字符,可以使用<![CDATE[]]>把字面值包裹起来。
例如将id="car1"的Bean用字面值注入值(给corp注入的值是<^^GanSu^^>,给maxSpeed注入的值是180):
$注意:本例中Car.class,Main.class其他代码都在上一篇文章中:Spring学习(2)——bean的配置
<!-- 通过字面值给corp和maxSpeed属性注入值 -->
<bean id="car1" class="com.atguigu.spring.beans.Car">
<constructor-arg value="Audi" type="java.lang.String"></constructor-arg>
<constructor-arg type="java.lang.String">
<value><![CDATA[<^^GanSu^^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>180</value>
</constructor-arg>
</bean>
执行结果是:
Car1: Car [brand=Audi, corp=<^^GanSu^^>, price=0.0, maxSpeed=180]
二、引用其他Bean
- 组成应用程序的Bean经常需要相互协作以完成应用程序的功能。要使Bean能够相互访问,就必须在Bean配置文件中指定对Bean的引用;
- 在Bean的配置文件中,可以通过<ref>元素或ref属性为Bean的属性或者构造器参数指定对Bean的引用;
- 也可以在属性或构造器里面含Bean的声明,这样的Bean成为内部Bean。
-
用ref属性或者<ref>元素指定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 + "]";
}
}
在applicationContext.xml中的person的bean中注入car1:
<!-- property的ref属性或<ref>元素家里bean之间的引用关系 -->
<bean id="person" class="com.atguigu.spring.beans.Person">
<property name="name" value="zhangsan"></property>
<property name="age" value="26"></property>
<!-- 用property的ref属性建立bean之间的引用关系 <property name="car" ref="car1"></property> -->
<!-- <ref>元素家里bean之间的引用关系 -->
<property name="car">
<ref bean="car1" />
</property>
</bean>
在main中调用,查看注入的值:
public static void main(String[] args) {
Main main=new Main();
main.testBeanAdd();
}
private void testBeanAdd() {
ApplicationContext cxt=new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) cxt.getBean("person");
System.out.println(person);
}
执行结果为:
Person [name=zhangsan, age=26, car=Car [brand=Audi, corp=<^^GanSu^^>, price=0.0, maxSpeed=180]]
-
用内部bean的列子
但是内部bean,不能被外部使用,只能在内部使用。
Person不变,xml改写成内部bean的实现方式:
<!-- 内部bean实现bean之间的引用关系 -->
<bean id="person" class="com.atguigu.spring.beans.Person">
<property name="name" value="zhangsan"></property>
<property name="age" value="26"></property>
<property name="car">
<bean class="com.atguigu.spring.beans.Car">
<constructor-arg value="DaZhong"
type="java.lang.String"></constructor-arg>
<constructor-arg value="beijing"
type="java.lang.String"></constructor-arg>
<constructor-arg value="200000" type="double"></constructor-arg>
</bean>
</property>
</bean>
执行main,的结果:
Person [name=zhangsan, age=26, car=Car [brand=DaZhong, corp=beijing, price=200000.0, maxSpeed=0]]
当然了,上面的例子Bean是用property注入值的,还可以用构造器注入,首先,在Person中添加构造器,然后在xml中用构造器注入内部Bean:
在Person中加入构造器:
public Person(String name, int age, Car car) {
super();
this.name = name;
this.age = age;
this.car = car;
}
在xml中用构造器注入:
<bean id="person1" class="com.atguigu.spring.beans.Person">
<constructor-arg value="zhangsan"></constructor-arg>
<constructor-arg value="26"></constructor-arg>
<constructor-arg ref="car1"></constructor-arg>
</bean>
三、null值和级联属性
使用专门的<null/>元素标签为bean的字符串或者其他对象类型的属性注入null值。
和struts和hibernate等其他框架一样,Spring支持级联属性的配置。
赋值null:
<!-- 用<null/>元素赋值null值 -->
<bean id="person3" class="com.atguigu.spring.beans.Person">
<constructor-arg value="zhangsan"></constructor-arg>
<constructor-arg value="26"></constructor-arg>
<!-- 赋值null值 -->
<constructor-arg><null/></constructor-arg>
</bean>
级联属性赋值(为级联属性赋值的时候,注意要先给属性初始化,才能为级联属性赋值,否则会有异常):
<!-- 为级联属性赋值,注意属性先要初始化之后才可以为级联属性赋值,否则会有异常。 -->
<bean id="person4" class="com.atguigu.spring.beans.Person">
<constructor-arg value="zhangsan"></constructor-arg>
<constructor-arg value="26"></constructor-arg>
<constructor-arg ref="car"></constructor-arg>
<property name="car.maxSpeed" value="240"></property>
</bean>
四、集合属性
- 在Spring可以通过一组内置的xml标签(例如:<list>/<set>/<map>)来配置集合属性;
- 配置java.util.List类型的属性,需要指定<list>标签,在标签中包含一些元素;这些标签可以通过<value>指定简单的常用之,通过<ref>指定对其他bean的引用;通过<bean>指定内置bean的定义;通过<null/>指定空元素;甚至可以内嵌其他集合。
- 数组的定义和list一样,都要使用<List>;
- 配置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属性定义;
- 使用<props>定义java.util.Properties,该标签使用多个<prop>作为子标签,每个<prop>标签必须定义key属性;
-
用<list>标签注入属性值的样例
新建Person类:
public class Person {
private String name;
private int age;
private List<Car> cars;
public Person(String name, int age, List<Car> cars) {
super();
this.name = name;
this.age = age;
this.cars = cars;
}
public Person() {
super();
}
@Override
public String toString() {
return "Person [name=" + name + ", age=" + age + ", 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;
}
}
新建Car类:
public class Car {
private String brand;
private String corp;
private double price;
private int maxSpeed;
public Car() {
super();
}
public Car(String brand, String corp, double price, int maxSpeed) {
super();
this.brand = brand;
this.corp = corp;
this.price = price;
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
}
}
xml设置bean:
<!-- first car1 -->
<bean id="newcar1"
class="com.atguigu.spring.beans.collections.Car">
<constructor-arg value="dazhong" index="0"></constructor-arg>
<constructor-arg value="gansu" index="1"></constructor-arg>
<constructor-arg value="120000.00" index="2"></constructor-arg>
<constructor-arg value="240" index="3"></constructor-arg>
</bean>
<!-- secord car1 -->
<bean id="newcar2"
class="com.atguigu.spring.beans.collections.Car">
<constructor-arg value="changan" index="0"></constructor-arg>
<constructor-arg value="gansu" index="1"></constructor-arg>
<constructor-arg value="150000.00" index="2"></constructor-arg>
<constructor-arg value="240" index="3"></constructor-arg>
</bean>
<!-- 给list注入值 -->
<bean id="newPerson"
class="com.atguigu.spring.beans.collections.Person">
<property name="name" value="zhangsan"></property>
<property name="age" value="12"></property>
<property name="cars">
<list>
<ref bean="newcar1" />
<ref bean="newcar1" />
<bean class="com.atguigu.spring.beans.collections.Car">
<constructor-arg value="aodi"></constructor-arg>
<constructor-arg value="changan"></constructor-arg>
<constructor-arg value="200000" type="double"></constructor-arg>
<constructor-arg value="180" type="int"></constructor-arg>
</bean>
</list>
</property>
</bean>
main执行:
private void testLists() {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person = (Person) cxt.getBean("newPerson");
System.out.println("person= " + person);
}
执行结果:
person= Person [name=zhangsan, age=12, cars=[Car [brand=dazhong, corp=gansu, price=120000.0, maxSpeed=240], Car [brand=dazhong, corp=gansu, price=120000.0, maxSpeed=240], Car [brand=aodi, corp=changan, price=200000.0, maxSpeed=180]]]
-
注入Map类属性值:
使用map节点及map的entry子节点配置Map类型的成员变量。
newPerson类:
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 + "]";
}
}
car类:
public class Car {
private String brand;
private String corp;
private double price;
private int maxSpeed;
public Car() {
super();
}
public Car(String brand, String corp, double price, int maxSpeed) {
super();
this.brand = brand;
this.corp = corp;
this.price = price;
this.maxSpeed = maxSpeed;
}
@Override
public String toString() {
return "Car [brand=" + brand + ", corp=" + corp + ", price=" + price + ", maxSpeed=" + maxSpeed + "]";
}
}
xml:
<!-- 配置map属性值 -->
<bean id="newpersonmap"
class="com.atguigu.spring.beans.collections.NewPerson">
<property name="name" value="Rose"></property>
<property name="age" value="28"></property>
<property name="cars">
<map>
<entry key="AA" value-ref="newcar1"></entry>
<entry key="BB" value-ref="newcar2"></entry>
</map>
</property>
</bean>
main:
private void testMaps() {
ApplicationContext cxt=new ClassPathXmlApplicationContext("applicationContext.xml");
NewPerson newperson=(NewPerson) cxt.getBean("newpersonmap");
System.out.println("newperson= "+newperson);
}
执行结果:
newperson= NewPerson [name=Rose, age=28, cars={AA=Car [brand=dazhong, corp=gansu, price=120000.0, maxSpeed=240], BB=Car [brand=changan, corp=gansu, price=150000.0, maxSpeed=240]}]
-
定义java.util.Properties
使用<props>定义java.util.Properties,改标签使用多个<prop>作为子标签,每个<prop>标签必须定义key值。
写一个注入properties的例子:
新建一个DataSource类:
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 + "]";
}
}
XML注入方法:
<!-- 配置properties的属性值 -->
<bean id="properties"
class="com.atguigu.spring.beans.collections.DataSource">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">123</prop>
<prop key="jdbcUrl">jdbc:mysql:///test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
</bean>
main方法执行:
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext cxt=new ClassPathXmlApplicationContext("applicationContext.xml");
Main m = new Main();
m.testProperties(cxt);
}
/**
*
* @param cxt
*/
private void testProperties(ApplicationContext cxt) {
DataSource ds=(DataSource) cxt.getBean("properties");
System.out.println("ds= "+ds);
}
执行结果:
ds= DataSource [properties={driverClass=com.mysql.jdbc.Driver, user=root, password=123, jdbcUrl=jdbc:mysql:///test}]
五、使用utility scheme定义集合
- 使用基本的集合标签定义集合的时候,不能讲集合作为独立的bean处理,导致其他bean无法引用该集合,所以无法在不同的bean之间共享集合。
- 可以使用util schema里面的集合标签定义独立的集合Bean,需要注意的是,必须在<beans>根元素里添加util schema定义。
xml代码:
<!-- 配置单例的集合Bean,以供多个bean进行引用,需要导入util命名空间 -->
<util:list id="cars111">
<ref bean="newcar1" />
<ref bean="newcar2" />
</util:list>
<bean id="person4"
class="com.atguigu.spring.beans.collections.Person">
<property name="name" value="Jack"></property>
<property name="age" value="28"></property>
<property name="cars" ref="cars111"></property>
</bean>
六、使用P命名空间
- 问了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息;
- Spring从2.5版本开始引入了一个新的P空间,可以通过<bean>元素属性的方式配置Bean的属性;
- 使用P命名空间后,基于XML的配置方式将进一步简化;
XML样例:
<!-- 通过p命名空间为bean的属性赋值,需要先导入P命名空间,相对于传统的配置方式更加的简洁 -->
<bean id="personP" class="com.atguigu.spring.beans.collections.Person" p:age="30"
p:name="Queen" p:cars-ref="cars">
</bean>