Spring 可以管理 singleton 作用域的 Bean 的生命周期,Spring 可以精确的知道该 Bean 何时被创建、何时被初始化完成、容器何时准备销毁该 Bean 实例。Spring 无法管理 prototype 作用域的 Bean 。
1、Spring 管理 Bean 的生命周期行为的时机:
① 注入依赖关系之后
② 即将销毁 Bean 之前
2、依赖关系注入之后的行为
-
Spring 提供两种方式在 Bean 的全部属性设置成功之后执行特定行为:
-
① 使用 init-method 属性在 Bean 全部属性设置结束后自动执行。
② 实现 InitializingBean 接口的 afterPropertiesSet() 方法。
<bean id="chinese" class="com.sunsharing.springDemo.model.impl.Chinese"
parent="person" init-method="init">
<constructor-arg ref="steelAxe"/>
</bean>
配置中指定 init() 方法是一个生命周期的方法。
/**
* Created by Hinbo on 2016/9/5.
*
*/
public class Chinese implements Person, BeanNameAware, InitializingBean, ApplicationContextAware {
private String beanName;
private String name;
private Axe axe;
public Chinese(){}
public Chinese(Axe axe){
this.axe = axe;
}
public void setAxe(Axe axe){
this.axe = axe;
}
public void setName(String name) {
this.name = name;
}
public void userAxe() {
System.out.println(axe.chop());
}
public void setBeanName(String name) {
this.beanName = name;
System.out.println("setBeanName ...... ");
}
//在该 Bean 注入依赖关系之后调用该方法
public void afterPropertiesSet() throws Exception {
System.out.println("正在执行初始化方法 afterPropertiesSet 。。。。。。");
}
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("applicationContext afterPropertiesSet ...... ");
}
public void init(){
System.out.println("正在执行初始化方法 init 。。。。。。");
}
}
两种的生命周期方法几乎一样,但是实现 InitializingBean 接口的方式污染了代码,是一种侵入式的设计,建议直接使用第一种。如果同时使用两种方法,则会先使用 InitializingBean 接口中的方法,然后再执行 init-method 属性指定的方法。
执行结果:
3、Bean 销毁之前的行为
-
Spring 两种定制 Bean 实例销毁之前的特定行为:
-
① 使用 destroy-method 属性,指定方法在该 Bean 销毁之前被自动执行,代码污染较小。
② 实现 DisposableBean 接口
singleton 作用域的 Bean 通常会随容器的关闭而销毁,在一个非 Web 应用的环境下可以在 JVM 里注册一个关闭钩子保证 Spring 容器关闭,且自动执行 singleton Bean 实例的回调方法。
<!-- 测试执行 Bean 销毁之前的行为 -->
<bean id="american" class="com.sunsharing.springDemo.model.impl.American"
destroy-method="close">
</bean>
测试 Bean:
/**
* Created by Hinbo on 2016/9/7.
* 测试 Bean 销毁之前的行为
*/
public class American implements Person, DisposableBean {
public American(){
System.out.println("Spring 实例化。。。。。。");
}
public void userAxe() {
System.out.println("American ......");
}
public void destroy() throws Exception {
System.out.println("正在执行销毁之前的方法 destroy ......");
}
public void close(){
System.out.println("正在执行销毁之前的方法 close ......");
}
}
测试代码:
//创建 Spring 容器
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext("spring-config.xml");
Person person = ctx.getBean("chinese", Person.class);
American american = ctx.getBean("american", American.class);
//为 Spring 容器注册关闭的钩子
ctx.registerShutdownHook();
具体的与依赖注入之后的行为类似,建议使用 destroy-method 属性,代码污染小。
执行结果:
4、Spring 容器中 Bean 实例的生命周期流程:
创建实例 –> 注入依赖关系 –> 调用 afterPropertiesSet –> 调用 init-method 方法 –> 对外提供服务 –> 调用 destroy –> 调用 destroy-method 方法 –> 实例被销毁