Tomcat生命周期:创建、初始化、运行、停止、销毁
调用流程
refresh,这里其实是spring的核心代码
这里
这是模板方法,看子类实现
AutoConfiguration有一个ServletWebServerFactoryAutoConfiguration会被加载进来(细节在我的SpringBoot自动装配中有)
所以才会获得tomcat对应的工厂。
进入getWebServer(),有多种实现
细节的创建
创建服务器阶段(套娃)
private void createWebServer() {
//首次进来空的
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
//获取tomcat对应工厂
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
//工厂创建webServer
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
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();
}
/**
* @Description:getWebServer
* @Author: PABLO
* @Date: 2022/5/16 22:34
* @Params: [initializers]
* @Return: org.springframework.boot.web.server.WebServer
**/
public WebServer getWebServer(ServletContextInitializer... initializers) {
if (this.disableMBeanRegistry) {
Registry.disableRegistry();
}
//创建Tomcat
//Tomcat主要组件 server service connector container(engine host context wrapper servlet )
Tomcat tomcat = new Tomcat();
//创建本地临时目录 如C:\Users\29751\AppData\Local\Temp\tomcat.9000.4254207608449001881
File baseDir = (this.baseDirectory != null) ? this.baseDirectory : createTempDir("tomcat");
tomcat.setBaseDir(baseDir.getAbsolutePath());
for (LifecycleListener listener : this.serverLifecycleListeners) {
tomcat.getServer().addLifecycleListener(listener);
}
//创建Connector 默认协议HTTP1.1
Connector connector = new Connector(this.protocol);
connector.setThrowOnFailure(true);
//往Server中的Service添加Connector,这里会创建server和service并绑定,而后在往service中添加connector
tomcat.getService().addConnector(connector);
//自定义tomcat参数
//如extends TomcatEmbeddedServletContainerFactory后重写customizeConnector,设置超时时间、最大连接数等等
//或使用ymal文件配置也可以自定义
/*
* # tomcat
server:
tomcat:
# 最大线程数
max-threads: 5
# 最大连接数
max-connections: 10
port: 9090
* */
customizeConnector(connector);
//tomcat设置Connector
tomcat.setConnector(connector);
//往HOST中设置自动部署标记值,getHost()中会创建engine,而后创建host,建立关联关系
tomcat.getHost().setAutoDeploy(false);
//设置pipeline的阀,处理请求会依次调用每个容器的每个阀,而后会继续调用下一个子容器...
configureEngine(tomcat.getEngine());
for (Connector additionalConnector : this.additionalTomcatConnectors) {
tomcat.getService().addConnector(additionalConnector);
}
//给当前host创建一个context应用
prepareContext(tomcat.getHost(), initializers);
return getTomcatWebServer(tomcat);
}
protected void prepareContext(Host host, ServletContextInitializer[] initializers) {
/**
* @Description: prepareContext
* @Author: PABLO
* @Date: 2022/5/16 23:07
* @Params: [host, initializers]
* @Return: void
**/
File documentRoot = getValidDocumentRoot();
//创建容器,每个HOST中可以有多个context,每个context可以认为是一个应用,即我们的一个项目,webapp大家还记的吧
TomcatEmbeddedContext context = new TomcatEmbeddedContext();
if (documentRoot != null) {
context.setResources(new TomcatServletWebServerFactory.LoaderHidingResourceRoot(context));
}
//设置初始值...
context.setName(getContextPath());
context.setDisplayName(getDisplayName());
context.setPath(getContextPath());
File docBase = (documentRoot != null) ? documentRoot : createTempDir("tomcat-docbase");
context.setDocBase(docBase.getAbsolutePath());
context.addLifecycleListener(new Tomcat.FixContextListener());
context.setParentClassLoader((this.resourceLoader != null) ? this.resourceLoader.getClassLoader()
: ClassUtils.getDefaultClassLoader());
resetDefaultLocaleMapping(context);
addLocaleMappings(context);
try {
context.setCreateUploadTargets(true);
}
catch (NoSuchMethodError ex) {
// Tomcat is < 8.5.39. Continue.
}
configureTldPatterns(context);
WebappLoader loader = new WebappLoader();
loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName());
loader.setDelegate(true);
context.setLoader(loader);
if (isRegisterDefaultServlet()) {
addDefaultServlet(context);
}
if (shouldRegisterJspServlet()) {
addJspServlet(context);
addJasperInitializer(context);
}
context.addLifecycleListener(new TomcatServletWebServerFactory.StaticResourceConfigurer(context));
ServletContextInitializer[] initializersToUse = mergeInitializers(initializers);
//将此context应用放入当前host
host.addChild(context);
//设置一些环境值
configureContext(context, initializersToUse);
//空实现,可扩展
postProcessContext(context);
}
初始化服务器阶段(套娃)
/**
* @Description:容器启动核心代码
* @Author: PABLO
* @Date: 2022/5/17 13:04
* @Params: []
* @Return: void
**/
private void initialize() throws WebServerException {
//控制台打印
logger.info("Tomcat initialized with port(s): " + getPortsDescription(false));
synchronized (this.monitor) {
addInstanceIdToEngineName();
//获取应用this.tomcat.getHost().findChildren())
Context context = findContext();
//添加生命周期监听器
context.addLifecycleListener((event) -> {
if (context.equals(event.getSource()) && Lifecycle.START_EVENT.equals(event.getType())) {
// Remove service connectors so that protocol binding doesn't
// happen when the service is started.
removeServiceConnectors();
}
});
//启动服务器并触发对应监听器
//每个容器都有生命周期,从server开始依次启动
this.tomcat.start();
}
}
//server启动初始状态为NEW
private volatile LifecycleState state = LifecycleState.NEW;
/*
* NEW(false, null), 新生状态
INITIALIZING(false, Lifecycle.BEFORE_INIT_EVENT),初始化中
INITIALIZED(false, Lifecycle.AFTER_INIT_EVENT),初始化完毕
STARTING_PREP(false, Lifecycle.BEFORE_START_EVENT),启动之前
STARTING(true, Lifecycle.START_EVENT),启动中
STARTED(true, Lifecycle.AFTER_START_EVENT),启动完成
STOPPING_PREP(true, Lifecycle.BEFORE_STOP_EVENT),停止之前
STOPPING(false, Lifecycle.STOP_EVENT),正在停止
STOPPED(false, Lifecycle.AFTER_STOP_EVENT),已经停止
DESTROYING(false, Lifecycle.BEFORE_DESTROY_EVENT),正在销毁
DESTROYED(false, Lifecycle.AFTER_DESTROY_EVENT),已经销毁
FAILED(false, null); 失败
* */
/**
* @Description:容器启动核心代码
* @Author: PABLO
* @Date: 2022/5/17 13:04
* @Params: []
* @Return: void
**/
public final synchronized void start() {
if (state.equals(LifecycleState.NEW)) {
//套娃启动操作,每个容器都来一遍
//最先是server-init,状态为new,进行初始化,状态为initializing,进行initInternal();
//会调用server的initInternal()
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
}
/**
* @Description: 初始化server的关键代码,server中初始化service
* @Author: PABLO
* @Date: 2022/5/17 13:12
* @Params: []
* @Return: void
**/
protected void initInternal() throws LifecycleException {
// 初始化Service 核心代码,将service的new状态改为initializing,进行initInternal();
for (Service service : services) {
//会调用service的initInternal()
service.init();
}
}
/**
* @Description: 初始化service的关键代码,如果engine为null,会先初始化engine
* @Author: PABLO
* @Date: 2022/5/17 13:15
* @Params: []
* @Return: void
**/
protected void initInternal() throws LifecycleException {
//初始化engine,这时engine是空的,因为刚刚只初始化到了service
if (engine != null) {
//初始化engine,将new改为initializing,进行initInternal();和server和service不同的是,初始化后会将initializing状态改为initialized
//调用engine的initInternal();
engine.init();
}
//初始化映射器
//web.xml中URL和servlet的映射关系,由该组件处理
mapperListener.init();
// 初始化engine后初始化连接器
//而后初始化protocoHandler endPoint逐层返回到server,整个容器初始化完毕..
synchronized (connectorsLock) {
for (Connector connector : connectors) {
connector.init();
}
}
}
启动服务阶段(套娃)
/**
* @Description: 容器的初始化阶段和启动阶段
* @Author: PABLO
* @Date: 2022/5/17 13:59
* @Params: []
* @Return: void
**/
public final synchronized void start() throws LifecycleException {
//初始化阶段
if (state.equals(LifecycleState.NEW)) {
//套娃初始化
init();
} else if (state.equals(LifecycleState.FAILED)) {
stop();
} else if (!state.equals(LifecycleState.INITIALIZED) &&
!state.equals(LifecycleState.STOPPED)) {
invalidTransition(Lifecycle.BEFORE_START_EVENT);
}
//初始化阶段完毕,进入启动阶段
setStateInternal(LifecycleState.STARTING_PREP, null, false);
//套娃启动
startInternal();
if (state.equals(LifecycleState.FAILED)) {
// This is a 'controlled' failure. The component put itself into the
// FAILED state so call stop() to complete the clean-up.
stop();
} else if (!state.equals(LifecycleState.STARTING)) {
// Shouldn't be necessary but acts as a check that sub-classes are
// doing what they are supposed to.
invalidTransition(Lifecycle.AFTER_START_EVENT);
} else {
setStateInternal(LifecycleState.STARTED, null, false);
}
}
/**
* @Description: 启动容器
* @Author: PABLO
* @Date: 2022/5/17 14:00
* @Params: []
* @Return: void
**/
protected void startInternal() throws LifecycleException {
//设置server状态为starting
setState(LifecycleState.STARTING);
//启动service、 engine
synchronized (servicesLock) {
for (Service service : services) {
service.start();
}
}
}
注意:在onRefresh中只是创建和初始化好了tomcat,但并未启动,在finishRefresh()–>startBeans()中启动