001/* 002 * Copyright 2002-2016 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.servlet.handler; 018 019import java.util.Collections; 020import java.util.Enumeration; 021import javax.servlet.Servlet; 022import javax.servlet.ServletConfig; 023import javax.servlet.ServletContext; 024import javax.servlet.ServletException; 025 026import org.springframework.beans.BeansException; 027import org.springframework.beans.factory.BeanInitializationException; 028import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor; 029import org.springframework.web.context.ServletConfigAware; 030import org.springframework.web.context.ServletContextAware; 031 032/** 033 * {@link org.springframework.beans.factory.config.BeanPostProcessor} 034 * that applies initialization and destruction callbacks to beans that 035 * implement the {@link javax.servlet.Servlet} interface. 036 * 037 * <p>After initialization of the bean instance, the Servlet {@code init} 038 * method will be called with a ServletConfig that contains the bean name 039 * of the Servlet and the ServletContext that it is running in. 040 * 041 * <p>Before destruction of the bean instance, the Servlet {@code destroy} 042 * will be called. 043 * 044 * <p><b>Note that this post-processor does not support Servlet initialization 045 * parameters.</b> Bean instances that implement the Servlet interface are 046 * supposed to be configured like any other Spring bean, that is, through 047 * constructor arguments or bean properties. 048 * 049 * <p>For reuse of a Servlet implementation in a plain Servlet container 050 * and as a bean in a Spring context, consider deriving from Spring's 051 * {@link org.springframework.web.servlet.HttpServletBean} base class that 052 * applies Servlet initialization parameters as bean properties, supporting 053 * both the standard Servlet and the Spring bean initialization style. 054 * 055 * <p><b>Alternatively, consider wrapping a Servlet with Spring's 056 * {@link org.springframework.web.servlet.mvc.ServletWrappingController}.</b> 057 * This is particularly appropriate for existing Servlet classes, 058 * allowing to specify Servlet initialization parameters etc. 059 * 060 * @author Juergen Hoeller 061 * @since 1.1.5 062 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) 063 * @see javax.servlet.Servlet#destroy() 064 * @see SimpleServletHandlerAdapter 065 */ 066public class SimpleServletPostProcessor implements 067 DestructionAwareBeanPostProcessor, ServletContextAware, ServletConfigAware { 068 069 private boolean useSharedServletConfig = true; 070 071 private ServletContext servletContext; 072 073 private ServletConfig servletConfig; 074 075 076 /** 077 * Set whether to use the shared ServletConfig object passed in 078 * through {@code setServletConfig}, if available. 079 * <p>Default is "true". Turn this setting to "false" to pass in 080 * a mock ServletConfig object with the bean name as servlet name, 081 * holding the current ServletContext. 082 * @see #setServletConfig 083 */ 084 public void setUseSharedServletConfig(boolean useSharedServletConfig) { 085 this.useSharedServletConfig = useSharedServletConfig; 086 } 087 088 @Override 089 public void setServletContext(ServletContext servletContext) { 090 this.servletContext = servletContext; 091 } 092 093 @Override 094 public void setServletConfig(ServletConfig servletConfig) { 095 this.servletConfig = servletConfig; 096 } 097 098 099 @Override 100 public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { 101 return bean; 102 } 103 104 @Override 105 public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { 106 if (bean instanceof Servlet) { 107 ServletConfig config = this.servletConfig; 108 if (config == null || !this.useSharedServletConfig) { 109 config = new DelegatingServletConfig(beanName, this.servletContext); 110 } 111 try { 112 ((Servlet) bean).init(config); 113 } 114 catch (ServletException ex) { 115 throw new BeanInitializationException("Servlet.init threw exception", ex); 116 } 117 } 118 return bean; 119 } 120 121 @Override 122 public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { 123 if (bean instanceof Servlet) { 124 ((Servlet) bean).destroy(); 125 } 126 } 127 128 @Override 129 public boolean requiresDestruction(Object bean) { 130 return (bean instanceof Servlet); 131 } 132 133 134 /** 135 * Internal implementation of the {@link ServletConfig} interface, 136 * to be passed to the wrapped servlet. 137 */ 138 private static class DelegatingServletConfig implements ServletConfig { 139 140 private final String servletName; 141 142 private final ServletContext servletContext; 143 144 public DelegatingServletConfig(String servletName, ServletContext servletContext) { 145 this.servletName = servletName; 146 this.servletContext = servletContext; 147 } 148 149 @Override 150 public String getServletName() { 151 return this.servletName; 152 } 153 154 @Override 155 public ServletContext getServletContext() { 156 return this.servletContext; 157 } 158 159 @Override 160 public String getInitParameter(String paramName) { 161 return null; 162 } 163 164 @Override 165 public Enumeration<String> getInitParameterNames() { 166 return Collections.enumeration(Collections.<String>emptySet()); 167 } 168 } 169 170}