Spring | 对象的生命周期

Spring | 对象的生命周期

Spring 对象的生命周期

对象的生命周期是指一个对象创建、存活、消亡的一个完整的过程,通过 IOC,Spring 接管了对象的控制权,所以也需要负责管理对象的生命周期,Spring 管理的对象生命周期分为三个阶段:创建阶段、初始化阶段、销毁阶段

创建阶段

  • 如果配置文件中 <bean> 标签的 scope 属性值为 "singleton",则 Spring 工厂创建时,就会创建该类的对象,且在项目运行的整个过程中,只会创建一次,用户每次调用工厂的 getBean() 方法获得的对象都是同一个
  • 注意,如果<bean> 标签还设置了 lazy-init 属性值为 "true",表明该类使用懒加载方式,也就是当用户第一次调用 getBean() 方法时才会创建对象,且只会创建一次
  • 如果配置文件中 <bean> 标签的 scope 属性值为 "prototype",则 Spring 工厂会在用户调用 getBean() 方法方法时才会创建对象,且每次获得对象都是不同的

初始化阶段

Spring 工厂在创建完对象后,会调用初始化方法,完成对象的初始化操作,注意,该初始化方法需要程序员根据需求编码实现,但是由 Spring 工厂进行调用,主要有以下两种方式定义初始化方法

  • 类实现 InitializingBean 接口,并实现其中的 afterPropertiesSet() 方法,在该方法中完成对象的初始化,无需修改配置文件
  • 类中编写一个普通方法,例如 public void myInit(){},然后在配置文件中对应的 <bean> 标签添加 init-method 属性,值为初始化方法的方法名,表明该方法是初始化方法

注意

  1. 如果一个类,同时用以上两种方法进行初始化,则实际的初始化方法执行顺序是,先执行 InitializingBean 的初始化的方法,再执行普通初始化方法
  2. 注入操作会发生在初始化之前,所以 InitializingBean 接口中的初始化方法命名为 afterPropertiesSet()

销毁阶段

Spring 销毁对象之前,会调用对象的销毁方法,完成销毁操作,有以下两种方式定义销毁方法

  • 类实现 DisposableBean 接口,并实现其中的 destroy() 方法,在该方法中完成对象销毁前需要进行的操作,无需修改配置文件
  • 类中编写一个普通方法,例如 public void myDestroy(){},然后在配置文件中对应的 <bean> 标签添加 destroy-method 属性,值为销毁方法的方法名,表明该方法是销毁方法

注意

  1. Spring 在工厂关闭时才会进行销毁对象的操作,即调用 ApplicationContext 对象的 close() 方法时
  2. 如果一个类,同时用以上两种方法完成对象的销毁,则实际销毁方法的执行顺序是,先执行 DisposableBean 接口的销毁方法,再执行普通销毁方法
  3. 销毁方法只适用于只创建一次的对象,即 scope="singleton"ConnectionSqlSession 等对象应该自行销毁或归还到连接池

Spring Bean 的后处理

Spring 通过 BeanPostProcessor 接口对工厂创建的(每一个)对象进行再加工

Spring Bean 后处理原理

BeanPostProcessor 接口规定有两个需要实现的方法,Spring 会调用这两个方法完成对象的后处理

  1. Object postProcessBeforeInitialization(Object bean,String beanName)
    该方法会在 Spring 创建对象、完成注入后,初始化操作前,通过参数获取对象,然后进行加工,最后再返回交给 Spring
  2. Object postProcessAfterInitialization(Object bean,Sring beanName)
    该方法会在 Spring 完成对对象的初始化操作后,通过参数获取对象,然后进行加工,最后再返回交给 Spring

在实际运用中,很少对对象进行初始化操作,所以后处理过程也不必分初始化前后,只需实现 postProcessAfterInitialization() 方法即可

实例

创建一个用于测试的类

public class Product {
    private int id;
    private String name;
    /*
    ... ... 
    set get toStirng 方法
    */
}

创建一个类实现 BeanPostProcessor 接口,实现 postProcessAfterInitialization() 方法,判断如果传入对象是 Product 对象,则进行处理

package cool.yzt.postprocessor;

import cool.yzt.domain.Product;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if(bean instanceof Product) {
            Product p = (Product)bean;
            p.setName("电脑");
            System.out.println(beanName);
        }
        return bean;
    }
}

配置文件,注入 product 的属性

<bean id="product" class="cool.yzt.domain.Product" scope="prototype">
        <property name="name" value="手机"/>
        <property name="id" value="10001"/>
</bean>

<bean id="myPostProcessor" class="cool.yzt.postprocessor.MyPostProcessor"/>

测试

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Product p1 = ctx.getBean("product",Product.class);
Product p2 = ctx.getBean("product",Product.class);
System.out.println(p1);
System.out.println(p2);
System.out.println(p1==p2);

结果

product
product
Product{id=10001, name='电脑'}
Product{id=10001, name='电脑'}
false

可以看到,Spring 确实对创建的对象进行了后处理,且该操作发生在在注入之后

总结 Spring 工厂创建对象的流转过程

Spring创建对象的流程

参考

孙哥说Spring5

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://yzt.cool/archives/spring对象的生命周期