Spring中的destroy-method

Spring销毁机制解析
本文详细解释了Spring框架中如何及何时调用bean的销毁方法,特别是在Web应用环境下,通过ContextLoaderListener实现ServletContextListener接口来确保容器关闭时正确执行bean的销毁逻辑。
究竟Spring在何时调用destroy-method="close" 这个方法close()呢?终于借助JavaEye找到了答案,原来如果Spring不在Web Container或是EJB Container中的时候,这个方法还是需要我们自己来调用的,具体就是调用BeanFactory的destroySingletons()方法,文档上的“自动调用”这几个字真是害我不浅呀,原来自动也是通过Web Container或是EJB Container才可以自动,具体做法就是要实现ServletContextListener这个接口,Spring中已经有具体的实现了:
 
public class ContextLoaderListener implements ServletContextListener {

        private ContextLoader contextLoader;

        /**
        * Initialize the root web application context.
        */

        public void contextInitialized(ServletContextEvent event) {
                this.contextLoader = createContextLoader();
                this.contextLoader.initWebApplicationContext(event.getServletContext());
        }

        /**
        * Create the ContextLoader to use. Can be overridden in subclasses.
        * @return the new ContextLoader
        */

        protected ContextLoader createContextLoader() {
                return new ContextLoader();
        }

        /**
        * Return the ContextLoader used by this listener.
        */

        public ContextLoader getContextLoader() {
                return contextLoader;
        }

        /**
        * Close the root web application context.
        */

        public void contextDestroyed(ServletContextEvent event) {
                this.contextLoader.closeWebApplicationContext(event.getServletContext());
        }

}
当tomcat关闭的时候会自动调用contextDestroyed(ServletContextEvent event)这个方法。在看一下contextLoader的closeWebApplicationContext方法:
 
public void closeWebApplicationContext(ServletContext servletContext) throws ApplicationContextException {
                servletContext.log("Closing root WebApplicationContext");
                Object wac = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
                if (wac instanceof ConfigurableApplicationContext) {
                        ((ConfigurableApplicationContext) wac).close();
                }
        }
AbstractApplicationContext.Close这个方法是要你自己调用的,在程序要结束的时候保证调用这个close方法,在这里的话就是由Listener来保证tomcat退出的时候调用close方法。
AbstractApplicationContext.Close的代码 :
 
public void close() {
                logger.info("Closing application context [" + getDisplayName() + "]");

                // Destroy all cached singletons in this context,
                // invoking DisposableBean.destroy and/or "destroy-method".
                getBeanFactory().destroySingletons();

                // publish corresponding event
                publishEvent(new ContextClosedEvent(this));
        }

最终还是调用到了getBeanFactory().destroySingletons(); 看来,没有容器,我们还是需要自己来搞定这个方法的调用的 !

- 作者: hpq852 2004年12月28日, 星期二 18:07

举个例子,ContextLoaderListener的源代码,
我们知道,如果要在tomcat里面使用spring的话需要这个Listener(或者ContextLoaderServlet)

代码
 public class ContextLoaderListener implements ServletContextListener {

private ContextLoader contextLoader;

/**
* Initialize the root web application context.
*
/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}

/**
* Create the ContextLoader to use. Can be overridden in subclasses.
* @return the new ContextLoader
*
/
protected ContextLoader createContextLoader() {
return new ContextLoader();
}

/**
* Return the ContextLoader used by this listener.
*
/
public ContextLoader getContextLoader() {
return contextLoader;
}

/**
* Close the root web application context.
*
/
public void contextDestroyed(ServletContextEvent event) {
this.contextLoader.closeWebApplicationContext(event.getServletContext());
}

}


当tomcat关闭的时候会自动调用contextDestroyed(ServletContextEvent event)这个方法。在看一下contextLoader的closeWebApplicationContext方法:

代码
 	public void closeWebApplicationContext(ServletContext servletContext) throws ApplicationContextException {

servletContext.log("Closing root WebApplicationContext");
Object wac = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
if (wac instanceof ConfigurableApplicationContext) {
((ConfigurableApplicationContext) wac).close();
}
}


就应该明白文档里面是什么意思了,AbstractApplicationContext.Close这个方法是要你自己调用的,在程序要结束的时候保证调用这个close方法,在这里的话就是由Listener来保证tomcat退出的时候调用close方法。
AbstractApplicationContext.Close的代码

代码
 	public void close() {

logger.info("Closing application context [" + getDisplayName() + "]");

 

// Destroy all cached singletons in this context,
// invoking DisposableBean.destroy and/or "destroy-method".
getBeanFactory().destroySingletons();


其实就是调用context里面的beanFactory的destroySingletons()方法了,这个没什么好说的。我的意思就是,容器本身不知道什么时候要shutdown了,这个消息是要靠外部(程序员)来提供的。

 

// publish corresponding event
publishEvent(new ContextClosedEvent(this));
}

spring的说明中有这样一句话,我大致翻译了一下:

“对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个 prototype bean的整个生命周期负责:容器在初始化、
配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,
容器都会调用所有对象的初始化生命周期回调方法,而对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。
清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责.”
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值