生命周期概念
所谓生命周期,即是一个对象从创建,使用,销毁的一个过程。众所周知,Spring是一个管理Bean的工厂,里面被管理的Bean对象也有生命周期。 生命周期实质就是在固定的时间节点执行特定的代码片段。
Spring Bean生命周期之5步
测试步骤如下:
- 创建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生命周期:销毁方法...");
}
}
- 基于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方法进行关闭。
细节总结:
- 第一:只有正常关闭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" />
- 再次执行上述的测试代码,可以看到如下测试结果
Spring Bean生命周期之10步
完整的生命周期如图所示:
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方法");
}
}
在执行测试方法,可以看到如下输出结果:
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"/>
执行测试方法,可以看到如下结果:
可以看到,我们获取到对象之后,后续的声明周期步骤便没有被执行。
最后,Spring管理Bean对象生命周期的源码可以参考:AbstractAutowireCapableBeanFactory的doCreateBean方法。