// 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.prepareW
SpringBoot中,如何动态的注入Servlet的三大组件Servlet,Filter,Listener
于 2024-04-15 13:56:44 首次发布