作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
基本流程图,方便查看
TomcatServletWebServerFactory的getWebServer
前面我们获取到了TomcatServletWebServerFactory
,现在就要创建了,创建TomcatWebServer
,里面会进行初始化,这里的方法就不多讲了,是关于tomcat
的一些组件的设置和启动,有兴趣可以自己研究下,我们重点关注springmvc
这边的。
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
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);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
return new TomcatWebServer(tomcat, getPort() >= 0);
}
public TomcatWebServer(Tomcat tomcat, boolean autoStart) {
Assert.notNull(tomcat, "Tomcat Server must not be null");
this.tomcat = tomcat;
this.autoStart = autoStart;
initialize();
}
ServletWebServerApplicationContext的finishRefresh
完成刷新后,就启动了服务器,并发出ServletWebServerInitializedEvent
事件:
DispatcherServlet初始化
流程图参考
第一次来请求的时候会进行初始化,调用initStrategies
方法,其实就是把需要的组件都获取到:
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);//上传文件
initLocaleResolver(context);//本地化
initThemeResolver(context);//主题
initHandlerMappings(context);//映射器
initHandlerAdapters(context);//处理器适配器
initHandlerExceptionResolvers(context);//异常处理
initRequestToViewNameTranslator(context);//视图名转换
initViewResolvers(context);//视图解析
initFlashMapManager(context);//重定向保存数据
}
内部其实很多都是一样的形式,我拿两个分析下:
initMultipartResolver
首先会获取名字为multipartResolver
的实例,如果不存在就为null
。
public static final String MULTIPART_RESOLVER_BEAN_NAME = "multipartResolver";
private void initMultipartResolver(ApplicationContext context) {
try {
this.multipartResolver = context.getBean(MULTIPART_RESOLVER_BEAN_NAME, MultipartResolver.class);
if (logger.isTraceEnabled()) {
logger.trace("Detected " + this.multipartResolver);
}
else if (logger.isDebugEnabled()) {
logger.debug("Detected " + this.multipartResolver.getClass().getSimpleName());
}
}
catch (NoSuchBeanDefinitionException ex) {
// Default is no multipart resolver.
this.multipartResolver = null;
if (logger.isTraceEnabled()) {
logger.trace("No MultipartResolver '" + MULTIPART_RESOLVER_BEAN_NAME + "' declared");
}
}
}
这个自动配置的时候有注册,具体在MultipartAutoConfiguration
中。
其他的我们下次来分析吧,看起来好像没多少东西,其实就是为了搞明白,初始化做了什么,组件是怎么来的。