通常,JavaBean 的属性值是私有的,同时拥有一组存取器方法,以 setXxx () 和 getXxx () 的形式存在。Spring 通过 Java 的反射机制借助属性的 set 方法来配置属性的值,以实现 setter 方式的注入。
下面定义一个 Person 类来演示 Spring Bean 的属性注入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 package cn.javacodes.spring.beans;public class Person { private String name; private int age; private String sex; private String resume; 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 String getSex () { return sex; } public void setSex (String sex) { this .sex = sex; } public String getResume () { return resume; } public void setResume (String resume) { this .resume = resume; } public Car getCar () { return car; } public void setCar (Car car) { this .car = car; } public Person (String name, int age, String sex, String resume) { this .name = name; this .age = age; this .sex = sex; this .resume = resume; } public Person (String name, int age, String sex, String resume, Car car) { this .name = name; this .age = age; this .sex = sex; this .resume = resume; this .car = car; } public Person () { } }
Person 类中包含一个无参的构造方法,因此可以在 Spring 中使用下面的 XML 声明一个:
1 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > </bean >
通过上面的 XML 生命的没有对任何属性进行赋值,下面逐步讲解如何为属性进行赋值。
一、注入简单值(字面值) 1、通过 value 属性注入 在 Spring 中可以使用元素配置 Bean 的属性。例如现在想给 bean person 的姓名、年龄、性别、简历等属性赋值,那么可以使用下面的方式:
1 2 3 4 5 6 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > <property name ="name" value ="张三" > </property > <property name ="age" value ="16" > </property > <property name ="sex" value ="男" > </property > <property name ="resume" value ="疯狂的Java码农" > </property > </bean >
一旦 Person 被实例化,Spring 就会调用元素所指定属性的 setter 方法为该属性注入值。在本实例中,name、sex、resume 属性均为 String 类型的字符串,而我们发现 int 类型的 age 属性也可以成功注入简单值,这是因为元素并没有限制只能注入 String 类型的值,value 属性同样可以指定为基本数据类型(包括数值型和布尔型等)。
2、通过子元素注入 那么我们想象一下,如果我们想注入的值中包含 XML 的特殊字符怎么办,上述方法是否仍然奏效?不妨尝试一下,例如我想将 person 的 resume 属性注入值 “<Coder!>”,那么在这个值中,“<>” 在 XML 中拥有特殊的含义,如果仍然使用 value 属性进行赋值,将会出现异常!
Exception in thread "main" org.springframework.beans.factory.xml.XmlBeanDefinitionStoreException: Line 11 in XML document from class path resource [applicationContext.xml] is invalid; nested exception is org.xml.sax.SAXParseException; lineNumber: 11; columnNumber: 40; 与元素类型 "property" 相关联的 "value" 属性值不能包含 '<' 字符。
那么如何解决这个问题呢?元素中可以添加一个子元素,其作用与 value 属性基本相同,而当我们想要注入包含特殊字符的字面值时,可以在子元素中使用 CDATA 节来解决,例如:
1 2 3 4 5 6 7 8 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > <property name ="name" value ="张三" > </property > <property name ="age" value ="16" > </property > <property name ="sex" value ="男" > </property > <property name ="resume" > <value > <![CDATA[<Coder!>]]></value > </property > </bean >
二、引用其他 Bean 上面使用 value 属性或子元素注入简单值只是实现简单的硬编码,而在实际开发过程中,经常需要为某一个属性赋值为一个对象,通常为另一个 bean。那么如何在 Spring 中为属性引用其他 bean 呢?
例如本例中 Person 实例拥有一个 Car 类型的属性 car,可以使用元素的 ref 属性为其进行赋值。类 Car 的源码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 package cn.javacodes.spring.beans;public class Car { private String brand; private String model; private String color; public Car () { } public Car (String brand, String model, String color) { this .brand = brand; this .model = model; this .color = color; } public String getBrand () { return brand; } public void setBrand (String brand) { this .brand = brand; } public String getModel () { return model; } public void setModel (String model) { this .model = model; } public String getColor () { return color; } public void setColor (String color) { this .color = color; } @Override public String toString () { return "Car{" + "brand='" + brand + '' ' + ", model=' " + model + ''' + " , color='" + color + ' '' + '}' ; } }
我们首先在 XML 中声明一个 Car 类型的,源码如下:
1 2 3 4 5 <bean id ="car" class ="cn.javacodes.spring.beans.Car" > <property name ="brand" value ="奥迪" > </property > <property name ="model" value ="A6" > </property > <property name ="color" value ="黑色" > </property > </bean >
那么可以在 person bean 中引用这个 bean,源码如下:
1 2 3 4 5 6 7 8 9 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > <property name ="name" value ="张三" > </property > <property name ="age" value ="16" > </property > <property name ="sex" value ="男" > </property > <property name ="resume" > <value > <![CDATA[<Coder!>]]></value > </property > <property name ="car" ref ="car" > </property > </bean >
三、注入内部 Bean 我们知道,在 Spring 中 bean 的默认作用域是单例的,通过上述方式注入 bean,意味着这个 bean 还可能被其他 bean 引用。例如,可能有另外一个 Person 类型的 bean person1,其 car 属性同样引用的是 id 为 car 的 bean,那么意味着这两个人同时拥有同一台奥迪 A6,这通常是不现实的。那么如何为一个 Bean 创建一个独有的内部 bean 呢?
在 Spring 中元素中还可以嵌套其它的元素,我们称嵌套在内部的为内部 bean,这个概念与 Java 的内部类十分相似。
我们修改一下 person 的声明,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > <property name ="name" value ="张三" > </property > <property name ="age" value ="16" > </property > <property name ="sex" value ="男" > </property > <property name ="resume" > <value > <![CDATA[<Coder!>]]></value > </property > <property name ="car" > <bean class ="cn.javacodes.spring.beans.Car" > <property name ="brand" value ="奥迪" > </property > <property name ="model" value ="A6" > </property > <property name ="color" value ="黑色" > </property > </bean > </property > </bean >
这样我们就成功的注入了一个内部 Bean。细心的朋友可能会发现,在这里内部 bean 没有给定其 id 属性,因为在这里其 id 属性似乎并不是那么必要,因为我们永远不会通过 id 来引用内部 bean。这也突出了内部 Bean 的最大缺点:它们不能被复用。内部 Bean 仅适用于一次注入,而且也不能被其它 Bean 所引用。
内部 Bean 并不局限于在元素中使用,我们同样可以在中使用,例如我们修改 person 的声明如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <bean id ="person" class ="cn.javacodes.spring.beans.Person" > <constructor-arg value ="张三" > </constructor-arg > <constructor-arg value ="16" > </constructor-arg > <constructor-arg name ="sex" value ="男" > </constructor-arg > <constructor-arg > <value > <![CDATA[<Coder!>]]></value > </constructor-arg > <constructor-arg > <bean class ="cn.javacodes.spring.beans.Car" > <constructor-arg name ="brand" value ="奥迪" > </constructor-arg > <constructor-arg name ="model" value ="A6" > </constructor-arg > <constructor-arg name ="color" value ="黑色" > </constructor-arg > </bean > </constructor-arg > </bean >