// Servlet上下文对象
public class ServletWebServerApplicationContext {
// 后置处理BeanFactory
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// 添加处理ServletContextAware,ServletConfigAware回调的Bean的后置处理器
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
// 忽略依赖的接口的注入
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
// 注册web作用域
this.registerWebApplicationScopes();
}
// 注册Web作用域
private void registerWebApplicationScopes() {
// 保存之前的作用域
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(getBeanFactory());
// 注册Request,Session,Application域
WebApplicationContextUtils.registerWebApplicationScopes(getBeanFactory());
// 合并之前的和最新保存的作用域
existingScopes.restore();
}
// 容器即将刷新
protected void onRefresh() {
super.onRefresh();
// 创建web服务器
this.createWebServer();
}
// 创建web服务器
private void createWebServer() {
// 获取Web服务器对象
WebServer webServer = this.webServer;
// 获取ServletContext对象
ServletContext servletContext = this.servletContext;
// 如果都为空,表示没有初始化Web容器
if (webServer == null && servletContext == null) {
// 获取创建WebServer的工厂
ServletWebServerFactory factory = this.getWebServerFactory();
// 获取容器中所有的ServletContextInitializer初始化器
ServletContextInitializer initializer = this.getSelfInitializer();
// 创建Web服务器
this.webServer = factory.getWebServer(initializer) {
// Tomcat的实现
// 创建Tomcat服务器
Tomcat tomcat = new Tomcat();
// 设置一些相关属性
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
tomcat.getService().addConnector(connector);
customizeConnector(connector) {
int port = Math.max(getPort(), 0);
connector.setPort(port);
// 对连接进行自定义
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
customizer.customize(connector);
}
}
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
// 返回WebServer对象
return getTomcatWebServer(tomcat) {
// 启动Tomcat服务器
this.tomcat.start();
}
}
}
// 如果servletContext初始化了
else if (servletContext != null) {
// 获取容器中所有的ServletContextInitializer初始化器
ServletContextInitializer initializer = this.getSelfInitializer();
// 回调该ServletContextInitializer接口的onStartup
/**
* @see {@link ServletWebServerApplicationContext#getSelfInitializer}执行
* 其实就是触发{@link ServletWebServerApplicationContext#selfInitialize}执行
*/
initializer.onStartup(servletContext);
}
// 初始化Servlet相关的属性配置
this.initPropertySources();
}
// 初始化Servlet相关的属性配置
protected void initPropertySources() {
ConfigurableEnvironment env = getEnvironment();
if (env instanceof ConfigurableWebEnvironment) {
((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null) {
WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig)
{
// 环境对象中,是否包含servletContextInitParams的配置
// 在创建环境对象的时候,就已经在构造方法中进行了配置,配置的属性源是一个占位的,类型为StubPropertySource
String name = StandardServletEnvironment.SERVLET_CONTEXT_PROPERTY_SOURCE_NAME;
// 将占位的属性源替换为ServletContextPropertySource这种属性源
if (servletContext != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
// 这样从servletContextInitParams获取的配置,实际上就是从servletContext获取配置
sources.replace(name, new ServletContextPropertySource(name, servletContext));
}
// 环境对象中,是否包含servletConfigInitParams的配置
// 在创建环境对象的时候,就已经在构造方法中进行了配置,配置的属性源是一个占位的,类型为StubPropertySource
name = StandardServletEnvironment.SERVLET_CONFIG_PROPERTY_SOURCE_NAME;
// 将占位的属性源替换为ServletConfigPropertySource这种属性源
if (servletConfig != null && sources.contains(name) && sources.get(name) instanceof StubPropertySource) {
// 这样从servletConfigInitParams获取的配置,实际上就是从servletConfig获取配置
sources.replace(name, new ServletConfigPropertySource(name, servletConfig));
}
}
}
}
}
// 获取容器中所有的ServletContextInitializer初始化器
private ServletContextInitializer getSelfInitializer() {
// return this::selfInitialize;
return new ServletContextInitializer() {
/**
* 该对象是由Tomcat创建的,onStartup最终也是通过tomcat回调的
* @see {@link org.springframework.boot.web.embedded.tomcat.TomcatStarter}
* 该类实现了ServletContainerInitializer接口,该接口为servlet规范中的初始化接口
* 通过SCI,META-INF/services/javax.servlet.ServletContainerInitializer方法注册
* 但是,TomcatStarter是通过手动创建的,并没有使用SCI注册
* 在{@link org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory#configureContext}中创建的对象
* 其中,在此刻与Spring提供的ServletContextInitializer接口上下文初始化器进行整合,将initializers传递给了TomcatStarter
* 然后调用Api,context.addServletContainerInitializer(starter, NO_CLASSES),将TomcatStarter动态注册到Tomcat上下文中
* 最终Tomcat就会执行所有实现了ServletContainerInitializer接口的onStartup方法
* 而在TomcatStarter内部的onStartup方法中,执行所有ServletContextInitializer的onStartup方法
*
* tip: TomcatStarter注册的方式是使用APi调用,而不是使用SCI,SCI的方式为: 在META-INF/services/javax.servlet.ServletContainerInitializer文件中添加实现类的全类名
* @param servletContext Servlet上下文,Tomcat创建好了ServletContext对象才会回调该方法
*/
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
ServletWebServerApplicationContext.this.selfInitialize(servletContext);
}
}
}
// 获取容器中所有的ServletContextInitializer初始化器
// 并且回调初始化方法
private void selfInitialize(ServletContext servletContext) {
// 提前处理下Web的上下文对象,给上下文设置ServletContext
this.prepareWebApplicationContext(servletContext);
// 注册Web的Application作用域
this.registerApplicationScope(servletContext);
// 将Servlet相关的参数注册为Bean,例如servletContext,servletConfig,contextParameters,contextAttributes这些Bean
WebApplicationContextUtils.registerEnvironmentBeans(getBeanFactory(), servletContext);
// 获取到容器中所有ServletContextInitializer类型的Bean,并执行初始化操作
Collection<ServletContextInitializer> servletContextInitializerBean = new ServletContextInitializerBeans(getBeanFactory());
// 执行提取到的ServletContextInitializer,包括动态添加Servlet三大组件的RegistrationBean
for (ServletContextInitializer beans : servletContextInitializerBean) {
// 执行这个初始化的onStartup方法
beans.onStartup(servletContext);
}
}
// 注册ServletContext:Application作用域
private void registerApplicationScope(ServletContext servletContext) {
ServletContextScope appScope = new ServletContextScope(servletContext);
// 注册到BeanFactory中
getBeanFactory().registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
// 保存到servletContext中
servletContext.setAttribute(ServletContextScope.class.getName(), appScope);
}
// 提前处理下Web的上下文对象,给上下文设置ServletContext
protected void prepareWebApplicationContext(ServletContext servletContext) {
// WebApplicationContext.class.getName() + ".ROOT",获取Spring父容器
Object rootContext = servletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
// 如果已经创建的父容器
if (rootContext != null) {
// 校验当前容器不能是自己,因为自身已经初始化过了
if (rootContext == this) {
throw new IllegalStateException("Cannot initialize context because there is already a root application context present - " + "check whether you have multiple ServletContextInitializers!");
}
return;
}
Log logger = LogFactory.getLog(ContextLoader.class);
try {
// 将当前上下文对象保存到ServletContext中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, this);
// 该当前上下文设置ServletContext
this.setServletContext(servletContext);
} catch (RuntimeException | Error ex) {
// 如果发生异常,将异常保存到该ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE对应的Key中
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ex);
throw ex;
}
}
// 从Spring中获取ServletWebServerFactory的Bean
protected ServletWebServerFactory getWebServerFactory() {
// 从Spring中获取ServletWebServerFactory的Bean
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
// 如果不存在,抛出异常
if (beanNames.length == 0) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to missing " + "ServletWebServerFactory bean.");
}
// 如果存在多个,抛出异常
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple " + "ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
// 获取容器中的Bean
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
public void setServletContext(@Nullable ServletContext servletContext) {
this.servletContext = servletContext;
}
// 动态注册Servlet
// 动态注入Filter和Listener都是差不多
class DispatcherServletRegistrationBean
// extends ServletRegistrationBean<DispatcherServlet>
// extends DynamicRegistrationBean<ServletRegistration.Dynamic>
extends RegistrationBean implements ServletContextInitializer {
// 该初始化器的初始化方法,这里是动态添加Servlet三大组件的入口
@Override
public final void onStartup(ServletContext servletContext) throws ServletException {
// 动态注册Servlet
this.register(description, servletContext);
}
@Override
protected final void register(String description, ServletContext servletContext) {
// 动态添加Servlet,返回javax.servlet提供的ServletRegistration.Dynamic类
D registration = this.addRegistration(description, servletContext);
// 对该动态注册的对象进行配置
this.configure(registration);
}
// 动态注册,该方法是父类中抽象的方法,对应不同的实现
// 在Filter中,这里是addFilter,在Servlet中,就是addServlet
@Override
protected ServletRegistration.Dynamic addRegistration(String description, ServletContext servletContext) {
// 动态添加Servlet,调用java.servlet的API
String name = getServletName();
return servletContext.addServlet(name, this.servlet);
}
// 对该动态注册的对象进行配置,该方法是父类中抽象的方法,对应不同的实现
// 在Filter中,这里是配置filter的拦截路径,在Servlet中,就是配置拦截URL,设置初始化参数,设置文件配置信息等等
@Override
protected void configure(ServletRegistration.Dynamic registration) {
super.configure(registration) {
// 这个Servlet组件是否支持异步
registration.setAsyncSupported(this.asyncSupported);
// 如果提供了初始化参数
if (!this.initParameters.isEmpty()) {
// 设置初始化参数
registration.setInitParameters(this.initParameters);
}
}
// 设置Servlet拦截的路径
String[] urlMapping = StringUtils.toStringArray(this.urlMappings);
if (urlMapping.length == 0 && this.alwaysMapUrl) {
urlMapping = DEFAULT_MAPPINGS;
}
if (!ObjectUtils.isEmpty(urlMapping)) {
registration.addMapping(urlMapping);
}
// 设置启动的时机
registration.setLoadOnStartup(this.loadOnStartup);
// 如果设置了文件相关配置
if (this.multipartConfig != null) {
// 设置文件配置信息
registration.setMultipartConfig(this.multipartConfig);
}
}
}
// 封装了Spring容器中所有ServletContextInitializer类型的Bean
class ServletContextInitializerBeans extends AbstractCollection<ServletContextInitializer> {
// dispatcher_servlet的名称 dispatcherServlet
private static final String DISPATCHER_SERVLET_NAME = "dispatcherServlet";
/**
* 不同ServletContextInitializer类型提供的Bean对象
*
* @see {@link ServletWebServerApplicationContext.ServletContextInitializerBeans#addServletContextInitializerBean(String, ServletContextInitializer, ListableBeanFactory)}
*/
private final Set<Object> seen = new HashSet<>();
// 需要初始化的ServletContextInitializer集合
// 当ServletContextInitializer类型为RegistrationBean,key为Servlet三大组件的类型
// 当ServletContextInitializer就是一个普通的ServletContextInitializer,key为本身
private final MultiValueMap<Class<?>, ServletContextInitializer> initializers;
// 需要查找的ServletContextInitializer的类型
private final List<Class<? extends ServletContextInitializer>> initializerTypes;
// 对this.initializers的values进行排序后的ServletContextInitializer
private List<ServletContextInitializer> sortedList;
/**
* @param beanFactory bean工厂
* @param initializerTypes 指定类型的初始化器
*/
public ServletContextInitializerBeans(ListableBeanFactory beanFactory, Class<? extends ServletContextInitializer>... initializerTypes) {
this.initializers = new LinkedMultiValueMap<>();
// 如果没有指定,默认为ServletContextInitializer类型
this.initializerTypes = (initializerTypes.length != 0) ? Arrays.asList(initializerTypes) : Collections.singletonList(ServletContextInitializer.class);
// 处理所有的ServletContextInitializer的Bean,并将这个ServletContextInitializer提供的Bean对象保存
this.addServletContextInitializerBeans(beanFactory);
// 将Spring中的Servlet三大组件,适配为RegistrationBean类型,然后通过RegistrationBean对它们进行动态祖册
this.addAdaptableBeans(beanFactory);
// 将ServletContextInitializer进行排序
List<ServletContextInitializer> sortedInitializers = this.initializers.values().stream()
// 将所有的ServletContextInitializer进行合并并排序
.flatMap((value) -> value.stream().sorted(AnnotationAwareOrderComparator.INSTANCE))
.collect(Collectors.toList());
// 保存排好序的ServletContextInitializer
this.sortedList = Collections.unmodifiableList(sortedInitializers);
// 打印映射日志
this.logMappings(this.initializers);
}
// 打印映射日志
public void logMappings(MultiValueMap<Class<?>, ServletContextInitializer> initializers) {
if (logger.isDebugEnabled()) {
this.logMappings("filters", initializers, Filter.class, FilterRegistrationBean.class);
this.logMappings("servlets", initializers, Servlet.class, ServletRegistrationBean.class);
}
}
/**
* @param name 组件的名称概要
* @param initializers 所有的ServletContextInitializer
* @param type 三大组件的类型
* @param registrationType 三个组件对应的RegistrationBean类型
*/
private void logMappings(String name, MultiValueMap<Class<?>, ServletContextInitializer> initializers, Class<?> type, Class<? extends RegistrationBean> registrationType) {
List<ServletContextInitializer> registrations = new ArrayList<>();
// 获取指定RegistrationBean类型对应的Initializer
registrations.addAll(initializers.getOrDefault(registrationType, Collections.emptyList()));
// 获取指定三大组件类型对应的initializer
registrations.addAll(initializers.getOrDefault(type, Collections.emptyList()));
// 使用,拼接打印
String info = registrations.stream().map(Object::toString).collect(Collectors.joining(", "));
logger.debug("Mapping " + name + ": " + info);
}
/**
* 将Spring中的Servlet三大组件,适配为RegistrationBean类型,然后通过RegistrationBean对它们进行动态祖册
*/
protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
// 获取Multipart相关配置
MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory) {
// 获取MultipartConfigElement类型的Bean返回,只返回一个
List<Entry<String, MultipartConfigElement>> beans = this.getOrderedBeansOfType(beanFactory, MultipartConfigElement.class);
return beans.isEmpty() ? null : beans.get(0).getValue();
}
// 将Spring中的Servlet三大组件中的Servlet组件,通过RegistrationBean类动态注册,该Serverlet对应的RegistrationBean是通过ServletRegistrationBeanAdapter来生成
this.addAsRegistrationBean(beanFactory, Servlet.class, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
// 将Spring中的Servlet三大组件中的Filter组件,通过RegistrationBean类动态注册,该Filter对应的RegistrationBean是通过FilterRegistrationBeanAdapter来生成
this.addAsRegistrationBean(beanFactory, Filter.class, Filter.class, new FilterRegistrationBeanAdapter());
// types.add(ServletContextAttributeListener.class);
// types.add(ServletRequestListener.class);
// types.add(ServletRequestAttributeListener.class);
// types.add(HttpSessionAttributeListener.class);
// types.add(HttpSessionListener.class);
// types.add(ServletContextListener.class);
Set<Class<?>> types = ServletListenerRegistrationBean.getSupportedTypes();
for (Class<?> listenerType : types) {
// 将Spring中的Servlet三大组件中的Listener组件,通过RegistrationBean类动态注册,该Listener对应的RegistrationBean是通过ServletListenerRegistrationBeanAdapter来生成
this.addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType, new ServletListenerRegistrationBeanAdapter());
}
}
/**
* 将Spring中的Servlet三大组件,通过RegistrationBean类,动态注册三大组件
* RegistrationBean本身是一个ServletContextInitializer,该类型用于注册Servlet,Filter,Listener...Servlet类型组件的抽象
* 该类可以提供一个对象类型的实例,例如FilterRegistrationBean提供Filter,ServletRegistrationBean注册Servlet
* 为什么要创建RegistrationBean?因为潜规定只有RegistrationBean才有注册组件的权利,所以我们注册的三大组件的Bean对象,例如Servlet,Filter对象
* 我们就需要包装成RegistrationBean,通过RegistrationBean来动态注册这些组件,为什么说是潜规定呢?
* 因为我们拿到了ServletContext对象之后,我们自己也可以通过addXXX来注册组件
*
* @param beanFactory Bean工厂
* @param type Servlet三大组件的抽象类型 Servlet.class,Filter.class,EventListener.class
* @param beanType Servlet.class,Filter.class,EventListener.class: Servlet三大组件的Bean类型,其中Listener类型有多种,可以是session,Request的,还有其他类型的
* @param adapter 创建RegistrationBean的适配器,而RegistrationBean就是动态注册Servlet三大组件的抽象类
*/
private <T, B extends T> void addAsRegistrationBean(ListableBeanFactory beanFactory, Class<T> type, Class<B> beanType, RegistrationBeanAdapter<T> adapter) {
// 获取Servlet三大组件的抽象类型的Bean,并且在this.seen中保存的bean需要被排除
List<Map.Entry<String, B>> entries = this.getOrderedBeansOfType(beanFactory, beanType, this.seen);
// 遍历所有该类型的Bean
for (Entry<String, B> entry : entries) {
String beanName = entry.getKey();
B bean = entry.getValue();
// 如果这个组件能保存成功,表示在之前没有被动态添加过
// seen保存之前处理过的Servelt三个组件
if (this.seen.add(bean)) {
// 创建一个RegistrationBean,RegistrationBean本身是一个ServletContextInitializer,该类型用于注册Servlet,Filter,Listener...Servlet类型组件的抽象
// 该类可以提供一个对象类型的实例,例如FilterRegistrationBean提供Filter,ServletRegistrationBean注册Servlet
// 为什么要创建RegistrationBean?因为潜规定只有RegistrationBean才有注册组件的权利,所以我们注册的三大组件的Bean对象,例如Servlet,Filter对象
// 我们就需要包装成RegistrationBean,通过RegistrationBean来动态注册这些组件,为什么说是潜规定呢?
// 因为我们拿到了ServletContext对象之后,我们自己也可以通过addXXX来注册组件
// 使用RegistrationBean的适配器创建一个RegistrationBean实例
RegistrationBean registrationBean = adapter.createRegistrationBean(beanName, bean, entries.size());
// 获取该Bean的顺序,因为Servelt三大组件的顺序还是比较重要
int order = getOrder(bean);
// 设置优先级
registration.setOrder(order);
// 保存该RegistrationBean到Map中,类型为对应的组件类型,它是一个ServletContextInitializer,保存到容器中
this.initializers.add(type, registration);
}
}
}
/**
* 根据类型获取排序之后的Bean对象
*
* @param beanFactory bean工厂
* @param type bean类型
* @param excludes 需要排序的类型或者beanName
* @return 符合条件的这些Bean
*/
private <T> List<Entry<String, T>> getOrderedBeansOfType(ListableBeanFactory beanFactory, Class<T> type, Set<?> excludes) {
// 获取指定类型的所有Bean名称
String[] names = beanFactory.getBeanNamesForType(type, true, false);
Map<String, T> map = new LinkedHashMap<>();
// 遍历所有的beanName
for (String name : names) {
// 如果该beaName没有被排除,并且该类不是作用域的代理类
if (!excludes.contains(name) && !ScopedProxyUtils.isScopedTarget(name)) {
// 获取该Bean对象
T bean = beanFactory.getBean(name, type);
// 如果该Bean没有被排除
if (!excludes.contains(bean)) {
// 保存该Bean
map.put(name, bean);
}
}
}
List<Entry<String, T>> beans = new ArrayList<>(map.entrySet());
// 对这些类型的Bean进行排序
beans.sort((o1, o2) -> AnnotationAwareOrderComparator.INSTANCE.compare(o1.getValue(), o2.getValue()));
// 返回保存的所有bean
return beans;
}
// 处理所有的ServletContextInitializer的Bean
public void addServletContextInitializerBeans(ListableBeanFactory beanFactory) {
// 遍历指定的ServletContextInitializer类型
for (Class<? extends ServletContextInitializer> initializerType : this.initializerTypes) {
// 根据指定类型获取ServletContextInitializer的Bean
for (Entry<String, ? extends ServletContextInitializer> initializerBean : getOrderedBeansOfType(beanFactory, initializerType)) {
// 根据不同的类型进行区分做不同的处理,并保存该initializer
this.addServletContextInitializerBean(initializerBean.getKey(), initializerBean.getValue(), beanFactory);
}
}
}
// 根据不同的类型进行区分做不同的处理,并保存该initializer,同时将初始化器提供的Servlet相关组件的Bean进行保存
public void addServletContextInitializerBean(String beanName, ServletContextInitializer initializer, ListableBeanFactory beanFactory) {
// 如果初始化器是ServletRegistrationBean类型,表示该Bean是一个用于动态注册Servlet的Bean对象
if (initializer instanceof ServletRegistrationBean) {
// 提供的这个servlet可以是bean,也可以不是bean,如果需要给spring管理,那就需要注册为bean
// 如果我们自己写的,就看自己需不需要注册为bean,spring内置的这些都注册为bean了
// 下面的Listener和Filter也是一样的
Servlet source = ((ServletRegistrationBean<?>) initializer).getServlet();
this.addServletContextInitializerBean(Servlet.class, beanName, initializer, beanFactory, source);
return;
}
// 如果初始化器是FilterRegistrationBean类型,表示该Bean是一个用于动态注册Filter的Bean对象
if (initializer instanceof FilterRegistrationBean) {
// 保存该initializer,并指定该类处理的源类型为Servlet
Filter source = ((FilterRegistrationBean<?>) initializer).getFilter();
this.addServletContextInitializerBean(Filter.class, beanName, initializer, beanFactory, source);
return;
}
// 如果初始化器是DelegatingFilterProxyRegistrationBean类型,表示该Bean是一个用于动态注册Filter的Bean对象
// 这个对象与FilterRegistrationBean区别
// DelegatingFilterProxyRegistrationBean: 通过getFilter返回的是一个代理对象DelegatingFilterProxy(静态代理)
// 这个代理对象DelegatingFilterProxy执行实际上是依靠该对象引用的beanName对应的容器中的Filter进行工作的
// 而FilterRegistrationBean
if (initializer instanceof DelegatingFilterProxyRegistrationBean) {
String source = ((DelegatingFilterProxyRegistrationBean) initializer).getTargetBeanName();
this.addServletContextInitializerBean(Filter.class, beanName, initializer, beanFactory, source);
return;
}
// 如果初始化器是ServletListenerRegistrationBean类型,表示该Bean是一个用于动态注册Servlet的listener的Bean对象
if (initializer instanceof ServletListenerRegistrationBean) {
EventListener source = ((ServletListenerRegistrationBean<?>) initializer).getListener();
this.addServletContextInitializerBean(EventListener.class, beanName, initializer, beanFactory, source);
return;
}
// 其他情况,保存该initializer,并将当前initializer对象本身进行保存
this.addServletContextInitializerBean(ServletContextInitializer.class, beanName, initializer, beanFactory, initializer);
}
/**
* 保存该initializer,同时记录该initializer提供的bean对象,可能是ServletContextInitializer本身,也可能是Servlet,Filter,Listener
*
* @see {@link ServletContextInitializerBeans#addServletContextInitializerBean(String, ServletContextInitializer, ListableBeanFactory)}
*/
public void addServletContextInitializerBean(Class<?> type, String beanName, ServletContextInitializer initializer, ListableBeanFactory beanFactory, Object source) {
// 保存找到的ServletContextInitializer
this.initializers.add(type, initializer);
// 保存该ServletContextInitializer类需要的源类型
if (source != null) {
this.seen.add(source);
}
}
}
// 注册Bean的工具类
class WebApplicationContextUtils {
// 注册Servelt相关的Bean,不注册ServletConfig
public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, @Nullable ServletContext sc) {
this.registerEnvironmentBeans(bf, sc, null);
}
// 注册Servelt相关的所有Bean
public static void registerEnvironmentBeans(ConfigurableListableBeanFactory bf, ServletContext servletContext, @Nullable ServletConfig servletConfig) {
// 如果容器中不存在servletContext的Bean
if (servletContext != null && !bf.containsBean(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME)) {
// 注册该Bean
bf.registerSingleton(WebApplicationContext.SERVLET_CONTEXT_BEAN_NAME, servletContext);
}
// 如果不存在servletConfig的Bena
if (servletConfig != null && !bf.containsBean(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME)) {
// 注册该Bean
bf.registerSingleton(ConfigurableWebApplicationContext.SERVLET_CONFIG_BEAN_NAME, servletConfig);
}
// 如果容器中不存在contextParameters的Bean
if (!bf.containsBean(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME)) {
Map<String, String> parameterMap = new HashMap<>();
// 加载servletContext中的初始化配置
if (servletContext != null) {
// ServletContext 对象代表了整个 web 应用程序的上下文,在整个应用程序范围内共享
Enumeration<?> paramNameEnum = servletContext.getInitParameterNames();
// 将数据保存到parameterMap中
while (paramNameEnum.hasMoreElements()) {
String paramName = (String) paramNameEnum.nextElement();
parameterMap.put(paramName, servletContext.getInitParameter(paramName));
}
}
// 加载servletConfig中的初始化配置
if (servletConfig != null) {
// ServletConfig对象代表了一个特定的Servlet的配置信息,I每个Servlet都有自己的ServletConfig对象
Enumeration<?> paramNameEnum = servletConfig.getnitParameterNames();
while (paramNameEnum.hasMoreElements()) {
String paramName = (String) paramNameEnum.nextElement();
parameterMap.put(paramName, servletConfig.getInitParameter(paramName));
}
}
// 注册该contextParameters的Bean
bf.registerSingleton(WebApplicationContext.CONTEXT_PARAMETERS_BEAN_NAME, Collections.unmodifiableMap(parameterMap));
}
// 如果容器中不存在contextAttributes的Bean
if (!bf.containsBean(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME)) {
Map<String, Object> attributeMap = new HashMap<>();
if (servletContext != null) {
// 获取上下文中所有的属性配置
Enumeration<?> attrNameEnum = servletContext.getAttributeNames();
while (attrNameEnum.hasMoreElements()) {
String attrName = (String) attrNameEnum.nextElement();
attributeMap.put(attrName, servletContext.getAttribute(attrName));
}
}
// 将ServletContext中所有的属性注册为Bean
bf.registerSingleton(WebApplicationContext.CONTEXT_ATTRIBUTES_BEAN_NAME, Collections.unmodifiableMap(attributeMap));
}
}
// 注册Servelt相关的Bean,不注册ServletConfig
public static void registerWebApplicationScopes(ConfigurableListableBeanFactory beanFactory, ServletContext sc) {
// 注册Request域
beanFactory.registerScope(WebApplicationContext.SCOPE_REQUEST, new RequestScope());
// 注册Session域
beanFactory.registerScope(WebApplicationContext.SCOPE_SESSION, new SessionScope());
if (sc != null) {
// 注册application域
ServletContextScope appScope = new ServletContextScope(sc);
beanFactory.registerScope(WebApplicationContext.SCOPE_APPLICATION, appScope);
sc.setAttribute(ServletContextScope.class.getName(), appScope);
}
// 注册对这些类型的ObjectFactory依赖,例如: 注入ServletRequest,使用返回RequestObjectFactory
beanFactory.registerResolvableDependency(ServletRequest.class, new RequestObjectFactory());
beanFactory.registerResolvableDependency(ServletResponse.class, new ResponseObjectFactory());
beanFactory.registerResolvableDependency(HttpSession.class, new SessionObjectFactory());
beanFactory.registerResolvableDependency(WebRequest.class, new WebRequestObjectFactory());
}
}
}
// 上下文环境对象
public class ConfigurableEnvironment {
public AbstractEnvironment() {
// 自定义配置属性源
this.customizePropertySources(this.propertySources);
}
// 自定义配置属性源,该方法是AbstractEnvironment的空实现的钩子方法,这里提供两个不同实现源码
protected void customizePropertySources(MutablePropertySources propertySources) {
// org.springframework.core.env.StandardEnvironment.customizePropertySources
{
// systemProperties
propertySources.addLast(new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
// systemEnvironment
propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
// org.springframework.web.context.support.StandardServletEnvironment.customizePropertySources
{
// servletConfigInitParams,这个目前只是一个占位
propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
// servletContextInitParams,这个目前只是一个占位
propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
}
// 调用父类的自定义方法
super.customizePropertySources(propertySources);
}
}
// 保存了程序中所有的配置属性键值对集合
public final MutablePropertySources propertySources = new MutablePropertySources();
// 获取程序中所有的配置属性键值对集合
public MutablePropertySources getPropertySources() {
return this.propertySources;
}
public class MutablePropertySources {
// 保存了程序中所有的配置属性键值对集合,每一个单独的配置都是一个PropertySource,其中PropertySource具有name和源数据
public final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<>();
}
}
@Configuration
public class FB {
static class LuckFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.err.println(request.getRemoteHost());
chain.doFilter(request, response);
}
}
// 这种方式,最终也会将Filter包装成FilterRegistrationBean注册ServletContext中
@Component
static class LuckFilter1 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.err.println(request.getRemoteHost());
chain.doFilter(request, response);
}
}
@Bean("luckFilterRegistrationBean")
public FilterRegistrationBean<LuckFilter> filterRegistrationBean() {
FilterRegistrationBean<LuckFilter> registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new LuckFilter());
return registrationBean;
}
}