/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.springframework.web.servlet.handler;

import java.util.Collections;
import java.util.Enumeration;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.context.ServletContextAware;

BeanPostProcessor that applies initialization and destruction callbacks to beans that implement the Servlet interface.

After initialization of the bean instance, the Servlet init method will be called with a ServletConfig that contains the bean name of the Servlet and the ServletContext that it is running in.

Before destruction of the bean instance, the Servlet destroy will be called.

Note that this post-processor does not support Servlet initialization parameters. Bean instances that implement the Servlet interface are supposed to be configured like any other Spring bean, that is, through constructor arguments or bean properties.

For reuse of a Servlet implementation in a plain Servlet container and as a bean in a Spring context, consider deriving from Spring's HttpServletBean base class that applies Servlet initialization parameters as bean properties, supporting both the standard Servlet and the Spring bean initialization style.

Alternatively, consider wrapping a Servlet with Spring's ServletWrappingController. This is particularly appropriate for existing Servlet classes, allowing to specify Servlet initialization parameters etc.

Author:Juergen Hoeller
See Also:
Since:1.1.5
/** * {@link org.springframework.beans.factory.config.BeanPostProcessor} * that applies initialization and destruction callbacks to beans that * implement the {@link javax.servlet.Servlet} interface. * * <p>After initialization of the bean instance, the Servlet {@code init} * method will be called with a ServletConfig that contains the bean name * of the Servlet and the ServletContext that it is running in. * * <p>Before destruction of the bean instance, the Servlet {@code destroy} * will be called. * * <p><b>Note that this post-processor does not support Servlet initialization * parameters.</b> Bean instances that implement the Servlet interface are * supposed to be configured like any other Spring bean, that is, through * constructor arguments or bean properties. * * <p>For reuse of a Servlet implementation in a plain Servlet container * and as a bean in a Spring context, consider deriving from Spring's * {@link org.springframework.web.servlet.HttpServletBean} base class that * applies Servlet initialization parameters as bean properties, supporting * both the standard Servlet and the Spring bean initialization style. * * <p><b>Alternatively, consider wrapping a Servlet with Spring's * {@link org.springframework.web.servlet.mvc.ServletWrappingController}.</b> * This is particularly appropriate for existing Servlet classes, * allowing to specify Servlet initialization parameters etc. * * @author Juergen Hoeller * @since 1.1.5 * @see javax.servlet.Servlet#init(javax.servlet.ServletConfig) * @see javax.servlet.Servlet#destroy() * @see SimpleServletHandlerAdapter */
public class SimpleServletPostProcessor implements DestructionAwareBeanPostProcessor, ServletContextAware, ServletConfigAware { private boolean useSharedServletConfig = true; @Nullable private ServletContext servletContext; @Nullable private ServletConfig servletConfig;
Set whether to use the shared ServletConfig object passed in through setServletConfig, if available.

Default is "true". Turn this setting to "false" to pass in a mock ServletConfig object with the bean name as servlet name, holding the current ServletContext.

See Also:
  • setServletConfig
/** * Set whether to use the shared ServletConfig object passed in * through {@code setServletConfig}, if available. * <p>Default is "true". Turn this setting to "false" to pass in * a mock ServletConfig object with the bean name as servlet name, * holding the current ServletContext. * @see #setServletConfig */
public void setUseSharedServletConfig(boolean useSharedServletConfig) { this.useSharedServletConfig = useSharedServletConfig; } @Override public void setServletContext(ServletContext servletContext) { this.servletContext = servletContext; } @Override public void setServletConfig(ServletConfig servletConfig) { this.servletConfig = servletConfig; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof Servlet) { ServletConfig config = this.servletConfig; if (config == null || !this.useSharedServletConfig) { config = new DelegatingServletConfig(beanName, this.servletContext); } try { ((Servlet) bean).init(config); } catch (ServletException ex) { throw new BeanInitializationException("Servlet.init threw exception", ex); } } return bean; } @Override public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException { if (bean instanceof Servlet) { ((Servlet) bean).destroy(); } } @Override public boolean requiresDestruction(Object bean) { return (bean instanceof Servlet); }
Internal implementation of the ServletConfig interface, to be passed to the wrapped servlet.
/** * Internal implementation of the {@link ServletConfig} interface, * to be passed to the wrapped servlet. */
private static class DelegatingServletConfig implements ServletConfig { private final String servletName; @Nullable private final ServletContext servletContext; public DelegatingServletConfig(String servletName, @Nullable ServletContext servletContext) { this.servletName = servletName; this.servletContext = servletContext; } @Override public String getServletName() { return this.servletName; } @Override @Nullable public ServletContext getServletContext() { return this.servletContext; } @Override @Nullable public String getInitParameter(String paramName) { return null; } @Override public Enumeration<String> getInitParameterNames() { return Collections.enumeration(Collections.emptySet()); } } }