?????????究竟Spring在何時(shí)調(diào)用destroy-method="close" 這個(gè)方法close()呢?終于借助JavaEye找到了答案,原來(lái)如果Spring不在Web Container或是EJB Container中的時(shí)候,這個(gè)方法還是需要我們自己來(lái)調(diào)用的,具體就是調(diào)用BeanFactory的destroySingletons()方法,文檔上的“自動(dòng)調(diào)用”這幾個(gè)字真是害我不淺呀,原來(lái)自動(dòng)也是通過(guò)Web Container或是EJB Container才可以自動(dòng),具體做法就是要實(shí)現(xiàn)ServletContextListener這個(gè)接口,Spring中已經(jīng)有具體的實(shí)現(xiàn)了:
?
publicclass ContextLoaderListener implements ServletContextListener {?
??????? private ContextLoader contextLoader;?
??????? /**
? ? ? ? * Initialize the root web application context.
? ? ? ? */
? ? ? ? publicvoid 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(){
? ? ? ? ? ? ? ? returnnew ContextLoader();
? ? ? ? }?
??????? /**
? ? ? ? * Return the ContextLoader used by this listener.
? ? ? ? */
? ? ? ? public ContextLoader getContextLoader(){
? ? ? ? ? ? ? ? return contextLoader;
? ? ? ? }?
??????? /**
? ? ? ? * Close the root web application context.
? ? ? ? */
? ? ? ? publicvoid contextDestroyed(ServletContextEvent event){
? ? ? ? ? ? ? ? this.contextLoader.closeWebApplicationContext(event.getServletContext());
? ? ? ? }
}
??????? private ContextLoader contextLoader;?
??????? /**
? ? ? ? * Initialize the root web application context.
? ? ? ? */
? ? ? ? publicvoid 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(){
? ? ? ? ? ? ? ? returnnew ContextLoader();
? ? ? ? }?
??????? /**
? ? ? ? * Return the ContextLoader used by this listener.
? ? ? ? */
? ? ? ? public ContextLoader getContextLoader(){
? ? ? ? ? ? ? ? return contextLoader;
? ? ? ? }?
??????? /**
? ? ? ? * Close the root web application context.
? ? ? ? */
? ? ? ? publicvoid contextDestroyed(ServletContextEvent event){
? ? ? ? ? ? ? ? this.contextLoader.closeWebApplicationContext(event.getServletContext());
? ? ? ? }
}
當(dāng)tomcat關(guān)閉的時(shí)候會(huì)自動(dòng)調(diào)用contextDestroyed(ServletContextEvent event)這個(gè)方法。在看一下contextLoader的closeWebApplicationContext方法:
?
publicvoid 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();
? ? ? ? ? ? ? ? }
? ? ? ? }
? ? ? ? ? ? ? ? servletContext.log("Closing root WebApplicationContext");
? ? ? ? ? ? ? ? Object wac = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
? ? ? ? ? ? ? ? if(wac instanceof ConfigurableApplicationContext){
? ? ? ? ? ? ? ? ? ? ? ? ((ConfigurableApplicationContext) wac).close();
? ? ? ? ? ? ? ? }
? ? ? ? }
AbstractApplicationContext.Close這個(gè)方法是要你自己調(diào)用的,在程序要結(jié)束的時(shí)候保證調(diào)用這個(gè)close方法,在這里的話就是由Listener來(lái)保證tomcat退出的時(shí)候調(diào)用close方法。
AbstractApplicationContext.Close的代碼 :
AbstractApplicationContext.Close的代碼 :
?
publicvoid 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));
? ? ? ? }
? ? ? ? ? ? ? ? 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));
? ? ? ? }
最終還是調(diào)用到了getBeanFactory().destroySingletons(); 看來(lái),沒(méi)有容器,我們還是需要自己來(lái)搞定這個(gè)方法的調(diào)用的 !