热部署
热部署和热加载是类似的,都是在不重启Tomcat的情况下,使得应用的最新代码生效。但热部署表示重新部署应用,它的执行主体就不能是Context了,而是Host。
在上一篇《Tomcat源码阅读(三)-热加载》阅读中发现,StandardEngine会开启一个由ContainerBase中定义的守护线程ContainerBackgroundProcessor,来执行当前容器以及所有子容器的backgroundProcess方法,并且一般容器(如StandardContext)在调用完自己的backgroundProcess方法之后,还会调用父类的backgroundProcess,也就是ContainerBase中的backgroundProcess。
ContainerBase中的backgroundProcess方法:
public void backgroundProcess() {
Cluster cluster = getClusterInternal();
if (cluster != null) {
try {
cluster.backgroundProcess();
} catch (Exception e) {
log.warn(sm.getString("containerBase.backgroundProcess.cluster",
cluster), e);
}
}
Realm realm = getRealmInternal();
if (realm != null) {
try {
realm.backgroundProcess();
} catch (Exception e) {
log.warn(sm.getString("containerBase.backgroundProcess.realm", realm), e);
}
}
Valve current = pipeline.getFirst();
while (current != null) {
try {
current.backgroundProcess();
} catch (Exception e) {
log.warn(sm.getString("containerBase.backgroundProcess.valve", current), e);
}
current = current.getNext();
}
// 触发PERIODIC_EVENT事件,而StandardHost有一个HostConfig监听器,就是在此处执行的热部署!
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}
HostConfig#lifecycleEvent:
public void lifecycleEvent(LifecycleEvent event) {
// Identify the host we are associated with
try {
host = (Host) event.getLifecycle();
if (host instanceof StandardHost) {
setCopyXML(((StandardHost) host).isCopyXML());
setDeployXML(((StandardHost) host).isDeployXML());
setUnpackWARs(((StandardHost) host).isUnpackWARs());
setContextClass(((StandardHost) host).getContextClass());
}
} catch (ClassCastException e) {
log.error(sm.getString("hostConfig.cce", event.getLifecycle()), e);
return;
}
// Process the event that has occurred
if (event.getType().equals(Lifecycle.PERIODIC_EVENT)) {
// 此处就是进行热部署
check();
} else if (event.getType().equals(Lifecycle.BEFORE_START_EVENT)) {
beforeStart();
} else if (event.getType().equals(Lifecycle.START_EVENT)) {
start();
} else if (event.getType().equals(Lifecycle.STOP_EVENT)) {
stop();
}
}
HostConfig#check():
protected void check() {
// 如果Context配置了autoDeploy =true
if (host.getAutoDeploy()) {
// Check for resources modification to trigger redeployment
DeployedApplication[] apps =
deployed.values().toArray(new DeployedApplication[0]);
for (int i = 0; i < apps.length; i++) {
if (!isServiced(apps[i].name))
checkResources(apps[i], false);
}
// Check for old versions of applications that can now be undeployed
if (host.getUndeployOldVersions()) {
checkUndeploy();
}
// 此处最终执行热部署
// Hotdeploy applications
deployApps();
}
}