1.Spring DI(依赖注入)的实现方式:属性注入和构造注入
依赖注入(Dependency Injection,DI)和控制反转含义相同,它们是从两个角度描述的同一个概念。
当某个 Java 实例需要另一个 Java 实例时,传统的方法是由调用者创建被调用者的实例(例如,使用 new 关键字
获得被调用者实例),而使用 Spring 框架后,被调用者的实例不再由调用者创建,而是由 Spring 容器创建,这称为控
制反转。
Spring 容器在创建被调用者的实例时,会自动将调用者需要的对象实例注入给调用者,这样,调用者通过 Spring
容器获得被调用者实例,这称为依赖注入。
被调用者
public class Person{
}
调用者
public class Student{
//被调用者---依赖对象
private Person person;
public void getPerson(){
person=new Person();
}
}
当某个 Java 实例【Student】需要另一个 Java 实例【Person】,Spring 容器在创建被调用者的实例【Person】时
会自动将调用者需要的对象实例【Person】注入给调用者【Student】,这样调用者【Student】通过 Spring 容器获得被
调用者【Person】实例,这称为依赖注入。
依赖注入主要有两种实现方式,分别是属性 setter 注入和构造方法注入。具体介绍如下。
1)属性 setter 注入--Set方法注入
指 IoC 容器使用 setter 方法注入被依赖的实例。通过调用无参构造器或无参 static 工厂方法实例化 bean 后,调用该
bean 的 setter 方法,即可实现基于 setter 的 DI。
1.创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建被调用者类
package com.wangxing.springdemo2;
public class Person {
public void testPerson(){
System.out.println("Person类的实例方法testPerson()");
}
}
3.创建调用者类
package com.wangxing.springdemo2;
public class Student {
//定义依赖对象
private Person person;
//依赖对象的set方法
public void setPerson(Person person) {
this.person = person;
}
public void getStudent(){
System.out.println("Student类的实例方法getStudent()");
person.testPerson();
}
}
4..配置Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--创建Person类对象-->
<bean id="per" class="com.wangxing.springdemo2.Person"></bean>
<!--创建Student类对象-->
<bean id="student" class="com.wangxing.springdemo2.Student">
<!--setter注入-->
<property name="person" ref="per"></property>
</bean>
</beans>
5.创建单元测试
package com.wangxing.springdemo2;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void test1(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
//字符串参数是配置文件中student对象的id属性的值
Student student=applicationContext.getBean("student",Student.class);
student.getStudent();
}
}
2)构造方法注入
指 IoC 容器使用构造方法注入被依赖的实例。基于构造器的 DI 通过调用带参数的构造方法实现,每个参数代表一个依赖。
1创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建被调用者类
package com.wangxing.springdemo3;
public class Person {
public void testPerson(){
System.out.println( "Person类的实例方法testPerson()" );
}
}
3.创建调用者类
package com.wangxing.springdemo3;
public class Student {
//定义依赖对象
private Person person;
//依赖对象的set方法
public Student(Person person){
this.person=person;
}
public void getStudent(){
System.out.println("Student类的实例方法getStudent()");
person.testPerson();
}
}
4.创建spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--创建Person类对象-->
<bean id="per" class="com.wangxing.springdemo3.Person"></bean>
<!--创建Student类对象-->
<bean id="student" class="com.wangxing.springdemo3.Student">
<!--构造方法注入-->
<constructor-arg index="0" ref="per"></constructor-arg>
</bean>
</beans>
5.创建测试方法
package com.wangxing.springdemo3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue(){
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student=applicationContext.getBean("student",Student.class);
student.getStudent();
}
}
2.Spring Bean的配置及常用属性
作为 Spring 核心机制的依赖注入,改变了传统的编程习惯,对组件的实例化不再由应用程序完成,转而交由 Spring 容器完
成,在需要时注入应用程序中,从而对组件之间依赖关系进行了解耦。这一切都离不开 Spring 配置文件中使用的 <bean> 元素。
Spring 容器可以被看作一个大工厂,而 Spring 容器中的 Bean 就相当于该工厂的产品。如果希望这个大工厂能够生产和管理
Bean,这时则需要告诉容器需要哪些 Bean,以及需要以何种方式将这些 Bean 装配到一起。
Spring 配置文件支持两种不同的格式,分别是 XML 文件格式和 Properties 文件格式。
通常情况下,Spring 会以 XML 文件格式作为 Spring 的配置文件,这种配置方式通过 XML 文件注册并管理 Bean 之间的
依赖关系。
XML 格式配置文件的根元素是 <beans>,该元素包含了多个 <bean> 子元素,每一个 <bean> 子元素定义了一个 Bean,并
描述了该 Bean 如何被装配到 Spring 容器中。
定义 Bean 的示例代码如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--创建Person类对象-->
<bean name="per" class="com.wangxing.springtest3.Person"></bean>
<!--创建Student类对象-->
<bean id="stu" class="com.wangxing.springtest3.Student">
<!--构造方法注入-->
<constructor-arg index="0" ref="per"></constructor-arg>
</bean>
</beans>
在上述代码中,分别使用 id 和 name 属性定义了两个 Bean,并使用 class 元素指定了 Bean 对应的实现类。
<bean> 元素中包含很多属性,其常用属性如表 1 所示。
表 1 <bean>元素的常用属性 | |
属性名称 | 描述 |
id | 是一个 Bean 的唯一标识符,Spring 容器对 Bean 的配置和管理都通过该属性完成 |
name | Spring 容器同样可以通过此属性对容器中的 Bean 进行配置和管理,name 属性中可以为 Bean 指定多个名称,每个名称之间用逗号或分号隔开 |
class | 该属性指定了 Bean 的具体实现类,它必须是一个完整的类名,使用类的全限定名【反射机制】 |
scope | 用于设定 Bean 实例的作用域,其属性值有 singleton(单例)、prototype(原型)、request、session 和 global Session。其默认值是 singleton |
constructor-arg | <bean>元素的子元素,可以使用此元素传入构造参数进行实例化。该元素的 index 属性指定构造参数的序号(从 0 开始),type 属性指定构造参数的类型 |
property | <bean>元素的子元素,用于调用 Bean 实例中的 Set 方法完成属性赋值,从而完成依赖注入。该元素的 name 属性指定 Bean 实例中的相应属性名 |
ref | <property> 和 <constructor-arg> 等元素的子元索,该元素中的 bean 属性用于指定对 Bean 工厂中某个 Bean 实例的引用 |
value | <property> 和 <constractor-arg> 等元素的子元素,用于直接指定一个常量值 |
list | 用于封装 List 或数组类型的依赖注入 |
set | 用于封装 Set 类型属性的依赖注入 |
map | 用于封装 Map 类型属性的依赖注入 |
entry | <map> 元素的子元素,用于设置一个键值对。其 key 属性指定字符串类型的键值,ref 或 value 子元素指定其值 |
3.Spring实例化Bean的三种方法
在面向对象的程序中,要想调用某个类的成员方法,就需要先实例化该类的对象。在 Spring 中,实例化 Bean 有三
种方式,分别是构造器实例化、静态工厂方式实例化和实例工厂方式实例化。本节将针对这三种方式分别进行讲解。
构造器实例化
构造器实例化是指 Spring 容器通过 Bean 对应的类中默认的构造函数实例化 Bean。下面通过案例演示如何使用构造
器实例化 Bean。
1创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建Person类
package com.wangxing.createbean;
public class Person {
public void testPerson() {
System.out.println( "Person类的testPerson()实例方法" );
}
}
3.创建Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!-- bean的第一种创建方法-->
<bean id="person" class="com.wangxing.createbean.Person"></bean>
</beans>
4.测试方法
package com.wangxing.createbean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Person person=applicationContext.getBean("person",Person.class);
person.testPerson();
}
}
静态工厂方式实例化
在 Spring 中,也可以使用静态工厂的方式实例化 Bean。此种方式需要提供一个静态工厂方法创建 Bean 的实例。
1创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建UserBean 类
package com.wangxing.createbean;
public class UserBean {
public void testUser() {
System.out.println( "UserBean类的testUser()实例方法" );
}
}
3.创建静态工厂类,并在该静态工厂类中创建一个返回UserBean类对象的名为getUserBean的静态方法,用于创建 Bean 的实例,如下所示。
package com.wangxing.createbean;
/**
* 静态工厂类
*/
public class MyBeanStaticFactory {
//4.创建一个返回UserBean类对象的名为getUserBean的静态方法
public static UserBean getUserBean(){
return new UserBean();
}
}
4.创建 Spring 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="user" class="com.wangxing.createbean.MyBeanStaticFactory" factory-method="getUserBean"></bean>
</beans>
5.测试方法
package com.wangxing.createbean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
UserBean userBean=applicationContext.getBean("user",UserBean.class);
userBean.testUser();
}
}
实例工厂方式实例化
在 Spring 中,还有一种实例化 Bean 的方式就是采用实例工厂。在这种方式中,工厂类不再使用静态方法创建 Bean 的实
例,而是直接在成员方法中创建 Bean 的实例。
同时,在配置文件中,需要实例化的 Bean 也不是通过 class 属性直接指向其实例化的类,而是通过 factory-bean 属性配置
一个实例工厂,然后使用 factory-method 属性确定使用工厂中的哪个方法。下面通过案例演示实例工厂方式的使用。
1创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建Student类
package com.wangxing.createbean;
public class Student {
public void testStudent(){
System.out.println("Student类的testStudent()实例方法");
}
}
3.创建一个名为 MyBeanFactory 的实例工厂类,在该类中创建一个返回Student类对象的实例方法。
package com.wangxing.createbean;
/**
* 实例工厂类
*/
public class MyBeanFactory {
//返回Student类对象的实例方法
public Student getStudent(){
return new Student();
}
}
4.创建 Spring 配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<!--创建实例工厂类对象-->
<bean id="myBeanFactory" class="com.wangxing.createbean.MyBeanFactory"></bean>
<!--创建Student类对象-->
<bean id="student" factory-bean="myBeanFactory" factory-method="getStudent"></bean>
</beans>
上述代码中,首先配置了一个实例工厂 Bean【myBeanFactory】,然后配置了需要实例化的 Bean。在 id 为 student的 Bean
中,使用 factory-bean 属性指定一个实例工厂,该属性值就是实例工厂的 id 属性值。使用 factory-method 属性确定使用工厂中的
getStudent() 方法。
5. 创建测试类
package com.wangxing.createbean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
Student student=applicationContext.getBean("student",Student.class);
student.testStudent();
}
}
4.Spring中Bean的作用域
本节先简单介绍了 Spring 中 bean 的 5 种作用域,然后详细介绍 singleton 和 prototype 这两种最常用的作用域。
作用域的种类
Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring3 为 Bean 定义了五种作用域,具体如下。
1)singleton
单例模式,使用 singleton 定义的 Bean 在 Spring 容器中只有一个实例,这也是 Bean 默认的作用域。
2)prototype
原型模式,每次通过 Spring 容器获取 prototype 定义的 Bean 时,容器都将创建一个新的 Bean 实例。
3)request
在一次 HTTP 请求中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在当
前 HTTP Request 内有效。
4)session
在一次 HTTP Session 中,容器会返回该 Bean 的同一个实例。而对不同的 HTTP 请求,会返回不同的实例,该作用域仅在
当前 HTTP Session 内有效。
5)global Session
在一个全局的 HTTP Session 中,容器会返回该 Bean 的同一个实例。该作用域仅在使用 portlet context 时有效。
在上述五种作用域中,singleton 和 prototype 是最常用的两种,接下来将对这两种作用域进行详细讲解。
singleton 作用域
singleton 是 Spring 容器默认的作用域,当一个 Bean 的作用域为 singleton 时,Spring 容器中只会存在一个共享的 Bean 实例,
并且所有对 Bean 的请求,只要 id 与该 Bean 定义相匹配,就只会返回 Bean 的同一个实例。
通常情况下,这种单例模式对于无会话状态的 Bean(如 DAO 层、Service 层)来说,是最理想的选择。
在 Spring 配置文件中,可以使用 <bean> 元素的 scope 属性,将 Bean 的作用域定义成 singleton,其配置方式如下所示:
<bean id="person" class="com.mengma.scope.Person" scope="singleton"/>
1.创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建UserBean类
package com.wangxing.scope;
public class UserBean {
public void testUser(){
System.out.println( "UserBean类的testUser()实例方法" );
}
}
3.创建Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="user" class="com.wangxing.scope.UserBean" scope="singleton"></bean>
</beans>
4.测试
package com.wangxing.scope;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationCntext.xml");
UserBean userBean1=applicationContext.getBean("user",UserBean.class);
UserBean userBean2=applicationContext.getBean("user",UserBean.class);
System.out.println("userBean1的hashcode码:"+userBean1.hashCode());
System.out.println("userBean2的hashcode码:"+userBean2.hashCode());
}
}
两次输出的结果相同,这说明 Spring 容器只创建了一个 UserBean类的实例。由于 Spring 容器默认作用域是 singleton,
如果不设置 scope="singleton",则其输出结果也将是一个实例。
prototype 作用域
使用 prototype 作用域的 Bean 会在每次请求该 Bean 时都会创建一个新的 Bean 实例。因此对需要保持会话状态的
Bean(如 Struts2 的 Action 类)应该使用 prototype 作用域。
在 Spring 配置文件中,要将 Bean 定义为 prototype 作用域,只需将 <bean> 元素的 scope 属性值定义成 prototype,
其示例代码如下所示:
<bean id="person" class="com.mengma.scope.Person" scope="prototype"/>
1.创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建PersonBean类
package com.wangxing.scope;
public class PersonBean {
public void testPerson(){
System.out.println( "PersonBean类的testPerson()实例方法" );
}
}
3.创建Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="person" class="com.wangxing.scope.PersonBean" scope="prototype"></bean>
</beans>
4.测试
package com.wangxing.scope;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
PersonBean personBean1=applicationContext.getBean("person",PersonBean.class);
PersonBean personBean2=applicationContext.getBean("person",PersonBean.class);
System.out.println("personBean1的hashcode码:"+personBean1.hashCode());
System.out.println("personBean2的hashcode码:"+personBean2.hashCode());
}
}
输出结果中可以看到,两次输出的结果并不相同,这说明在 prototype 作用域下,Spring 容器创建了两个不同的 Student实例。
5.Spring Bean的生命周期
Spring 容器可以管理 singleton 作用域 Bean 的生命周期,在此作用域下,Spring 能够精确地知道该 Bean 何时被创建,何时
初始化完成,以及何时被销毁。
而对于 prototype 作用域的 Bean,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,
Spring 容器将不再跟踪其生命周期。每次客户端请求 prototype 作用域的 Bean 时,Spring 容器都会创建一个新的实例,并且不
会管那些被配置成 prototype 作用域的 Bean 的生命周期。
了解 Spring 生命周期的意义就在于,可以利用 Bean 在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但
一般情况下,会在 Bean 被初始化后和被销毁前执行一些相关操作。
在 Spring 中,Bean 的生命周期是一个很复杂的执行过程,我们可以利用 Spring 提供的方法定制 Bean 的创建过程。
当一个 Bean 被加载到 Spring 容器时,它就具有了生命,而 Spring 容器在保证一个 Bean 能够使用之前,会进行很多工作。
Spring 容器中 Bean 的生命周期流程如图 1 所示。
图 1 Bean 的生命周期
Bean 生命周期的整个执行过程描述如下。
1)根据配置情况调用 Bean 构造方法或工厂方法实例化 Bean。
2)利用依赖注入完成 Bean 中所有属性值的配置注入。
3)如果 Bean 实现了 BeanNameAware 接口,则 Spring 调用 Bean 的 setBeanName() 方法传入当前 Bean 的 id 值。
4)如果 Bean 实现了 BeanFactoryAware 接口,则 Spring 调用 setBeanFactory() 方法传入当前工厂实例的引用。
5)如果 Bean 实现了 ApplicationContextAware 接口,则 Spring 调用 setApplicationContext() 方法传入当前
ApplicationContext 实例的引用。
6)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的预初始化方法 postProcessBeforeInitialzation()
对 Bean 进行加工操作,此处非常重要,Spring 的 AOP 就是利用它实现的。
7)如果 Bean 实现了 InitializingBean 接口,则 Spring 将调用 afterPropertiesSet() 方法。
8)如果在配置文件中通过 init-method 属性指定了初始化方法,则调用该初始化方法。
9)如果 BeanPostProcessor 和 Bean 关联,则 Spring 将调用该接口的初始化方法 postProcessAfterInitialization()。此时,
Bean 已经可以被应用系统使用了。
10)如果在 <bean> 中指定了该 Bean 的作用范围为 scope="singleton",则将该 Bean 放入 Spring IoC 的缓存池中,将触发
Spring 对该 Bean 的生命周期管理;如果在 <bean> 中指定了该 Bean 的作用 范围为 scope="prototype",则
将该 Bean 交给调用者,调用者管理该 Bean 的生命周期,Spring 不再管理该 Bean。
11)如果 Bean 实现了 DisposableBean 接口,则 Spring 会调用 destory() 方法将 Spring 中的 Bean 销毁;如果在配置文件中通
过 destory-method 属性指定了 Bean 的销毁方法,则 Spring 将调用该方法对 Bean 进行销毁。
Spring 为 Bean 提供了细致全面的生命周期过程,通过实现特定的接口或 <bean> 的属性设置,都可以对 Bean 的生命周期过程产
生影响。虽然可以随意配置 <bean> 的属性,但是建议不要过多地使用 Bean 实现接口,因为这样会导致代码和 Spring 的聚合过于紧密。
1.创建项目,完善结构,导入依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
2.创建PersonBean 类
package com.wangxing.demo5;
public class PersonBean {
public PersonBean(){
System.out.println("创建PersonBean对象");
}
public void initPerson(){
System.out.println("initPerson()是我们定制的初始化方法");
}
public void testPerson(){
System.out.println("testPerson()是PersonBean的实例方法");
}
public void destoryPerson(){
System.out.println("destoryPerson()是我们定制的销毁方法");
}
}
3.创建Spring配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="person" class="com.wangxing.demo5.PersonBean" scope="singleton" init-method="initPerson" destroy-method="destoryPerson"></bean>
</beans>
4.测试
package com.wangxing.demo5;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AppTest {
@Test
public void shouldAnswerWithTrue() {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
PersonBean personBean=applicationContext.getBean("person",PersonBean.class);
personBean.testPerson();
//((AbstractApplicationContext)applicationContext).close();
((AbstractApplicationContext)applicationContext).registerShutdownHook();
}
}
当spring配置文件中的scope属性是singleton时,Spring 能够精确地知道该 Bean 何时被创建,何时初始化完成,以及何时被销毁。
被定制的销毁方法【destoryPerson()】可以被执行
当spring配置文件中的scope属性是prototype时,Spring 只负责创建,当容器创建了 Bean 的实例后,Bean 的实例就交给客户端代码管理,Spring 容器将不再跟踪其生命周期。
被定制的销毁方法【destoryPerson()】不会执行