Spring Bean生命周期

150 阅读4分钟

生命周期概念

所谓生命周期,即是一个对象从创建,使用,销毁的一个过程。众所周知,Spring是一个管理Bean的工厂,里面被管理的Bean对象也有生命周期。 生命周期实质就是在固定的时间节点执行特定的代码片段。

Spring Bean生命周期之5步

测试步骤如下:

  1. 创建Animal类,指定构造方法,set方法,以及初始化和销毁方法
public class Animal {

  private String name;
  
  // 第一步:对象实例化
  public Animal() {
    System.out.println("spring bean生命周期:构造方法...");
  }

  // 第二步:属性赋值
  public void setName(String name) {
    this.name = name;
    System.out.println("spring bean生命周期:属性赋值...");
  }

  // 第三步:初始化对象
  void initMethod() {
    System.out.println("spring bean生命周期:初始化方法...");
  }
    
  // 第五步:对象销毁
  void destroyMethod() {
    System.out.println("spring bean生命周期:销毁方法...");
  }
}
  1. 基于xml方式配置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"
       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">

    <!--定义bean-->
    <bean class="cn.chiatso.bean.Animal" id="animal" p:name="动物类" init-method="initMethod" destroy-method="destroyMethod"/>

    <!--配置bean后置处理器-->
    <bean class="cn.chiatso.bean.PostProcessor" />
</beans>

init-method属性指定初始化方法,destroy-method属性置顶销毁方法,上述属性赋值通过p命名空间注入 3. 测试

ApplicationContext application = new ClassPathXmlApplicationContext("spring.xml");
Animal animal = application.getBean("animal", Animal.class);
System.out.println("spring bean生命周期:使用bean对象..." + animal);
((ClassPathXmlApplicationContext)application).close();

这里有个细节,Spring Bean生命周期销毁的前提是Spring容器正常关闭,通过调用子类的close方法进行关闭

image.png

细节总结:

  • 第一:只有正常关闭spring容器,bean的销毁方法才会被调用。
  • 第二:ClassPathXmlApplicationContext类才有close()方法。
  • 第三:配置文件中的init-method指定初始化方法。destroy-method指定销毁方法。

Spring Bean生命周期之7步

在5步基础之上,还可以增加两步,分别在初始化方法执行前和后执行相应的代码片段,这需要 Spring提供的BeanPostProcessor实现。该接口默认实现了postProcessBeforeInitialization前置初始化方法和postProcessAfterInitialization后置初始化方法。该Bean后置处理器是容器级别,一旦为容器配置,将对容器中所有bean生效。

  • 编写BeanPostProcessor实现类PostProcessor,实现其中的方法:
public class PostProcessor implements BeanPostProcessor {
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("spring bean生命周期:初始化前置方法");
    return bean;
  }

  public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    System.out.println("spring bean生命周期:初始化后置方法");
    return bean;
  }
}
  • 配置后置处理器:将下面内容加入到上面的xml配置文件中,配置后置处理器
<!--配置bean后置处理器-->
<bean class="cn.chiatso.bean.PostProcessor" />
  • 再次执行上述的测试代码,可以看到如下测试结果

image.png

Spring Bean生命周期之10步

完整的生命周期如图所示:

image.png

Spring会在相应的过程中检查Bean是否实现上图提到的接口并执行相应的接口方法。 上图中检查Bean是否实现了Aware的相关接口是什么意思?

Aware相关的接口包括:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware

  • 当Bean实现了BeanNameAware,Spring会将Bean的名字传递给Bean。
  • 当Bean实现了BeanClassLoaderAware,Spring会将加载该Bean的类加载器传递给Bean。
  • 当Bean实现了BeanFactoryAware,Spring会将Bean工厂对象传递给Bean。

测试以上10步,可以让Animal类实现5个接口,并实现所有方法:

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware
  • InitializingBean
  • DisposableBean

对上面的Animal类进行改造,让其实现BeanNameAware,InitializingBean,DisposableBean接口,并实现其中接口方法,如下所示:

public class Animal implements DisposableBean, InitializingBean, BeanNameAware {

  private String name;

  public void setName(String name) {
    this.name = name;
    System.out.println("spring bean生命周期:属性赋值...");
  }

  public Animal() {
    System.out.println("spring bean生命周期:构造方法...");
  }

  void initMethod() {
    System.out.println("spring bean生命周期:初始化方法...");
  }

  void destroyMethod() {
    System.out.println("spring bean生命周期:销毁方法...");
  }

  public void destroy() throws Exception {
    System.out.println("spring bean生命周期:destroy方法");
  }

  public void afterPropertiesSet() throws Exception {
    System.out.println("spring bean生命周期:afterPropertiesSet方法");
  }

  public void setBeanName(String name) {
    System.out.println("spring bean生命周期:aware方法");
  }
}

在执行测试方法,可以看到如下输出结果:

image.png

Bean最常见的范围(scope)有singleton(单例)和prototype(原型),其中singleton范围的bean的生命周期完全由Spring框架进行管理,而prototype范围的bean由Spring进行创建,用户一旦使用之后,Spring便不再进行管理后续的生命周期。接下来进行验证:

我们不需要修改Animal类,只需要在xml配置文件中将Animal实例对象的声明添加上scope="prototype"即可,表示该实例是原型(每次获取Spring容器都将会重新创建一个新的对象),如下:

<!--定义bean-->
<bean class="cn.chiatso.bean.Animal" id="animal" p:name="动物类" init-method="initMethod" destroy-method="destroyMethod" scope="prototype"/>

执行测试方法,可以看到如下结果:

image.png

可以看到,我们获取到对象之后,后续的声明周期步骤便没有被执行。

最后,Spring管理Bean对象生命周期的源码可以参考:AbstractAutowireCapableBeanFactory的doCreateBean方法。