Spring中的destroy-method

    技术2026-08-22  21

    究竟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所持有的昂贵资源,都是客户端代码的职责.”
    最新回复(0)