Spring的bean管理(XML方式)
一、Bean实例化的方式
- 在Spring通过配置文件创建对象
- bean实例化的三种实现方式
- 使用类的无参构造器创建(默认)
如果类中只有有参构造器,没有无参构造器,在创建类的对象时,若没有传入参数,则会报错; - 使用静态工厂创建
创建静态的方法,返回类对象; - 使用实例工厂创建
(1)先创建工厂对象;(2)再通过工厂对象调用非静态方法创建对象;
- 使用类的无参构造器创建(默认)
二、Bean标签的常用属性
1. id属性:用于给类起名称,不允包含特殊符号;
2. class属性:创建对象所在类的全路径;
3. scop属性:
(1)单例(singleton默认):整个应用中,只创建bean的一个实例;
- 创建了两个对象,但是是两个对象的地址是一样的,说明类对象只创建了一个。
@Test
public void testUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user1 = (User) context.getBean("user");
User user2 = (User) context.getBean("user");
System.out.println(user1);
System.out.println(user2);
}
- 输出结果如下:
com.chuanzhi.spring.User@2d8f65a4
com.chuanzhi.spring.User@2d8f65a4
(2)多例(prototype):每次注入或者通过Spring应用上下文获取时,都会创建一个新的bean实例; (配置Action时需要用到)
- 如果有XML配置文件中声明scope=”prototype”,则创建的对象有多个。如下所示:
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype"></bean>
- 输出结果如下:
com.chuanzhi.spring.User@646d64ab
com.chuanzhi.spring.User@59e5ddf
(3)request:创建对象把对象放到request域里面
(4)session:创建对象把对象放到session域里面
(5)GlobleSession:创建对象把对象放到GlobleSession域里面
三、Bean属性注入
1. 属性注入,即创建对象时向类的属性设置值;
2. 类的属性注入方式:
- set方法注入(重点);
- 有参构造注入;
- 使用接口注入;
3. 在Spring框架里面,只支持前两种方式
(1)使用有参构造进行属性注入
- 第一步 创建类对象
package com.chuanzhi.spring;
public class User {
private String name;
public void add(){
System.out.println("this is user add....."+name);
}
public User(String name) {
this.name = name;
}
public User() {
// TODO Auto-generated constructor stub
}
}
- 第二步 bean1.xml文件配置
<bean id="user" class="com.chuanzhi.spring.User">
<!-- 用有参构造实现属性注入 -->
<constructor-arg value="小王" name="name"></constructor-arg>
</bean>
- 输出结果如下:
com.chuanzhi.spring.User@646d64ab
this is user add.....小王
(2)使用set方法注入属性(重点)
- 第一步 创建类对象
package com.chuanzhi.spring;
public class Book {
private String bookName;
public void setBookName(String bookName) {
this.bookName = bookName;
}
public String getBookName() {
return bookName;
}
public void print() {
System.out.println("书的名字为:" + bookName);
}
}
- 第二步 bean1.xml文件配置
<bean id="book" class="com.chuanzhi.spring.Book">
<!-- 使用set方法注入属性
name属性:类里面定义的属性名称;
value属性:设置属性的具体值;
-->
<property name="bookName" value="《Spring实战》"></property>
</bean>
- 第三步 写测试代码
@Test
public void testUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1);
user1.add();
}
- 输出结果如下:
com.chuanzhi.spring.Book@1c3a4799
书的名字为:《Spring实战》
四、注入对象类型属性
不仅可以注入字符串类型的属性,而且可以注入其他对象类型的属性
- 第一步 创建user类、和book类
user类
package com.chuanzhi.spring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class User {
private String name;
public void add(){
System.out.println("this is user add....."+name);
}
public User(String name) {
this.name = name;
}
public User() {
// TODO Auto-generated constructor stub
}
}
book类
package com.chuanzhi.spring;
public class Book {
private String bookName;
private User user;
public void setBookName(String bookName) {
this.bookName = bookName;
}
public void print() {
System.out.println("书的名字为:" + bookName);
user.add();
}
public void setUser(User user) {
this.user = user;
}
}
- 第二步 bean1.xml文件配置
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype">
<!-- 用有参构造实现属性注入-->
<constructor-arg value="小王" name="name"></constructor-arg>
</bean>
<bean id="book" class="com.chuanzhi.spring.Book">
<!-- 使用set方法注入属性
name属性:类里面定义的属性名称;
value属性:设置属性的具体值;
-->
<property name="bookName" value="《Spring实战》"></property>
<!--
name属性:类里面定义的属性名称;
*因为需要注入的对象不再是字符串类型,是对象类型,所以不再使用value属性
ref属性:ref的值必须是通过bean标签配置中id的值
-->
<property name="user" ref="user"></property>
</bean>
- 第三步 写测试代码
@Test
public void TestBook(){
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
Book book = (Book) context.getBean("book");
System.out.println(book);
book.print();
}
- 输出结果
com.chuanzhi.spring.Book@2d8f65a4
书的名字为:《Spring实战》
this is user add.....小王
五、c-命名空间
c-命名空间是在Spring3.0中引入的,它是在XML中更为简洁地描述构造器参数的方式,要使用它的话,必须要在XML的顶部声明其模式,如下第二行所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:c="http://www.springframework.org/schema/c"
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">
在c-命名空间和模式声明之后,我们就可以使用它来声明构造器参数了,如下所示:
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype"></bean>
<bean id="book" class="com.chuanzhi.spring.Book" c:username-ref="user"></bean>
上面,我们使用了c-命名空间来声明构造器参数,它作为元素的一个属性,这个属性名以“c:”开头,也应时命名空间的前缀,然后是要装配的构造参数名,在此之后是“-ref”,这是一个命名的约定,它会告诉Spring,正在装配一个bean的引用,这个bean的名字是user,而不是字符串类型的字面量“user”!
上面的代码的效果,等同于下面的代码:
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype"></bean>
<bean id="book" class="com.chuanzhi.spring.Book">
<constructor-arg ref="user" name="username"></constructor-arg>
</bean>
六、p-命名空间
p-命名空间是在Spring3.0中引入的,它是在XML中更为简洁地描述构造器参数的方式,要使用它的话,必须要在XML的顶部声明其模式,如下第二行所示:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/c"
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">
在p-命名空间和模式声明之后,我们就可以使用它来声明构造器参数了,如下所示:
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype"></bean>
<bean id="book" class="com.chuanzhi.spring.Book" p:username-ref="user"></bean>
上面,我们使用了p-命名空间来声明构造器参数,它作为元素的一个属性,这个属性名以“p:”开头,也应时命名空间的前缀,然后是要装配的属性名,在此之后是“-ref”,这是一个命名的约定,它会告诉Spring,正在装配一个bean的引用,这个bean的名字是user,而不是字符串类型的字面量“user”!
上面的代码的效果,等同于下面的代码:
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype"></bean>
<bean id="book" class="com.chuanzhi.spring.Book">
<property-arg ref="user" name="username"></property-arg>
</bean>
七、复杂类型属性的注入
- array数组
- list集合
- map集合
properties类型
- 第一步 创建User类对象,并且添加多个复杂类型属性
package com.chuanzhi.spring;
import java.util.List;
import java.util.Map;
import java.util.Properties;
public class User {
private String name;
private String[] array;
private List<String> list;
private Map<String,String> map;
private Properties properties;
public void setName(String name) {
this.name = name;
}
public void setArray(String[] array) {
this.array = array;
}
public void setList(List<String> list) {
this.list = list;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
public void add(){
System.out.println("this is user add....."+name);
System.out.println("array:"+array);
System.out.println("list:"+list);
System.out.println("map:"+map);
System.out.println("properties:"+properties);
}
}
- 第二步 在XML配置文件中为bean注入复杂类型属性
<bean id="user" class="com.chuanzhi.spring.User" scope="prototype">
<!-- 用有参构造实现属性注入-->
<!-- 字符串类型 -->
<property value="小王" name="name"></property>
<!-- 数组 -->
<property name="array">
<list>
<value>小王</value>
<value>小李</value>
<value>小宋</value>
<value>小杨</value>
</list>
</property>
<!-- list集合 -->
<property name="list">
<list>
<value>小马</value>
<value>小力</value>
<value>小奥</value>
</list>
</property>
<!-- map集合 -->
<property name="map">
<map>
<entry key="aa" value="lucy"></entry>
<entry key="bb" value="mary"></entry>
<entry key="cc" value="tom"></entry>
</map>
</property>
<!-- properties类型 -->
<property name="properties">
<props>
<prop key="driverclass">com.mysql.jdbc</prop>
<prop key="username">root</prop>
<prop key="password">123456</prop>
</props>
</property>
</bean>
- 第三步 写测试代码
@Test
public void testUser() {
ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");
User user1 = (User) context.getBean("user");
System.out.println(user1);
user1.add();
}
- 输出结果
com.chuanzhi.spring.User@ea1a8d5
this is user add.....小王
array:[Ljava.lang.String;@1563da5
list:[小马, 小力, 小奥]
map:{aa=lucy, bb=mary, cc=tom}
properties:{password=123456, driverclass=com.mysql.jdbc, username=root}