对象的生命周期
什么是对象的生命周期
- 一个对象的创建、存活、消亡的一个完整过程。
为什么要学习对象的生命周期?
(由程序员控制的
创建对象 就使用new,User user = new User()
若一直有被引用,那么他就一直存活在虚拟机内存中,直到被虚拟机(JVM) 垃圾回收(GC)
销毁:虚拟机内存不够 或者进程结束,对象自然就消亡了)
- Spring中, 由Spring负责对象的创建、存活、销毁,了解生命周期,有利于为我们创建对象。
生命周期的三个阶段
创建阶段
- Spring 工厂何时创建对象?
(1)scope=“singleton”
Spring工厂创建的同时,对象的创建
package com.life;
public class Product {
public Product() {
//为了验证什么时候创建对象,这里在无参构造力输出打印,方便验证
System.out.println("Product.product");
}
}
<bean id="product" scope="singleton" class="com.life.Product"></bean>
测试(1):
@org.junit.Test
public void Test6(){
//获取工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
}
//output
//Product.product
注意:这种情况也许在获取对象的同时创建对象
,则需要在bean
里加lazy-init
标签, 如下
<bean id="product" scope="singleton" class="com.life.Product" lazy-init="true"></bean>
若此时用测试(1)的代码测试,不会有输出。
(2)scope="prototype"
Spring 工厂会在获取对象的同时,创建对象ctx.getBean()
;在这执行这句话的时候创建。
要先创建工厂,需要对象的时候再创建对象
<bean id="product" scope="prototype" class="com.life.Product"></bean>
测试(2)
@org.junit.Test
public void Test6(){
//获取工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
//创建对象
Product product = (Product) ctx.getBean("product");
}
//output
//Product.product
注意 scope=“singleton”
的标签若想大到与测试(2)一样的效果, 在bean
里加lazy-init
标签即可。
初始化阶段
Spring工厂在创建完对象后,调用对象的初始化方法,完成对应的初始化操作。
- 初始化方法提供: 程序员根据需求,提供初始化方法,最终完成初始化操作
- 初始化方法调用: Spring工厂进行调用
初始化定义的两种方式
(1)实现InitializingBean
接口
(2)在对象中提供一个普通的方法
- 实现
InitializingBean
接口,(藕合)
完成afterPropertiesSet初始化方法,Spring会调用
//默认singleton,创建工厂的同时创建对象
<bean id="product" class="com.life.Product"></bean>
public class Product implements InitializingBean {
public Product() {
System.out.println("Product.product");
}
//这就是初始化方法,程序员根据需求,在里面做初始化操作
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Product.afterPropertiesSet");
}
}
测试
创建对象 那一行 被屏蔽,是因为singleton设置,即创建工厂的同时已经创建了对象,这里没必要再写一次。
结果输出了Spring初始化的值,即证明了完成对象的创建后,Spring会自动调用初始化方法。
@org.junit.Test
public void Test6(){
//获取工厂
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
// //创建对象
// Product product = (Product) ctx.getBean("product");
}
//output
//Product.product
//Product.afterPropertiesSet
- 在对象中提供一个普通的方法,
自己创建一个初始化方法,那么Spring怎么会知道呢,所以方法名需要告诉Spring,即在配置文件中配置
<bean id="product" class="com.life.Product" init-method="myInit"/>
public void myInit(){
System.outprintln(Product.myInit)
}
小结:
- 提供接口,接口是Spring自己定义的,不需要增加额外配置
package com.life;
import org.springframework.beans.factory.InitializingBean;
//1. 提供接口,接口是Spring自己定义的,不需要增加额外配置
public class Product implements InitializingBean {
public Product() {
System.out.println("Product.product");
}
//这就是初始化方法,在里面做初始化操作
//Spring会调用
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Product.afterPropertiesSet");
}
}
- 提供普通方法,不藕合Spring框架,不用实现规定的接口。
但是 需要增加配置init-method
需要告诉Spring初始化方法
//2. 提供普通方法,不藕合Spring框架,不用实现规定的接口
// 但是 需要增加配置 init-method 需要告诉Spring初始化方法
public class Product{
public Product() {
System.out.println("Product.product");
}
public void myInit(){
System.out.println("Product.myInit");
}
}
细节分析
(1)如果一个对象即实现了initializingBean
接口,又提供普通的初始化方法,那么它调用的顺序是什么?
回答:都会执行,先执行initializingBean
,后执行普通初始化。
(2)注入
发生在初始化
之前
若类中有自己的属性,然后有各自的set get 方法,然后就有set 注入。顺序:先创建对象 - DI - 初始化
(3)什么叫初始化操作?
一般是对资源的初始化。资源如 数据库,IO 网络… 这些都比较耗资源,一般放在初始化中。
销毁阶段
Spring 销毁对象前,会调用对象的销毁方法,完成销毁。
- 什么时候销毁所创建的对象?
在工厂关闭的时候销毁,关闭前会调用销毁方法。ctx.close()
;
- 销毁方法:程序员根据自己的需求,定义销毁方法,完成销毁操作。
- 调用: 是由Spring工厂完成调用
- 怎么来定义销毁方法?
(1) 实现DisposableBean
接口方法
(2) 定义普通方法,配置文件中配置destroy-method="myDestroy"
,和初始化类似。
package com.life;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
//1. 提供接口,接口是Spring自己定义的,不需要增加额外配置
public class Product implements InitializingBean, DisposableBean {
public Product() {
System.out.println("Product.product");
}
...
//1. 实现DisposableBean接口里的destroy方法即可
@Override
public void destroy() throws Exception {
System.out.println("Product.destroy");
}
//2. 定义普通方法,记得配置文件需要配置告知Spring这是destroy
public void myDestroy(){
System.out.println("Product.myDestroy");
}
//<bean id="product" class="com.life.Product" destroy-method="myDestroy"></bean>
}
总结
- 销毁方法只适用与
scope=singleton
的配置,若是scope=prototype
,工厂关闭但是方法并没有销毁。 - 什么是销毁操作?
主要指资源的释放,比如io.close()
,connection.close()
- ---- 这个是孙帅老师的课件图,非常厉害