一、通过 setter 方法为属性赋值
通过 bean 的 setXxx() 方法赋值,在配置文件中注册一个bean,并使用 property 标签来给属性赋值:
<!--注册一个Person对象,Spring会自动创建这个Person对象-->
<bean id="person01" class="com.njf.spring.bean.Person">
<!--
使用property标签为Person对象的属性赋值
name="lastName": 指定属性名
value="子龙": 指定属性值
-->
<property name="lastName" value="子龙"></property>
<property name="age" value="18"></property>
<property name="email" value="zilong@achang.com"></property>
<property name="gender" value="男"></property>
</bean>
同时也在 Person 类的 setLastName() 方法中添加打印输出:
public void setLastName(String lastName) {
System.out.println("调用了Person的setLastName方法");
this.lastName = lastName;
}
测试:
/**
* 通过 setter 方法为 bean 的属性赋值
*/
@Test
public void testSetBeanProp1() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person01 = (Person) ioc.getBean("person01");
System.out.println("person01 = " + person01);
}
运行结果:
可以看到使用 property 标签来给属性赋值,其实就是调用的其 setter 方法。
javaBean的属性名是由什么决定的?
由getter/setter方法后面的名决定,首字母小写所有的getter/setter都自动生成!!!千万别乱改
注意:使用property标签这种方式是调用的 setter 方法,而不是直接对声明的属性进行操作的。
二、通过构造器为属性赋值
1、使用构造器为属性赋值(推荐使用)
配置文件中进行配置 bean 信息:
<bean id="person02" class="com.njf.spring.bean.Person">
<!--
调用有参构造器进行对象并赋值
public Person(String lastName, Integer age, String gender, String email)
-->
<constructor-arg name="lastName" value="小明"></constructor-arg>
<constructor-arg name="email" value="xiaoming@126.com"></constructor-arg>
<constructor-arg name="gender" value="男"></constructor-arg>
<constructor-arg name="age" value="18"></constructor-arg>
</bean>
测试代码:
@Test
public void testSetBeanProp2() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person02 = (Person) ioc.getBean("person02");
System.out.println("person02 = " + person02);
}
可以使用 constructor-arg 标签来调用构造器方法给 bean 赋值,而且还可以打乱顺序,Spring 自动匹配合适的构造器。
2、省略 name 的构造器赋值
除此之外,还可以只使用 value 属性给赋值:
<!--可以省略 name 属性,严格按照构造器参数的位置-->
<bean id="person03" class="com.njf.spring.bean.Person">
<constructor-arg value="小明"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<constructor-arg value="男"></constructor-arg>
<constructor-arg value="xiaoming@126.com"></constructor-arg>
</bean>
但是这种情况,必须严格按照构造器参数的位置先后依次声明各个属性。
3、添加 index 属性的赋值(通过索引值指定参数位置)
对于上面的情况,如果把 email 放在了 sex 的前面会怎么样呢?
<bean id="person04" class="com.njf.spring.bean.Person">
<constructor-arg value="小明"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<constructor-arg value="xiaoming@126.com"></constructor-arg>
<constructor-arg value="男"></constructor-arg>
</bean>
测试运行:
这是就会赋值混乱,就可以使用 index 来指定参数的索引,从 0 开始。
修改配置文件:
<!--使用 index 为参数指定索引,从0开始-->
<bean id="person04" class="com.njf.spring.bean.Person">
<constructor-arg value="小明"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<constructor-arg value="xiaoming@126.com" index="3"></constructor-arg>
<constructor-arg value="男" index="2"></constructor-arg>
</bean>
再次运行测试:
正常赋值了。
4、添加 type 属性的赋值(通过类型区分重载的构造器)
为 Person 类添加三个参数的构造器:
public Person(String lastName, Integer age, String gender) {
System.out.println("调用了三个参数的构造器");
this.lastName = lastName;
this.age = age;
this.gender = gender;
}
public Person(String lastName, String email, String gender) {
System.out.println("调用了三个参数的构造器");
this.lastName = lastName;
this.email = email;
this.gender = gender;
}
配置 bean 信息:
<bean id="person05" class="com.njf.spring.bean.Person">
<constructor-arg value="小明"></constructor-arg>
<constructor-arg value="18"></constructor-arg>
<constructor-arg value="男"></constructor-arg>
</bean>
测试运行:
发现并没有成功赋值,对于重载的构造器,Spring 仅凭 value 不能判断调用哪一个构造器。
修改配置文件:
<!-- 重载的情况type可以指定参数的类型-->
<bean id="person05" class="com.njf.spring.bean.Person">
<constructor-arg value="小明"></constructor-arg>
<constructor-arg value="18" index="1" type="java.lang.Integer"></constructor-arg>
<constructor-arg value="男"></constructor-arg>
</bean>
重新测试:
可以正确赋值了,当遇到重载的构造器时,可以用 index 指定参数的索引位置,用 type 指定参数的类型。
三、通过p名称空间为 bean 赋值
为了简化XML文件的配置,越来越多的XML文件采用属性而非子元素配置信息。Spring 从2.5版本开始引入了一个新的p命名空间,可以通过<bean>元素属性的方式配置Bean 的属性。
添加名称空间:
使用 p 命名空间后,基于 XML 的配置方式将进一步简化
<bean id="person06" class="com.njf.spring.bean.Person" p:lastName="小刘" p:age="18" p:gender="男" p:email="liu@126.com"></bean>
四、可以使用的值
1、字面量
2、null 值
null 值可以直接使用。
对于有初始值的 Person 类
如果在容器中就想给它赋值为 null,可以直接使用 null 标签来赋值。
<!-- 测试使用 null 值,默认引用类型就是 null,基本类型就是默认值 -->
<bean id="person07" class="com.njf.spring.bean.Person">
<property name="lastName">
<null/>
</property>
</bean>
下面的写法是错误的:
<bean id="person07" class="com.njf.spring.bean.Person">
<property name="lastName" value="null"></property>
</bean>
五、为引用类型赋值
修改完的 Person 类中有一个 Car 属性,如何给该引用类型的赋值呢
1、外部已声明的 bean、引用其他的 bean
当 bean 实例里面有引用其他的 bean 时,可以使用 ref (reference)来引用其他的 bean 的实例。
配置文件:
<bean id="car01" class="com.njf.spring.bean.Car">
<property name="carName" value="宝马"></property>
<property name="color" value="绿色"></property>
<property name="price" value="30000"></property>
</bean>
<!--引用其他 bean-->
<bean id="person08" class="com.njf.spring.bean.Person">
<!--ref:引用外面的一个值-->
<property name="car" ref="car01"></property>
</bean>
测试:
@Test
public void testSetBeanProp8() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person08 = (Person) ioc.getBean("person08");
System.out.println("person08 = " + person08);
Car car = ioc.getBean(Car.class);
System.out.println(car == person08.getCar()); //true
car.setPrice(4000);
System.out.println(person08.getCar().getPrice()); //4000
System.out.println(car == person08.getCar()); //true
}
在这里引用的是都是容器中同一个 Car,当修改了 Car 的属性时,Persong08 中的 Car 属性也会跟着变化。(同一个对象)
2、引用内部 bean
<bean id="person09" class="com.njf.spring.bean.Person">
<!--创建内部 bean-->
<property name="car">
<bean id="car02" class="com.njf.spring.bean.Car">
<property name="carName" value="宝马"></property>
<property name="color" value="红色"></property>
<property name="price" value="5000"></property>
</bean>
</property>
</bean>
@Test
public void testSetBeanProp9() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person09 = (Person) ioc.getBean("person09");
System.out.println("person09 = " + person09);
System.out.println(person09.getCar());
/**
* org.springframework.beans.factory.NoSuchBeanDefinitionException:
* No bean named 'car02' is defined
*/
Car car02 = (Car) ioc.getBean("car02");
System.out.println("car02 = " + car02);
}
六、为集合类型赋值
1、为数组属性赋值
<bean id="person10" class="com.njf.spring.bean.Person">
<!-- 给数组类型赋值 -->
<property name="names">
<array> <!-- 使用 array 标签-->
<value>老张</value>
<value>老李</value>
</array>
</property>
</bean>
<bean id="person11" class="com.njf.spring.bean.Person">
<!-- 给数组类型赋值 -->
<property name="names">
<list> <!-- 使用 list标签-->
<value>小张</value>
<value>小李</value>
</list>
</property>
</bean>
@Test
public void testSetBeanProp10() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person10 = (Person) ioc.getBean("person10");
System.out.println("person10 = " + person10);
System.out.println(Arrays.toString(person10.getNames()));
Person person11 = (Person) ioc.getBean("person11");
System.out.println("person11 = " + person11);
System.out.println(Arrays.toString(person11.getNames()));
}
2、为List属性赋值
使用 <list> 标签,设置同数组
配置文件:
<bean id="person12" class="com.njf.spring.bean.Person">
<!-- 给List类型赋值 -->
<property name="books"> <!-- 使用 array 标签-->
<array>
<bean class="com.njf.spring.bean.Book">
<property name="bookName" value="水浒传"></property>
</bean>
</array>
</property>
</bean>
<bean id="person13" class="com.njf.spring.bean.Person">
<!-- 给List类型赋值 -->
<property name="books">
<list> <!-- 使用 list标签-->
<bean class="com.njf.spring.bean.Book">
<property name="bookName" value="西游记"></property>
</bean>
<ref bean="book01"></ref>
</list>
</property>
</bean>
<bean id="book01" class="com.njf.spring.bean.Book">
<property name="bookName" value="红楼梦"></property>
</bean>
测试运行:
@Test
public void testSetBeanProp11() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person12 = (Person) ioc.getBean("person12");
System.out.println("person12 = " + person12);
System.out.println(person12.getBooks());
Person person13 = (Person) ioc.getBean("person13");
System.out.println("person13 = " + person13);
System.out.println(person13.getBooks());
}
3、为Set属性赋值
使用 <set> 标签,其他同数组
配置文件:
<bean id="person14" class="com.njf.spring.bean.Person">
<!-- 给 Set 类型赋值 -->
<property name="hobby">
<set>
<value>骑行</value>
<value>爬山</value>
<value>打球</value>
</set>
</property>
</bean>
测试代码:
@Test
public void testSetBeanProp14() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person14 = (Person) ioc.getBean("person14");
System.out.println("person14 = " + person14);
System.out.println(person14.getHobby());
}
4、为 Map 属性赋值
<bean id="person15" class="com.njf.spring.bean.Person">
<!-- 给 Map 类型赋值 -->
<property name="map">
<map>
<!--一个 entry 代码一个键值对-->
<entry key="key01" value="张三"></entry>
<entry key="key02" value="18"></entry>
<entry key="key03" value-ref="book01"></entry>
<entry key="key04">
<bean class="com.njf.spring.bean.Car">
<property name="carName" value="宝马"></property>
</bean>
</entry>
<entry key="key05">
<map></map>
</entry>
<entry>
<key>
<value>key06</value>
</key>
<value>张老师</value>
</entry>
</map>
</property>
</bean>
@Test
public void testSetBeanProp15() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person15 = (Person) ioc.getBean("person15");
System.out.println("person15 = " + person15);
System.out.println(person15.getMap());
}
5、为 Properties 属性赋值
配置文件:
<bean id="person16" class="com.njf.spring.bean.Person">
<property name="properties">
<!-- properties = new Properties() 所有的 k=v 都是String-->
<props>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
测试代码:
@Test
public void testSetBeanProp16() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person16 = (Person) ioc.getBean("person16");
System.out.println("person16 = " + person16);
System.out.println(person16.getProperties());
}
6、utils 名称空间创建一个可以外部引用的集合bean
配置文件:
<util:list id="bookList">
<ref bean="book01"/>
<bean class="com.njf.spring.bean.Book">
<property name="bookName" value="西游记"></property>
</bean>
</util:list>
<util:set id="hobby">
<value>打球</value>
<value>爬山</value>
<value>游泳</value>
</util:set>
<util:map id="map">
<entry>
<key>
<value>20200316</value>
</key>
<value>小黑老师</value>
</entry>
<entry>
<key>
<value>20200317</value>
</key>
<value>小白老师</value>
</entry>
</util:map>
<bean id="person17" class="com.njf.spring.bean.Person">
<property name="books" ref="bookList"></property>
<property name="hobby" ref="hobby"></property>
<property name="map" ref="map"></property>
</bean>
测试代码:
@Test
public void testSetBeanProp17() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person17 = (Person) ioc.getBean("person17");
System.out.println("person17 = " + person17);
System.out.println(person17.getBooks());
System.out.println(person17.getHobby());
System.out.println(person17.getMap());
}
当使用了util名称空间创建的集合对象,可以直接从容器中获取到集合 bean对象。
7、级联属性赋值
给 bean 的级联属性赋值,当一个 bean 中又引用了另外一个 bean,可以为引用的 bean的属性进行赋值。
配置文件:
<bean id="person18" class="com.njf.spring.bean.Person">
<property name="lastName" value="张三"></property>
<property name="car" ref="car01"></property>
<!-- 设置级联属性 -->
<property name="car.carName" value="红旗"></property>
</bean>
测试代码:
/**
* 级联属性可以修改属性的属性,注意:原来的 bean 的值可能会被修改
*/
@Test
public void testSetBeanProp18() {
ApplicationContext ioc = new ClassPathXmlApplicationContext("applicationContext.xml");
Person person18 = (Person) ioc.getBean("person18");
System.out.println("person18 = " + person18);
System.out.println(person18.getCar().getCarName());
Car car01 = (Car) ioc.getBean("car01");
System.out.println(car01.getCarName());
}