与定制初始化行为相似,Spring也提供两种方法定制Bean实例销毁之前的行为:
① 使用destroy-method属性:
destroy-method属性指定某个方法在Bean销毁之前被自动执行。使用这种方式,不需要将代码与Spring的接口耦合,代码污染小。
② 实现DisposableBean接口:
该接口提供了一个方法,void destroy( ) throws Exception,该方法就是Bean实例被销毁之前应该执行的方法。
Axe.java :
public interface Axe {
public String chop();
}Person.java :
public interface Person {
public void useAxe();
}SteelAxe.java :
public class SteelAxe implements Axe {
@Override
public String chop() {
return "钢斧砍柴真快";
}
public SteelAxe() {
System.out.println("Spring实例化依赖Bean:SteelAxe实例...");
}
}Chinese.java :
public class Chinese implements Person,DisposableBean {
private Axe axe;
public Chinese() {
System.out.println("Spring实例化主调Bean:Chinese实例...");
}
public void setAxe(Axe axe) {
System.out.println("Spring执行依赖关系注入...");
this.axe = axe;
}
@Override
public void useAxe() {
System.out.println(axe.chop());
}
public void close(){
System.out.println("正在执行销毁之前的方法close...");
}
@Override
public void destroy() throws Exception {
System.out.println("正在执行销毁之前的方法destroy...");
}
}bean.xml核心配置:
<bean id="chinese" class="com.bean.Chinese" destroy-method="close">
<property name="axe" ref="steelAxe"></property>
</bean>
<bean id="steelAxe" class="com.bean.SteelAxe"/>Test.java :
public class Test {
public static void main(String[] args) {
AbstractApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
Person p=(Person) ctx.getBean("chinese");
p.useAxe();
ctx.registerShutdownHook();
}
}运行Test.java,控制台输出:
singleton 作用域的Bean通常会随容器的关闭而销毁,但问题是:ApplicationContext容器在什么时候关闭呢?在基于web的ApplicationContext实现中,系统已经提供了相应的代码保证关闭web应用时恰当地关闭Spring容器。
如果处于一个非web应用的环境下,为了让Spring容器优雅地关闭,并调用singleton Bean上的相应析构回调方法,则需要在JVM虚拟机里注册一个关闭钩子,这样就可保证Spring容器被恰当关闭,且自动执行singleton Bean实例的析构回调方法。
为了注册关闭钩子,只需要调用在AbstractApplicationContext中提供的registerShutdownHook( )方法即可。
从程序的输出可以看出:Spring容器注入之后,关闭之前,程序先调用destroy方法进行回收资源,再调用close方法进行回收资源。
如果某个Bean类实现了DisposableBean接口,在Bean被销毁之前,Spring容器会自动调用该Bean实例的destroy方法,其结果与采用destroy-method属性指定生命周期方法几乎一样。但实现DisposableBean接口污染了代码,是侵入式设计,因此不推荐使用。
除此之外,如果容器中很多Bean都需要指定特定的生命周期行为,则可以利用 <beans.../> 元素的 default-init-method属性和
default-destroy-method 属性,这两个属性的作用类似于 <bean.../>元素的
init-method 属性和destroy-method 属性,区别是default-init-method和default-destroy-method是针对容器中所有Bean生效。
需要指出的是,当Bean实现了ApplicationContextAware接口、BeanNameAware接口之后,Spring容器会在该Bean初始化完成之后,也就是调用init-method属性指定的方法之后,再来回调setApplicationContext(ApplicationContext appCtx)、setBeanName(String name)方法。
本文介绍如何在Spring框架中定制Bean的销毁行为,包括使用destroy-method属性及实现DisposableBean接口两种方式,并通过示例代码展示了如何注册关闭钩子来确保容器优雅关闭。
319

被折叠的 条评论
为什么被折叠?



