tomcat的启动过程就是
脚本->catalina.jar->catalina->standardServer->standardService->standardEngine(Catalina加载web组件)/connector(启动监听请求)
我们发布到tomcat webapp下的项目将会在Engine中加载,下面说说加载过程
先是解析过程,在engine启动时,有一步 findChildren找到Catalina的子容器 StandardHost[localhost],在这里开启了一个线程池 startStopExecutor,这个只有一个核心线程,也就是说我们的StandardHost加载时是串行加载的
StandardHost中的start()方法就从这个线程池开始异步执行,传入了不同的context,可以看成webapp下的项目参数
public void start() {
if (log.isDebugEnabled()) {
log.debug(sm.getString("hostConfig.start"));
}
try {
ObjectName hostON = host.getObjectName();
oname = new ObjectName
(hostON.getDomain() + ":type=Deployer,host=" + host.getName());
Registry.getRegistry(null, null).registerComponent
(this, oname, this.getClass().getName());
} catch (Exception e) {
log.warn(sm.getString("hostConfig.jmx.register", oname), e);
}
if (!host.getAppBaseFile().isDirectory()) {
log.error(sm.getString("hostConfig.appBase", host.getName(),
host.getAppBaseFile().getPath()));
host.setDeployOnStartup(false);
host.setAutoDeploy(false);
}
if (host.getDeployOnStartup()) {
deployApps();
}
}
···
hostConfig/contextConfig 继承了 LifecycleListener ,在项目启动早些时候解析server.xml时 digester中加入了两个监听器
在host和context启动时会触发响应的事件,hostConfig#start方法会启动一个线程池执行的子类DeployDirectory#run方法中调用了deployDirectory方法,向host和context注入子类并启动,前面的组件都是在tomcat中配好的,从这里开始就跟我们的开发部署相关了,在context的 LifecycleListener 启动中configureStart()方法被调用,其中最重要的方法就是webConfig()
protected synchronized void configureStart() {
// Called from StandardContext.start()
if (log.isDebugEnabled()) {
log.debug(sm.getString("contextConfig.start"));
}
if (log.isDebugEnabled()) {
log.debug(sm.getString("contextConfig.xmlSettings",
context.getName(),
Boolean.valueOf(context.getXmlValidation()),
Boolean.valueOf(context.getXmlNamespaceAware())));
}
webConfig();
if (!context.getIgnoreAnnotations()) {
applicationAnnotationsConfig();
}
if (ok) {
validateSecurityRoles();
}
// Configure an authenticator if we need one
if (ok) {
authenticatorConfig();
}
// Dump the contents of this pipeline if requested
if (log.isDebugEnabled()) {
log.debug("Pipeline Configuration:");
Pipeline pipeline = context.getPipeline();
Valve valves[] = null;
if (pipeline != null) {
valves = pipeline.getValves();
}
if (valves != null) {
for (Valve valve : valves) {
log.debug(" " + valve.getClass().getName());
}
}
log.debug("======================");
}
// Make our application available if no problems were encountered
if (ok) {
context.setConfigured(true);
} else {
log.error(sm.getString("contextConfig.unavailable"));
context.setConfigured(false);
}
}
webConfig就是解析context项目的web.xml方法,该方法将系统默认的参数先创建好,然后调用merge方法将项目启动的所有参数加载
在解析web.xml的过程中,会解析listener标签,将其中的监听器注册到context里面
for (String listener : listeners) {
context.addApplicationListener(listener);
}
随后standardContext在 listenerStart()方法中启动了listener,监听器调用了contextInitialized方法,以ContextLoaderListener为例,使用了contextLoader#initWebApplicationContext(event.getServletContext())方法就启动了spring容器
**整个过程就是,tomcat组件的启动,加载配置文件web.xml,从配置文件中获取监听器注册应用监听,事件触发启动spring,然后再spring容器中解析spring-configloaction,加载spring组件**