热加载的原理是开启一个后台线程,检查文件变化,变化就重新加载类。
java
// ContainerBackgroundProcessor实现Runnable接口,负责后台处理
protected class ContainerBackgroundProcessor implements Runnable {
@Override
// run方法是主处理逻辑
public void run() {
// 定义变量保存可能出现的异常
Throwable t = null;
// 定义变量保存线程意外死亡的日志信息
String unexpectedDeathMessage = sm.getString("containerBase.backgroundProcess.unexpectedThreadDeath",
Thread.currentThread().getName());
try {
// 循环处理,直到线程结束
while (!threadDone) {
try {
// 每隔一定时间睡眠
Thread.sleep(backgroundProcessorDelay * 1000L);
} catch (InterruptedException e) {
// 忽略中断异常
}
if (!threadDone) {
// 调用processChildren方法处理子容器
processChildren(ContainerBase.this);
}
}
} catch (RuntimeException | Error e) {
// 如果发生异常,保存到t变量并抛出
t = e;
throw e;
} finally {
if (!threadDone) {
// 线程意外死亡打印日志
log.error(unexpectedDeathMessage, t);
}
}
}
// 处理子容器
protected void processChildren(Container container) {
// 保存当前类加载器
ClassLoader originalClassLoader = null;
try {
if (container instanceof Context) {
// Context实例获取类加载器
Loader loader = ((Context) container).getLoader();
// Loader可能为null,忽略
if (loader == null) {
return;
}
// 使用Context的类加载器
originalClassLoader = ((Context) container).bind(false, null);
}
// 处理当前容器
container.backgroundProcess();
// 获取子容器
Container[] children = container.findChildren();
for (Container child : children) {
if (child.getBackgroundProcessorDelay() <= 0) {
// 处理子容器
processChildren(child);
}
}
} catch (Throwable t) {
// 处理异常
ExceptionUtils.handleThrowable(t);
log.error(sm.getString("containerBase.backgroundProcess.error"), t);
} finally {
if (container instanceof Context) {
// 恢复类加载器
((Context) container).unbind(false, originalClassLoader);
}
}
}
}
javapublic void backgroundProcess() {
//1. 执行容器中 Cluster 组件的周期性任务
Cluster cluster = getClusterInternal();
if (cluster != null) {
cluster.backgroundProcess();
}
//2. 执行容器中 Realm 组件的周期性任务
Realm realm = getRealmInternal();
if (realm != null) {
realm.backgroundProcess();
}
//3. 执行容器中 Valve 组件的周期性任务
Valve current = pipeline.getFirst();
while (current != null) {
current.backgroundProcess();
current = current.getNext();
}
//4. 触发容器的 " 周期事件 ",Host 容器的监听器 HostConfig 就靠它来调用
fireLifecycleEvent(Lifecycle.PERIODIC_EVENT, null);
}
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!