Spring Boot Tomcat 启动流程
Tomcat Spring Boot 面试 About 8,561 words版本
Spring Boot 2.6.0
启动流程
加载自动配置
spring-boot-autoconfigure-2.6.0.jar
下META-INF/spring.factories
中配置的Auto Configure
的值。
@Configuration(proxyBeanMethods = false)
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServletRequest.class)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(ServerProperties.class)
@Import({ ServletWebServerFactoryAutoConfiguration.BeanPostProcessorsRegistrar.class,
ServletWebServerFactoryConfiguration.EmbeddedTomcat.class,
ServletWebServerFactoryConfiguration.EmbeddedJetty.class,
ServletWebServerFactoryConfiguration.EmbeddedUndertow.class })
public class ServletWebServerFactoryAutoConfiguration {
}
ServletWebServerFactoryAutoConfiguration
注解@Import
导入的配置类
@Configuration(proxyBeanMethods = false)
class ServletWebServerFactoryConfiguration {
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Tomcat.class, UpgradeProtocol.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedTomcat {
@Bean
TomcatServletWebServerFactory tomcatServletWebServerFactory(//...) {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Server.class, Loader.class, WebAppContext.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedJetty {
@Bean
JettyServletWebServerFactory JettyServletWebServerFactory(//...) {
}
}
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass({ Servlet.class, Undertow.class, SslClientAuthMode.class })
@ConditionalOnMissingBean(value = ServletWebServerFactory.class, search = SearchStrategy.CURRENT)
static class EmbeddedUndertow {
@Bean
UndertowServletWebServerFactory undertowServletWebServerFactory(//...) {
}
}
}
IOC 容器 onRefresh
onRefresh
中重写了父类AbstractApplicationContext
的空实现方法onRefresh
public class ServletWebServerApplicationContext extends GenericWebApplicationContext implements ConfigurableWebServerApplicationContext {
@Override
protected void onRefresh() {
super.onRefresh();
try {
// 创建 Web 容器
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
private void createWebServer() {
WebServer webServer = this.webServer;
// 刚开始 webServer 和 servletContext 都为 null
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
// 获取
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer));
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context", ex);
}
}
initPropertySources();
}
protected ServletWebServerFactory getWebServerFactory() {
// 根据 ServletWebServerFactory 类型获取
// 在文章前面读取到的 ServletWebServerFactoryConfiguration 配置类
// 如果是 Tomcat 就是 TomcatServletWebServerFactory
String[] beanNames = getBeanFactory().getBeanNamesForType(ServletWebServerFactory.class);
// 如果有多个 Web 容器会抛出异常
if (beanNames.length > 1) {
throw new ApplicationContextException("Unable to start ServletWebServerApplicationContext due to multiple ServletWebServerFactory beans : " + StringUtils.arrayToCommaDelimitedString(beanNames));
}
return getBeanFactory().getBean(beanNames[0], ServletWebServerFactory.class);
}
}
TomcatServletWebServerFactory
的getWebServer
方法中创建Tomcat
容器
public class TomcatServletWebServerFactory extends AbstractServletWebServerFactory implements ConfigurableTomcatWebServerFactory, ResourceLoaderAware {
@Override
public WebServer getWebServer(ServletContextInitializer... initializers) {
// 创建 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);
tomcat.setConnector(connector);
tomcat.getHost().setAutoDeploy(false);
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
prepareContext(tomcat.getHost(), initializers);
// 调用自身方法,传入 tomcat 对象
return getTomcatWebServer(tomcat);
}
protected TomcatWebServer getTomcatWebServer(Tomcat tomcat) {
// 创建 TomcatWebServer 对象
return new TomcatWebServer(tomcat, getPort() >= 0, getShutdown());
}
}
TomcatWebServer
构造中启动Tomcat
服务
public class TomcatWebServer implements WebServer {
private final Object monitor = new Object();
// 构造函数
public TomcatWebServer(Tomcat tomcat, boolean autoStart, Shutdown shutdown) {
this.tomcat = tomcat;
this.autoStart = autoStart;
this.gracefulShutdown = (shutdown == Shutdown.GRACEFUL) ? new GracefulShutdown(tomcat) : null;
// 调用初始化方法
initialize();
}
private void initialize() throws WebServerException {
synchronized (this.monitor) {
// 启动 Tomcat 服务
this.tomcat.start();
// 所有 Tomcat 现场都是守护线程(意味着 main 方法执行结束,线程就关闭了)
// 并且创建一个新的非守护线程运行,等待 tomcat 的 StandSever 结束
startDaemonAwaitThread();
}
}
private void startDaemonAwaitThread() {
Thread awaitThread = new Thread("container-" + (containerCounter.get())) {
@Override
public void run() {
// 等待应用结束,线程退出
TomcatWebServer.this.tomcat.getServer().await();
}
};
awaitThread.setContextClassLoader(getClass().getClassLoader());
awaitThread.setDaemon(false);
awaitThread.start();
}
}
完整调用链
initialize:123, TomcatWebServer (org.springframework.boot.web.embedded.tomcat)
<init>:104, TomcatWebServer (org.springframework.boot.web.embedded.tomcat)
getTomcatWebServer:473, TomcatServletWebServerFactory (org.springframework.boot.web.embedded.tomcat)
getWebServer:206, TomcatServletWebServerFactory (org.springframework.boot.web.embedded.tomcat)
createWebServer:182, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
onRefresh:160, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:577, AbstractApplicationContext (org.springframework.context.support)
refresh:145, ServletWebServerApplicationContext (org.springframework.boot.web.servlet.context)
refresh:730, SpringApplication (org.springframework.boot)
refreshContext:412, SpringApplication (org.springframework.boot)
run:302, SpringApplication (org.springframework.boot)
run:1301, SpringApplication (org.springframework.boot)
run:1290, SpringApplication (org.springframework.boot)
main:25, DemoApplication (com.example.demo)
备注
DispatcherServlet
是在finishBeanFactoryInitialization
实例化所有的单例bean
时加载的,但默认懒加载,没有调用initStrategies
完成映射扫描等。
所以:Spring Boot
首次请求比较慢。
public class DispatcherServlet extends FrameworkServlet {
@Override
protected void onRefresh(ApplicationContext context) {
initStrategies(context);
}
protected void initStrategies(ApplicationContext context) {
initMultipartResolver(context);
initLocaleResolver(context);
initThemeResolver(context);
initHandlerMappings(context);
initHandlerAdapters(context);
initHandlerExceptionResolvers(context);
initRequestToViewNameTranslator(context);
initViewResolvers(context);
initFlashMapManager(context);
}
}
Views: 2,645 · Posted: 2022-01-01
————        END        ————
Give me a Star, Thanks:)
https://github.com/fendoudebb/LiteNote扫描下方二维码关注公众号和小程序↓↓↓
Loading...