001/* 002 * Copyright 2002-2019 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.context; 018 019import java.util.Enumeration; 020 021import javax.servlet.ServletContext; 022import javax.servlet.ServletContextEvent; 023import javax.servlet.ServletContextListener; 024 025import org.apache.commons.logging.Log; 026import org.apache.commons.logging.LogFactory; 027 028import org.springframework.beans.factory.DisposableBean; 029 030/** 031 * Web application listener that cleans up remaining disposable attributes 032 * in the ServletContext, i.e. attributes which implement {@link DisposableBean} 033 * and haven't been removed before. This is typically used for destroying objects 034 * in "application" scope, for which the lifecycle implies destruction at the 035 * very end of the web application's shutdown phase. 036 * 037 * @author Juergen Hoeller 038 * @since 3.0 039 * @see org.springframework.web.context.support.ServletContextScope 040 * @see ContextLoaderListener 041 */ 042public class ContextCleanupListener implements ServletContextListener { 043 044 private static final Log logger = LogFactory.getLog(ContextCleanupListener.class); 045 046 047 @Override 048 public void contextInitialized(ServletContextEvent event) { 049 } 050 051 @Override 052 public void contextDestroyed(ServletContextEvent event) { 053 cleanupAttributes(event.getServletContext()); 054 } 055 056 057 /** 058 * Find all Spring-internal ServletContext attributes which implement 059 * {@link DisposableBean} and invoke the destroy method on them. 060 * @param servletContext the ServletContext to check 061 * @see DisposableBean#destroy() 062 */ 063 static void cleanupAttributes(ServletContext servletContext) { 064 Enumeration<String> attrNames = servletContext.getAttributeNames(); 065 while (attrNames.hasMoreElements()) { 066 String attrName = attrNames.nextElement(); 067 if (attrName.startsWith("org.springframework.")) { 068 Object attrValue = servletContext.getAttribute(attrName); 069 if (attrValue instanceof DisposableBean) { 070 try { 071 ((DisposableBean) attrValue).destroy(); 072 } 073 catch (Throwable ex) { 074 if (logger.isWarnEnabled()) { 075 logger.warn("Invocation of destroy method failed on ServletContext " + 076 "attribute with name '" + attrName + "'", ex); 077 } 078 } 079 } 080 } 081 } 082 } 083 084}