对象的生命周期

什么是对象的生命周期

  • 一个对象的创建、存活、消亡的一个完整过程。

为什么要学习对象的生命周期?
(由程序员控制的
创建对象 就使用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)在对象中提供一个普通的方法

  1. 实现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
  1. 在对象中提供一个普通的方法,

自己创建一个初始化方法,那么Spring怎么会知道呢,所以方法名需要告诉Spring,即在配置文件中配置

<bean id="product" class="com.life.Product" init-method="myInit"/>
public void myInit(){
	System.outprintln(Product.myInit)
}

小结:

  1. 提供接口,接口是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");
    }
}
  1. 提供普通方法,不藕合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 销毁对象前,会调用对象的销毁方法,完成销毁。

  1. 什么时候销毁所创建的对象?
    工厂关闭的时候销毁,关闭前会调用销毁方法。
    ctx.close();
  • 销毁方法:程序员根据自己的需求,定义销毁方法,完成销毁操作。
  • 调用: 是由Spring工厂完成调用
  1. 怎么来定义销毁方法?

(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()
  • spring 手动销毁 spring对象什么时候执行销毁_spring 手动销毁

  • ---- 这个是孙帅老师的课件图,非常厉害