bean 标签的别名配置
- bean 标签有属性 name,用于定义 bean 的别名。别名可定义多个,使用逗号(,)、分号(😉 或空格( )分隔
Spring配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="default">
<bean id="student" name="stu1 stu2" class="com.tianshi.domain.Student" >
<property name="id" value="1"/>
<property name="name" value="张三"/>
</bean>
<!-- <!–Spring框架的核心配置文件–>-->
<!-- <!–一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象-->
<!-- id 唯一标识-->
<!-- class 类型的具体名称,必须写包名.类名-->
<!-- –>-->
<!--<!– <bean id="student" class="com.tianshi.domain.Student"/>–>-->
<!-- <!–配置静态工厂–>-->
<!--<!– //唯一一个静态工厂(构造注入)–>-->
<!-- <bean id="studentWithStaticFactory" class="com.tianshi.factory.StudentStaticFactory"-->
<!-- factory-method="getStudent">-->
<!-- <!–DI构造注入-->
<!-- 用来确定给哪个属性赋值(可同时使用):-->
<!-- index:参数在构造参数表中的下标,从0开始计数-->
<!-- name:构造方法参数名称-->
<!-- type:构造方法参数类型-->
<!-- 设置属性的值(只用一个):-->
<!-- value:要传入的构造方法参数值(简单类型)-->
<!-- ref:要传入的构造方法参数(引用类型)-->
<!-- 建议用index+name+value/ref完成配置-->
<!-- –>-->
<!-- <constructor-arg index="0" name="id" value="100"/>-->
<!-- <constructor-arg index="1" name="name" value="小明"/>-->
<!-- </bean>-->
<!-- <!–配置实例工厂两个–>-->
<!-- <!–C名称空间注入-->
<!-- 基于参数索引的配置:-->
<!-- c:_索引数="值" 注入简单类型数据值-->
<!-- c:_索引数-ref="bean的id" 注入Spring容器中的其他的bean对象-->
<!-- 基于参数名的配置:-->
<!-- c:参数名="值" 注入简单类型的数据值-->
<!-- c:参数名="bean的id" 注入Spring容器中其他的bean对象-->
<!--–>-->
<!--<!– //第一个实例工厂(C名称空间注入)–>-->
<!-- <bean id="studentFactory1" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <bean id="studentWithInstanceFactory1" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory1" factory-method="getStudent" c:_0="101" c:name="李四"/>-->
<!--<!– //Book的实例工厂–>-->
<!-- <bean id="bookFactory" class="com.tianshi.factory.BookInstanceFactory"/>-->
<!-- <bean id="bookWithInstanceFactory" class="com.tianshi.domain.Book" p:id="1" p:name="空"/>-->
<!--<!– //第二个实例工厂(各种类型的属性注入的配置)–>-->
<!-- <bean id="studentFactory2" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <!–自动装配–>-->
<!-- <!–局部的依赖注入自动装配-->
<!-- 在bean标签中,有属性 autowire,代表是否采用自动装配逻辑。-->
<!-- 可以设置的值:-->
<!-- default : 默认的,此是默认值。默认策略就是全局策略-->
<!-- no : 不使用自动装配逻辑。-->
<!-- byName : 根据名字完成自动装配。当前bean中的property的名字和当前配置文件中bean的id如果一样,则自动注入-->
<!-- 有可能,类型不匹配-->
<!-- byType : 根据类型完成自动装配。当前bean中的property的类型和当前配置文件中bean的类型如有一样,则自动注入-->
<!-- 有可能,当前配置文件中有多个bean的类型和同一个property的类型相同,抛出异常。-->
<!-- 最常用。一般情况下,一个配置文件,不会配置多个同类型bean-->
<!-- constructor : 构造器注入。扫描当前bean类型中的有参数构造方法,扫描构造方法的参数表,-->
<!-- 基于先byType,再byName的顺序逻辑,在当前配置文件中匹配bean对象,调用构造方法注入。-->
<!-- –>-->
<!-- <bean id="studentWithInstanceFactory2" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory2" factory-method="getStudent" autowire="byType">-->
<!-- <property name="id" value="105"/>-->
<!-- <property name="name" value="王"/>-->
<!-- <!–数组array标签,一个标签代表一个数组–>-->
<!-- <property name="hobbies">-->
<!-- <array>-->
<!-- <!–数组中的简单数据,按照属性依次从0开始赋值–>-->
<!-- <value>0下标</value>-->
<!-- <value>1下标</value>-->
<!-- <value>2下标</value>-->
<!-- <!–ref,数组中的一个引用类型数据,按照配置属性依次从0下标开始赋值–>-->
<!-- <!–<ref bean="beanId"></ref>–>-->
<!-- </array>-->
<!-- </property>-->
<!-- <!–List集合,list标签,一个标签代表一个集合对象–>-->
<!-- <property name="books">-->
<!-- <list>-->
<!-- <!–0下标位置对象–>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- <!–配置一个局部的bean对象,不需要命名(不写id),局部有效–>-->
<!-- <bean class="com.tianshi.domain.Book">-->
<!-- <property name="id" value="2"></property>-->
<!-- <property name="name" value="算法导论"/>-->
<!-- </bean>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- </list>-->
<!-- </property>-->
<!-- <!–Set集合,set标签–>-->
<!-- <property name="set">-->
<!-- <set>-->
<!-- <value>set值1</value>-->
<!-- <value>set值2</value>-->
<!-- <value>set值3</value>-->
<!-- </set>-->
<!-- </property>-->
<!-- <!–Map集合,map标签和entry子标签,一个map标签代表一个Map集合一个entry标签代表map中的一个键值对–>-->
<!-- <property name="map">-->
<!-- <map>-->
<!-- <!–entry有属性 key:简单类型键值,key-ref:引用类型键值-->
<!-- value:简单类型value值,value-ref:引用类型value值–>-->
<!-- <entry key="1" value="value1"></entry>-->
<!-- <entry key="2" value="value2"></entry>-->
<!-- <entry key="3" value="value3"></entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- <!–引用类型属性,使用ref注入–>-->
<!--<!– <property name="book" ref="bookWithInstanceFactory"/>–>-->
<!-- </bean>-->
<!-- <!–配置FactoryBean工厂两个–>-->
<!-- <!–设值注入-->
<!-- 标签属性:-->
<!-- name:要注入数据的property属性名-->
<!-- value:为属性赋值(简单数据类型)-->
<!-- ref:为属性赋值(引用数据类型)-->
<!-- –>-->
<!--<!– //第一个FactoryBean工厂(设值注入)–>-->
<!-- <bean id="studentWithFactoryBean1" class="com.tianshi.factory.StudentFactoryBean">-->
<!-- <property name="id" value="102"/>-->
<!-- <property name="name" value="王五"/>-->
<!-- </bean>-->
<!-- <!–P名称空间注入-->
<!-- 仅基于参数名,无基于索引:-->
<!-- p:属性名 = "简单数据"-->
<!-- p:属性名-ref = "引用数据,其他bean标签的id"-->
<!-- –>-->
<!--<!– //第二个FactoryBean工厂(P名称空间注入)–>-->
<!-- <bean id="studentWithFactoryBean2" class="com.tianshi.factory.StudentFactoryBean" p:id="103" p:name="赵六"/>-->
</beans>
测试(自动转换)
java
package com.tianshi.test;
import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class StudentTest {
public static void main(String[] args) {
// //耦合方式管理Student对象
// Student student = new Student();
// student.setId(1);
// student.setName("张三");
// System.out.println(student);
// //通过Spring容器创建Student的对象
// //创建Spring容器,创建的容器指定读取配置文件为类型的构造参数
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// Student student=(Student)applicationContext.getBean("student");
// student.setId(2);
// student.setName("李四");
// System.out.println(student);
//自动转换+别名
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//原始名称
Student student1 = context.getBean("student", Student.class);
System.out.println(student1);
//别名1
Student student2 = context.getBean("stu1",Student.class);
System.out.println(student2);
//别名2
Student student3 = context.getBean("stu2",Student.class);
System.out.println(student3);
System.out.println(student1 == student2);
}
}

bean 标签的所用范围配置--scope 属性
Spring 中 bean 标签有属性 scope,用于定义 bean 的作用范围,常用可选范围如下:
- singleton:单例(默认)
- prototype:非单例
Spring配置
xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="default">
<bean id="student1" name="stu1 stu2" class="com.tianshi.domain.Student" >
<property name="id" value="1"/>
<property name="name" value="单例学生"/>
</bean>
<bean id="student" name="student_" class="com.tianshi.domain.Student" scope="prototype">
<property name="id" value="1"/>
<property name="name" value="多例学生"/>
</bean>
<!-- <!–Spring框架的核心配置文件–>-->
<!-- <!–一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象-->
<!-- id 唯一标识-->
<!-- class 类型的具体名称,必须写包名.类名-->
<!-- –>-->
<!--<!– <bean id="student" class="com.tianshi.domain.Student"/>–>-->
<!-- <!–配置静态工厂–>-->
<!--<!– //唯一一个静态工厂(构造注入)–>-->
<!-- <bean id="studentWithStaticFactory" class="com.tianshi.factory.StudentStaticFactory"-->
<!-- factory-method="getStudent">-->
<!-- <!–DI构造注入-->
<!-- 用来确定给哪个属性赋值(可同时使用):-->
<!-- index:参数在构造参数表中的下标,从0开始计数-->
<!-- name:构造方法参数名称-->
<!-- type:构造方法参数类型-->
<!-- 设置属性的值(只用一个):-->
<!-- value:要传入的构造方法参数值(简单类型)-->
<!-- ref:要传入的构造方法参数(引用类型)-->
<!-- 建议用index+name+value/ref完成配置-->
<!-- –>-->
<!-- <constructor-arg index="0" name="id" value="100"/>-->
<!-- <constructor-arg index="1" name="name" value="小明"/>-->
<!-- </bean>-->
<!-- <!–配置实例工厂两个–>-->
<!-- <!–C名称空间注入-->
<!-- 基于参数索引的配置:-->
<!-- c:_索引数="值" 注入简单类型数据值-->
<!-- c:_索引数-ref="bean的id" 注入Spring容器中的其他的bean对象-->
<!-- 基于参数名的配置:-->
<!-- c:参数名="值" 注入简单类型的数据值-->
<!-- c:参数名="bean的id" 注入Spring容器中其他的bean对象-->
<!--–>-->
<!--<!– //第一个实例工厂(C名称空间注入)–>-->
<!-- <bean id="studentFactory1" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <bean id="studentWithInstanceFactory1" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory1" factory-method="getStudent" c:_0="101" c:name="李四"/>-->
<!--<!– //Book的实例工厂–>-->
<!-- <bean id="bookFactory" class="com.tianshi.factory.BookInstanceFactory"/>-->
<!-- <bean id="bookWithInstanceFactory" class="com.tianshi.domain.Book" p:id="1" p:name="空"/>-->
<!--<!– //第二个实例工厂(各种类型的属性注入的配置)–>-->
<!-- <bean id="studentFactory2" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <!–自动装配–>-->
<!-- <!–局部的依赖注入自动装配-->
<!-- 在bean标签中,有属性 autowire,代表是否采用自动装配逻辑。-->
<!-- 可以设置的值:-->
<!-- default : 默认的,此是默认值。默认策略就是全局策略-->
<!-- no : 不使用自动装配逻辑。-->
<!-- byName : 根据名字完成自动装配。当前bean中的property的名字和当前配置文件中bean的id如果一样,则自动注入-->
<!-- 有可能,类型不匹配-->
<!-- byType : 根据类型完成自动装配。当前bean中的property的类型和当前配置文件中bean的类型如有一样,则自动注入-->
<!-- 有可能,当前配置文件中有多个bean的类型和同一个property的类型相同,抛出异常。-->
<!-- 最常用。一般情况下,一个配置文件,不会配置多个同类型bean-->
<!-- constructor : 构造器注入。扫描当前bean类型中的有参数构造方法,扫描构造方法的参数表,-->
<!-- 基于先byType,再byName的顺序逻辑,在当前配置文件中匹配bean对象,调用构造方法注入。-->
<!-- –>-->
<!-- <bean id="studentWithInstanceFactory2" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory2" factory-method="getStudent" autowire="byType">-->
<!-- <property name="id" value="105"/>-->
<!-- <property name="name" value="王"/>-->
<!-- <!–数组array标签,一个标签代表一个数组–>-->
<!-- <property name="hobbies">-->
<!-- <array>-->
<!-- <!–数组中的简单数据,按照属性依次从0开始赋值–>-->
<!-- <value>0下标</value>-->
<!-- <value>1下标</value>-->
<!-- <value>2下标</value>-->
<!-- <!–ref,数组中的一个引用类型数据,按照配置属性依次从0下标开始赋值–>-->
<!-- <!–<ref bean="beanId"></ref>–>-->
<!-- </array>-->
<!-- </property>-->
<!-- <!–List集合,list标签,一个标签代表一个集合对象–>-->
<!-- <property name="books">-->
<!-- <list>-->
<!-- <!–0下标位置对象–>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- <!–配置一个局部的bean对象,不需要命名(不写id),局部有效–>-->
<!-- <bean class="com.tianshi.domain.Book">-->
<!-- <property name="id" value="2"></property>-->
<!-- <property name="name" value="算法导论"/>-->
<!-- </bean>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- </list>-->
<!-- </property>-->
<!-- <!–Set集合,set标签–>-->
<!-- <property name="set">-->
<!-- <set>-->
<!-- <value>set值1</value>-->
<!-- <value>set值2</value>-->
<!-- <value>set值3</value>-->
<!-- </set>-->
<!-- </property>-->
<!-- <!–Map集合,map标签和entry子标签,一个map标签代表一个Map集合一个entry标签代表map中的一个键值对–>-->
<!-- <property name="map">-->
<!-- <map>-->
<!-- <!–entry有属性 key:简单类型键值,key-ref:引用类型键值-->
<!-- value:简单类型value值,value-ref:引用类型value值–>-->
<!-- <entry key="1" value="value1"></entry>-->
<!-- <entry key="2" value="value2"></entry>-->
<!-- <entry key="3" value="value3"></entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- <!–引用类型属性,使用ref注入–>-->
<!--<!– <property name="book" ref="bookWithInstanceFactory"/>–>-->
<!-- </bean>-->
<!-- <!–配置FactoryBean工厂两个–>-->
<!-- <!–设值注入-->
<!-- 标签属性:-->
<!-- name:要注入数据的property属性名-->
<!-- value:为属性赋值(简单数据类型)-->
<!-- ref:为属性赋值(引用数据类型)-->
<!-- –>-->
<!--<!– //第一个FactoryBean工厂(设值注入)–>-->
<!-- <bean id="studentWithFactoryBean1" class="com.tianshi.factory.StudentFactoryBean">-->
<!-- <property name="id" value="102"/>-->
<!-- <property name="name" value="王五"/>-->
<!-- </bean>-->
<!-- <!–P名称空间注入-->
<!-- 仅基于参数名,无基于索引:-->
<!-- p:属性名 = "简单数据"-->
<!-- p:属性名-ref = "引用数据,其他bean标签的id"-->
<!-- –>-->
<!--<!– //第二个FactoryBean工厂(P名称空间注入)–>-->
<!-- <bean id="studentWithFactoryBean2" class="com.tianshi.factory.StudentFactoryBean" p:id="103" p:name="赵六"/>-->
</beans>
测试
java
package com.tianshi.test;
import com.tianshi.domain.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class StudentTest {
public static void main(String[] args) {
// //耦合方式管理Student对象
// Student student = new Student();
// student.setId(1);
// student.setName("张三");
// System.out.println(student);
// //通过Spring容器创建Student的对象
// //创建Spring容器,创建的容器指定读取配置文件为类型的构造参数
// ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
// Student student=(Student)applicationContext.getBean("student");
// student.setId(2);
// student.setName("李四");
// System.out.println(student);
//自动转换+别名
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//原始名称
Student student1 = context.getBean("student1", Student.class);
System.out.println(student1);
//别名1
Student student2 = context.getBean("stu1",Student.class);
System.out.println(student2);
//别名2
Student student3 = context.getBean("stu2",Student.class);
System.out.println(student3);
System.out.println(student1 == student2);
System.out.println(student2 == student3);
//非单例
Student student4 = context.getBean("student",Student.class);
System.out.println(student4);
//非单例别名
Student student5 = context.getBean("student_",Student.class);
System.out.println(student5);
System.out.println(student4 == student5);
}
}

Spring 为什么 bean 默认是单例的?
- 适合交给容器进行管理的 bean
- 表现层对象
- 业务层对象
- 数据层对象
- 工具对象
- 不适合交给容器进行管理的 bean
- 封装实体的域对象
bean 的生命周期
- 生命周期:从创建到消亡的完整过程
- bean 生命周期:bean 从创建到销毁的整体过程
- bean 生命周期控制:在 bean 创建后到销毁前做一些事情
- Spring 中 bean 的生命周期具体如下:
- 初始化容器
- 创建对象(内存分配)
- 执行构造方法
- 执行属性注入(set 操作)
- 执行 bean 初始化方法
- 使用 bean
- 执行业务操作
- 关闭/销毁容器
- 执行 bean 销毁方法
- 初始化容器
上述所有步骤中,还未接触到的初始化和销毁两个过程(即 bean 的生命周期控制方法)Spring 中的生命周期控制方法也是有两种实现方案,分别是:自定义、实现与标准接口实现
自定义实现声明周期控制方法
实体类
java
package com.tianshi.domain;
public class Book {
private Integer id;
private String name;
public Book() {
}
public Book(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer id() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String name() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 初始化方法
* 不要有返回值,不要有参数表。
*/
public void init(){
System.out.println("Book类型初始化方法运行。。。。。");
}
/**
* 销毁方法|回收资源方法
* 不要有返回值,不要有参数表。
*/
public void destroy(){
System.out.println("Book类型销毁方法运行。。。。。。");
}
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Spring配置
java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="default">
<bean id="book" init-method="init" destroy-method="destroy" class="com.tianshi.domain.Book">
<property name="id" value="100"/>
<property name="name" value="spring in action"/>
</bean>
<!-- <bean id="student1" name="stu1 stu2" class="com.tianshi.domain.Student" >-->
<!-- <property name="id" value="1"/>-->
<!-- <property name="name" value="单例学生"/>-->
<!-- </bean>-->
<!-- <bean id="student" name="student_" class="com.tianshi.domain.Student" scope="prototype">-->
<!-- <property name="id" value="1"/>-->
<!-- <property name="name" value="多例学生"/>-->
<!-- </bean>-->
<!--
标签常用属性:
name: 别名,给bean增加别名。功能和id相同。一个标签id唯一。name可以定义若干个。
别名的值要求全局唯一。定义多个别名,可以使用符合分割。常用 ',' ' '。
现在使用的不多。曾经struts框架流行的时候常用。
scope : 作用域。可以赋予的值只有 singleton 和 prototype
singleton, 单例的。Spring IoC容器启动的时候自动创建bean对象,且仅创建唯一一次。默认
prototype, 多例的。IoC容器启动时不创建对象,每次调用geBean方法时,创建一个对象。
init-method : 初始化方法。在对象创建完成,设置注入完成后,getBean获取对象前,运行。
初始化逻辑,会在容器创建完成时,就已完成。
destroy-method : 销毁方法。在容器关闭|销毁前执行。
-->
<!-- <!–Spring框架的核心配置文件–>-->
<!-- <!–一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象-->
<!-- id 唯一标识-->
<!-- class 类型的具体名称,必须写包名.类名-->
<!-- –>-->
<!--<!– <bean id="student" class="com.tianshi.domain.Student"/>–>-->
<!-- <!–配置静态工厂–>-->
<!--<!– //唯一一个静态工厂(构造注入)–>-->
<!-- <bean id="studentWithStaticFactory" class="com.tianshi.factory.StudentStaticFactory"-->
<!-- factory-method="getStudent">-->
<!-- <!–DI构造注入-->
<!-- 用来确定给哪个属性赋值(可同时使用):-->
<!-- index:参数在构造参数表中的下标,从0开始计数-->
<!-- name:构造方法参数名称-->
<!-- type:构造方法参数类型-->
<!-- 设置属性的值(只用一个):-->
<!-- value:要传入的构造方法参数值(简单类型)-->
<!-- ref:要传入的构造方法参数(引用类型)-->
<!-- 建议用index+name+value/ref完成配置-->
<!-- –>-->
<!-- <constructor-arg index="0" name="id" value="100"/>-->
<!-- <constructor-arg index="1" name="name" value="小明"/>-->
<!-- </bean>-->
<!-- <!–配置实例工厂两个–>-->
<!-- <!–C名称空间注入-->
<!-- 基于参数索引的配置:-->
<!-- c:_索引数="值" 注入简单类型数据值-->
<!-- c:_索引数-ref="bean的id" 注入Spring容器中的其他的bean对象-->
<!-- 基于参数名的配置:-->
<!-- c:参数名="值" 注入简单类型的数据值-->
<!-- c:参数名="bean的id" 注入Spring容器中其他的bean对象-->
<!--–>-->
<!--<!– //第一个实例工厂(C名称空间注入)–>-->
<!-- <bean id="studentFactory1" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <bean id="studentWithInstanceFactory1" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory1" factory-method="getStudent" c:_0="101" c:name="李四"/>-->
<!--<!– //Book的实例工厂–>-->
<!-- <bean id="bookFactory" class="com.tianshi.factory.BookInstanceFactory"/>-->
<!-- <bean id="bookWithInstanceFactory" class="com.tianshi.domain.Book" p:id="1" p:name="空"/>-->
<!--<!– //第二个实例工厂(各种类型的属性注入的配置)–>-->
<!-- <bean id="studentFactory2" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <!–自动装配–>-->
<!-- <!–局部的依赖注入自动装配-->
<!-- 在bean标签中,有属性 autowire,代表是否采用自动装配逻辑。-->
<!-- 可以设置的值:-->
<!-- default : 默认的,此是默认值。默认策略就是全局策略-->
<!-- no : 不使用自动装配逻辑。-->
<!-- byName : 根据名字完成自动装配。当前bean中的property的名字和当前配置文件中bean的id如果一样,则自动注入-->
<!-- 有可能,类型不匹配-->
<!-- byType : 根据类型完成自动装配。当前bean中的property的类型和当前配置文件中bean的类型如有一样,则自动注入-->
<!-- 有可能,当前配置文件中有多个bean的类型和同一个property的类型相同,抛出异常。-->
<!-- 最常用。一般情况下,一个配置文件,不会配置多个同类型bean-->
<!-- constructor : 构造器注入。扫描当前bean类型中的有参数构造方法,扫描构造方法的参数表,-->
<!-- 基于先byType,再byName的顺序逻辑,在当前配置文件中匹配bean对象,调用构造方法注入。-->
<!-- –>-->
<!-- <bean id="studentWithInstanceFactory2" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory2" factory-method="getStudent" autowire="byType">-->
<!-- <property name="id" value="105"/>-->
<!-- <property name="name" value="王"/>-->
<!-- <!–数组array标签,一个标签代表一个数组–>-->
<!-- <property name="hobbies">-->
<!-- <array>-->
<!-- <!–数组中的简单数据,按照属性依次从0开始赋值–>-->
<!-- <value>0下标</value>-->
<!-- <value>1下标</value>-->
<!-- <value>2下标</value>-->
<!-- <!–ref,数组中的一个引用类型数据,按照配置属性依次从0下标开始赋值–>-->
<!-- <!–<ref bean="beanId"></ref>–>-->
<!-- </array>-->
<!-- </property>-->
<!-- <!–List集合,list标签,一个标签代表一个集合对象–>-->
<!-- <property name="books">-->
<!-- <list>-->
<!-- <!–0下标位置对象–>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- <!–配置一个局部的bean对象,不需要命名(不写id),局部有效–>-->
<!-- <bean class="com.tianshi.domain.Book">-->
<!-- <property name="id" value="2"></property>-->
<!-- <property name="name" value="算法导论"/>-->
<!-- </bean>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- </list>-->
<!-- </property>-->
<!-- <!–Set集合,set标签–>-->
<!-- <property name="set">-->
<!-- <set>-->
<!-- <value>set值1</value>-->
<!-- <value>set值2</value>-->
<!-- <value>set值3</value>-->
<!-- </set>-->
<!-- </property>-->
<!-- <!–Map集合,map标签和entry子标签,一个map标签代表一个Map集合一个entry标签代表map中的一个键值对–>-->
<!-- <property name="map">-->
<!-- <map>-->
<!-- <!–entry有属性 key:简单类型键值,key-ref:引用类型键值-->
<!-- value:简单类型value值,value-ref:引用类型value值–>-->
<!-- <entry key="1" value="value1"></entry>-->
<!-- <entry key="2" value="value2"></entry>-->
<!-- <entry key="3" value="value3"></entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- <!–引用类型属性,使用ref注入–>-->
<!--<!– <property name="book" ref="bookWithInstanceFactory"/>–>-->
<!-- </bean>-->
<!-- <!–配置FactoryBean工厂两个–>-->
<!-- <!–设值注入-->
<!-- 标签属性:-->
<!-- name:要注入数据的property属性名-->
<!-- value:为属性赋值(简单数据类型)-->
<!-- ref:为属性赋值(引用数据类型)-->
<!-- –>-->
<!--<!– //第一个FactoryBean工厂(设值注入)–>-->
<!-- <bean id="studentWithFactoryBean1" class="com.tianshi.factory.StudentFactoryBean">-->
<!-- <property name="id" value="102"/>-->
<!-- <property name="name" value="王五"/>-->
<!-- </bean>-->
<!-- <!–P名称空间注入-->
<!-- 仅基于参数名,无基于索引:-->
<!-- p:属性名 = "简单数据"-->
<!-- p:属性名-ref = "引用数据,其他bean标签的id"-->
<!-- –>-->
<!--<!– //第二个FactoryBean工厂(P名称空间注入)–>-->
<!-- <bean id="studentWithFactoryBean2" class="com.tianshi.factory.StudentFactoryBean" p:id="103" p:name="赵六"/>-->
</beans>
测试
java
package com.tianshi.test;
import com.tianshi.domain.Book;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
}
}
经测试发现,销毁方法并没有执行,这是 Spring 框架机制的问题,原因是 Spring 定义了,只有在容器关闭前才会触发 bean 的销毁。那么关闭容器的方式有:
- 手工关闭容器
- ConfigurableApplicationContext 接口 close()操作
- 注册关闭钩子,在虚拟机退出前先关闭容器再退出虚拟机
- ConfigurableApplicationContext 接口 registerShutdownHook()操作

- ConfigurableApplicationContext 接口 registerShutdownHook()操作
修改测试代码再次测试
java
package com.tianshi.test;
import com.tianshi.domain.Book;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookTest {
public static void main(String[] args) {
// ConfigurableApplicationContext是ApplicationContext接口的子接口
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
// 手工关闭容器。关闭容器的时候,Spring会先销毁bean对象。如果bean配置了销毁方法,先运行销毁方法,后销毁对象
// context.close();
// 注册关闭任务。通知Spring框架,当JVM关闭的时候,先关闭容器
context.registerShutdownHook();
}
}
两种方式均能够成功

标准接口实现生命周期控制方法
实体类
java
package com.tianshi.domain;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import java.io.Serializable;
public class Book implements Serializable, InitializingBean, DisposableBean {
private Integer id;
private String name;
public Book() {
}
public Book(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer id() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String name() {
return name;
}
public void setName(String name) {
this.name = name;
}
/**
* 标准接口:初始化在属性完成后要做什么
* @throws Exception
*/
public void afterPropertiesSet() throws Exception {
System.out.println("基于Spring接口完成初始化。。。");
}
/**
* 标准接口:销毁
* @throws Exception
*/
public void destroy() throws Exception {
System.out.println("基于Spring接口完成销毁。。。");
}
/**
* 初始化方法
* 不要有返回值,不要有参数表。
*/
// public void init(){
// System.out.println("Book类型初始化方法运行。。。。。");
// }
/**
* 销毁方法|回收资源方法
* 不要有返回值,不要有参数表。
*/
// public void destroy(){
// System.out.println("Book类型销毁方法运行。。。。。。");
// }
@Override
public String toString() {
return "Book{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
Spring配置
- 采用 Spring 框架提供的标准接口来完成生命周期的控制,可以省略对应的配置内容
- 虽然配置省略了,但是代码和 Spring 框架耦合在一起,不利于后续代码的维护,不推 荐使用
java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd"
default-autowire="default">
<bean id="book" class="com.tianshi.domain.Book">
<!-- init-method="init" destroy-method="destroy"-->
<property name="id" value="100"/>
<property name="name" value="spring in action"/>
</bean>
<!-- <bean id="student1" name="stu1 stu2" class="com.tianshi.domain.Student" >-->
<!-- <property name="id" value="1"/>-->
<!-- <property name="name" value="单例学生"/>-->
<!-- </bean>-->
<!-- <bean id="student" name="student_" class="com.tianshi.domain.Student" scope="prototype">-->
<!-- <property name="id" value="1"/>-->
<!-- <property name="name" value="多例学生"/>-->
<!-- </bean>-->
<!--
标签常用属性:
name: 别名,给bean增加别名。功能和id相同。一个标签id唯一。name可以定义若干个。
别名的值要求全局唯一。定义多个别名,可以使用符合分割。常用 ',' ' '。
现在使用的不多。曾经struts框架流行的时候常用。
scope : 作用域。可以赋予的值只有 singleton 和 prototype
singleton, 单例的。Spring IoC容器启动的时候自动创建bean对象,且仅创建唯一一次。默认
prototype, 多例的。IoC容器启动时不创建对象,每次调用geBean方法时,创建一个对象。
init-method : 初始化方法。在对象创建完成,设置注入完成后,getBean获取对象前,运行。
初始化逻辑,会在容器创建完成时,就已完成。
destroy-method : 销毁方法。在容器关闭|销毁前执行。
-->
<!-- <!–Spring框架的核心配置文件–>-->
<!-- <!–一个bean标签就是一个domain对象,让Spring框架帮忙创建管理这个对象-->
<!-- id 唯一标识-->
<!-- class 类型的具体名称,必须写包名.类名-->
<!-- –>-->
<!--<!– <bean id="student" class="com.tianshi.domain.Student"/>–>-->
<!-- <!–配置静态工厂–>-->
<!--<!– //唯一一个静态工厂(构造注入)–>-->
<!-- <bean id="studentWithStaticFactory" class="com.tianshi.factory.StudentStaticFactory"-->
<!-- factory-method="getStudent">-->
<!-- <!–DI构造注入-->
<!-- 用来确定给哪个属性赋值(可同时使用):-->
<!-- index:参数在构造参数表中的下标,从0开始计数-->
<!-- name:构造方法参数名称-->
<!-- type:构造方法参数类型-->
<!-- 设置属性的值(只用一个):-->
<!-- value:要传入的构造方法参数值(简单类型)-->
<!-- ref:要传入的构造方法参数(引用类型)-->
<!-- 建议用index+name+value/ref完成配置-->
<!-- –>-->
<!-- <constructor-arg index="0" name="id" value="100"/>-->
<!-- <constructor-arg index="1" name="name" value="小明"/>-->
<!-- </bean>-->
<!-- <!–配置实例工厂两个–>-->
<!-- <!–C名称空间注入-->
<!-- 基于参数索引的配置:-->
<!-- c:_索引数="值" 注入简单类型数据值-->
<!-- c:_索引数-ref="bean的id" 注入Spring容器中的其他的bean对象-->
<!-- 基于参数名的配置:-->
<!-- c:参数名="值" 注入简单类型的数据值-->
<!-- c:参数名="bean的id" 注入Spring容器中其他的bean对象-->
<!--–>-->
<!--<!– //第一个实例工厂(C名称空间注入)–>-->
<!-- <bean id="studentFactory1" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <bean id="studentWithInstanceFactory1" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory1" factory-method="getStudent" c:_0="101" c:name="李四"/>-->
<!--<!– //Book的实例工厂–>-->
<!-- <bean id="bookFactory" class="com.tianshi.factory.BookInstanceFactory"/>-->
<!-- <bean id="bookWithInstanceFactory" class="com.tianshi.domain.Book" p:id="1" p:name="空"/>-->
<!--<!– //第二个实例工厂(各种类型的属性注入的配置)–>-->
<!-- <bean id="studentFactory2" class="com.tianshi.factory.StudentInstanceFactory"/>-->
<!-- <!–自动装配–>-->
<!-- <!–局部的依赖注入自动装配-->
<!-- 在bean标签中,有属性 autowire,代表是否采用自动装配逻辑。-->
<!-- 可以设置的值:-->
<!-- default : 默认的,此是默认值。默认策略就是全局策略-->
<!-- no : 不使用自动装配逻辑。-->
<!-- byName : 根据名字完成自动装配。当前bean中的property的名字和当前配置文件中bean的id如果一样,则自动注入-->
<!-- 有可能,类型不匹配-->
<!-- byType : 根据类型完成自动装配。当前bean中的property的类型和当前配置文件中bean的类型如有一样,则自动注入-->
<!-- 有可能,当前配置文件中有多个bean的类型和同一个property的类型相同,抛出异常。-->
<!-- 最常用。一般情况下,一个配置文件,不会配置多个同类型bean-->
<!-- constructor : 构造器注入。扫描当前bean类型中的有参数构造方法,扫描构造方法的参数表,-->
<!-- 基于先byType,再byName的顺序逻辑,在当前配置文件中匹配bean对象,调用构造方法注入。-->
<!-- –>-->
<!-- <bean id="studentWithInstanceFactory2" class="com.tianshi.domain.Student"-->
<!-- factory-bean="studentFactory2" factory-method="getStudent" autowire="byType">-->
<!-- <property name="id" value="105"/>-->
<!-- <property name="name" value="王"/>-->
<!-- <!–数组array标签,一个标签代表一个数组–>-->
<!-- <property name="hobbies">-->
<!-- <array>-->
<!-- <!–数组中的简单数据,按照属性依次从0开始赋值–>-->
<!-- <value>0下标</value>-->
<!-- <value>1下标</value>-->
<!-- <value>2下标</value>-->
<!-- <!–ref,数组中的一个引用类型数据,按照配置属性依次从0下标开始赋值–>-->
<!-- <!–<ref bean="beanId"></ref>–>-->
<!-- </array>-->
<!-- </property>-->
<!-- <!–List集合,list标签,一个标签代表一个集合对象–>-->
<!-- <property name="books">-->
<!-- <list>-->
<!-- <!–0下标位置对象–>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- <!–配置一个局部的bean对象,不需要命名(不写id),局部有效–>-->
<!-- <bean class="com.tianshi.domain.Book">-->
<!-- <property name="id" value="2"></property>-->
<!-- <property name="name" value="算法导论"/>-->
<!-- </bean>-->
<!-- <ref bean="bookWithInstanceFactory"></ref>-->
<!-- </list>-->
<!-- </property>-->
<!-- <!–Set集合,set标签–>-->
<!-- <property name="set">-->
<!-- <set>-->
<!-- <value>set值1</value>-->
<!-- <value>set值2</value>-->
<!-- <value>set值3</value>-->
<!-- </set>-->
<!-- </property>-->
<!-- <!–Map集合,map标签和entry子标签,一个map标签代表一个Map集合一个entry标签代表map中的一个键值对–>-->
<!-- <property name="map">-->
<!-- <map>-->
<!-- <!–entry有属性 key:简单类型键值,key-ref:引用类型键值-->
<!-- value:简单类型value值,value-ref:引用类型value值–>-->
<!-- <entry key="1" value="value1"></entry>-->
<!-- <entry key="2" value="value2"></entry>-->
<!-- <entry key="3" value="value3"></entry>-->
<!-- </map>-->
<!-- </property>-->
<!-- <!–引用类型属性,使用ref注入–>-->
<!--<!– <property name="book" ref="bookWithInstanceFactory"/>–>-->
<!-- </bean>-->
<!-- <!–配置FactoryBean工厂两个–>-->
<!-- <!–设值注入-->
<!-- 标签属性:-->
<!-- name:要注入数据的property属性名-->
<!-- value:为属性赋值(简单数据类型)-->
<!-- ref:为属性赋值(引用数据类型)-->
<!-- –>-->
<!--<!– //第一个FactoryBean工厂(设值注入)–>-->
<!-- <bean id="studentWithFactoryBean1" class="com.tianshi.factory.StudentFactoryBean">-->
<!-- <property name="id" value="102"/>-->
<!-- <property name="name" value="王五"/>-->
<!-- </bean>-->
<!-- <!–P名称空间注入-->
<!-- 仅基于参数名,无基于索引:-->
<!-- p:属性名 = "简单数据"-->
<!-- p:属性名-ref = "引用数据,其他bean标签的id"-->
<!-- –>-->
<!--<!– //第二个FactoryBean工厂(P名称空间注入)–>-->
<!-- <bean id="studentWithFactoryBean2" class="com.tianshi.factory.StudentFactoryBean" p:id="103" p:name="赵六"/>-->
</beans>
测试
java
package com.tianshi.test;
import com.tianshi.domain.Book;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookTest {
public static void main(String[] args) {
// ConfigurableApplicationContext是ApplicationContext接口的子接口
ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Book book = context.getBean("book", Book.class);
System.out.println(book);
// 手工关闭容器。关闭容器的时候,Spring会先销毁bean对象。如果bean配置了销毁方法,先运行销毁方法,后销毁对象
context.close();
// 注册关闭任务。通知Spring框架,当JVM关闭的时候,先关闭容器
// context.registerShutdownHook();
}
}
