概述
WebApplicationContextServletContextAwareProcessor
被用于向bean
注入ConfigurableWebApplicationContext
应用上下文,它仅仅用在当前应用是一个Springboot
+ Spring MVC
(也就是Servlet
)Web
应用的情况下。如果当前应用是一个非Spring boot Servlet Web
应用,而是一个非Servlet
应用,或者非Web
的命令行应用,则WebApplicationContextServletContextAwareProcessor
根本不会出现在应用上下文中。
WebApplicationContextServletContextAwareProcessor
继承自ServletContextAwareProcessor
,而ServletContextAwareProcessor
是Spring MVC Web
应用(不一定要基于Springboot
)中应用上下文向bean
设置ServletContext
的BeanPostProcessor
。可以认为WebApplicationContextServletContextAwareProcessor
是ServletContextAwareProcessor
针对Springboot
环境的一个变种,其目的一致。
对比父类ServletContextAwareProcessor
,WebApplicationContextServletContextAwareProcessor
获取ServletContext
,ServletConfig
的方式有所不同:它先尝试从指定的ConfigurableWebApplicationContext
应用上下文中获取ServletContext
,ServletConfig
,如果获取不到,才使用父类ServletContextAwareProcessor
定义的方式再尝试获取ServletContext
,ServletConfig
。二者向bean
设置ServletContext
,ServletConfig
的逻辑是一样的。
WebApplicationContextServletContextAwareProcessor
自己会由应用上下文创建和注册到bean
容器,不需要应用开发人员操心。具体注册位置如下:
// 类 ServletWebServerApplicationContext 代码片段
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
}
相应调用栈举例 :
SpringApplication#run
=> SpringApplication#refresh
==> ServletWebServerApplicationContext#refresh
===> AbstractApplicationContext#refresh
====> AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory
=====> ServletWebServerApplicationContext#postProcessBeanFactory
WebApplicationContextServletContextAwareProcessor
位于包package org.springframework.boot.web.servlet.context
。
源代码解析
WebApplicationContextServletContextAwareProcessor
package org.springframework.boot.web.servlet.context;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.util.Assert;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.ServletContextAwareProcessor;
/**
* @author Phillip Webb
*/
public class WebApplicationContextServletContextAwareProcessor
extends ServletContextAwareProcessor {
private final ConfigurableWebApplicationContext webApplicationContext;
public WebApplicationContextServletContextAwareProcessor(
ConfigurableWebApplicationContext webApplicationContext) {
Assert.notNull(webApplicationContext, "WebApplicationContext must not be null");
this.webApplicationContext = webApplicationContext;
}
@Override
protected ServletContext getServletContext() {
// 先尝试从webApplicationContext中获取ServletContext,如果获取不到
// 然后再使用父类的方式获取
ServletContext servletContext = this.webApplicationContext.getServletContext();
return (servletContext != null) ? servletContext : super.getServletContext();
}
@Override
protected ServletConfig getServletConfig() {
// 先尝试从webApplicationContext中获取servletConfig ,如果获取不到
// 然后再使用父类的方式获取
ServletConfig servletConfig = this.webApplicationContext.getServletConfig();
return (servletConfig != null) ? servletConfig : super.getServletConfig();
}
}
ServletContextAwareProcessor
package org.springframework.web.context.support;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.lang.Nullable;
import org.springframework.web.context.ServletConfigAware;
import org.springframework.web.context.ServletContextAware;
/**
* @author Juergen Hoeller
* @author Phillip Webb
* @since 12.03.2004
* @see org.springframework.web.context.ServletContextAware
* @see org.springframework.web.context.support.XmlWebApplicationContext#postProcessBeanFactory
*/
public class ServletContextAwareProcessor implements BeanPostProcessor {
@Nullable
private ServletContext servletContext;
@Nullable
private ServletConfig servletConfig;
/**
* Create a new ServletContextAwareProcessor without an initial context or config.
* When this constructor is used the #getServletContext() and/or
* #getServletConfig() methods should be overridden.
*/
protected ServletContextAwareProcessor() {
}
/**
* Create a new ServletContextAwareProcessor for the given context.
*/
public ServletContextAwareProcessor(ServletContext servletContext) {
this(servletContext, null);
}
/**
* Create a new ServletContextAwareProcessor for the given config.
*/
public ServletContextAwareProcessor(ServletConfig servletConfig) {
this(null, servletConfig);
}
/**
* Create a new ServletContextAwareProcessor for the given context and config.
*/
public ServletContextAwareProcessor(@Nullable ServletContext servletContext,
@Nullable ServletConfig servletConfig) {
this.servletContext = servletContext;
this.servletConfig = servletConfig;
}
/**
* Returns the ServletContext to be injected or null. This method
* can be overridden by subclasses when a context is obtained after the post-processor
* has been registered.
*/
@Nullable
protected ServletContext getServletContext() {
if (this.servletContext == null && getServletConfig() != null) {
return getServletConfig().getServletContext();
}
return this.servletContext;
}
/**
* Returns the ServletConfig to be injected or null. This method
* can be overridden by subclasses when a context is obtained after the post-processor
* has been registered.
*/
@Nullable
protected ServletConfig getServletConfig() {
return this.servletConfig;
}
// BeanPostProcessor 定义的方法,在bean创建时,实例化后,初始化前应用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
// 如果 bean 实现了 ServletContextAware 接口,并且 servletContext 不为 null,
// 则设置 bean 的 servletContext 属性
if (getServletContext() != null && bean instanceof ServletContextAware) {
((ServletContextAware) bean).setServletContext(getServletContext());
}
// 如果 bean 实现了 ServletConfigAware 接口,并且 servletConfig 不为 null,
// 则设置 bean 的 servletConfig 属性
if (getServletConfig() != null && bean instanceof ServletConfigAware) {
((ServletConfigAware) bean).setServletConfig(getServletConfig());
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}