7.9.2: Bean 销毁之前的行为

来源:互联网 发布:mac风扇声音大 编辑:程序博客网 时间:2024/04/29 07:04

与定制初始化行为相似,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 {@Overridepublic 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;}@Overridepublic void useAxe() {System.out.println(axe.chop());}public void close(){System.out.println("正在执行销毁之前的方法close...");}@Overridepublic 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)方法。



原创粉丝点击