Tomcat中LifecycleListener监听器原理分析(观察者模式的运用)
对于读过我Tomcat启动流程的小伙伴们应该清楚,在Host容器启动的过程中会激发HostConfig监听器,从而使得HostConfig可以根据对应的web.xml文件构建Context容器并加入Host中,那么HostConfig监听器到底是如何激发的呢?没有看过启动源码的小伙伴可以移步下文梳理一下过程:Tomcat启动源码流程分析(图解及源码注释) (三)Tomcat启动源码流程分析(图解及
对于读过我Tomcat启动流程的小伙伴们应该清楚,在Host容器启动的过程中会激发HostConfig监听器,从而使得HostConfig可以根据对应的web.xml文件构建Context容器并加入Host中,那么HostConfig监听器到底是如何激发的呢?
没有看过启动源码的小伙伴可以移步下文梳理一下过程:
首先我们要知道无论是Engine,Host,Context,Server等等都是继承于ContainerBase容器,在ContainerBase的start方法中,在调用子容器的start方法后,都会调用一个名为setState(LifecycleState.STARTING)的方法设置当前容器的状态为start状态.
protected synchronized void startInternal() throws LifecycleException {
.....
//获取所有子容器,并交给线程池进行启动(线程池在Engine初始化阶段以及被初始化)
//实际上在StartChild线程启动时,启动子容器的startInternal方法
Container children[] = findChildren();
List<Future<Void>> results = new ArrayList<>();
for (Container child : children) {
results.add(startStopExecutor.submit(new StartChild(child)));
}
MultiThrowable multiThrowable = null;
.....
//设置管线
if (pipeline instanceof Lifecycle) {
((Lifecycle) pipeline).start();
}
//***激发STARTING状态的监听
setState(LifecycleState.STARTING);
// Start our thread
threadStart();
}
那么为什么这个方法能触发监听器的监听呢?我们点进此方法中,
protected synchronized void setState(LifecycleState state) throws LifecycleException {
setStateInternal(state, null, true);
}
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
throws LifecycleException {
....
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
//设置容器的监听器用于start或stop容器
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
可以发现一个名为fireLifecycleEvent(lifecycleEvent, data)的方法,这个方法就非常有意思了,在这个方法中容器调用了当前容器中所有监听器的lifecycleEvent方法.
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
那么当我们随便打开一个监听器,比如HostConfig类,会发现HostConfig类的接口LifecycleListener中存在一个方法lifecycleEvent(LifecycleEvent event),打开HostConfig中该方法的实现,我们可以发现:
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监听器调用了HostConfig.start()方法(注:这里状态的判断用的是Lifecycle接口中的一个String对象START_EVENT,实际上就是字符串"start",而一开始LifeCycleState.STARTING是个枚举类,对应的就是Lifecycle接口中的START_EVENT对象,两者在此时是等价的)
public enum LifecycleState {
....
STARTING(true, Lifecycle.START_EVENT),
....
private final boolean available;
private final String lifecycleEvent;
private LifecycleState(boolean available, String lifecycleEvent) {
this.available = available;
this.lifecycleEvent = lifecycleEvent;
}
public boolean isAvailable() {
return available;
}
public String getLifecycleEvent() {
return lifecycleEvent;
}
}
在让我们来深入理解一下Tomcat容器的构建,所有Tomcat的容器都继承于LifecycleBase抽象类
该抽象类中存在当前容器的状态,以及所有监听器的List集合
/**
* The list of registered LifecycleListeners for event notifications.
*/
private final List<LifecycleListener> lifecycleListeners = new CopyOnWriteArrayList<>();
/**
* The current state of the source component.
*/
private volatile LifecycleState state = LifecycleState.NEW;
同时setState方法是LifecycleBase中的一个确定的方法
protected synchronized void setState(LifecycleState state) throws LifecycleException {
setStateInternal(state, null, true);
}
他调用了LifecycleBase类中的setStateInternal方法
private synchronized void setStateInternal(LifecycleState state, Object data, boolean check)
throws LifecycleException {
....
this.state = state;
String lifecycleEvent = state.getLifecycleEvent();
//设置容器的监听器用于start或stop容器
if (lifecycleEvent != null) {
fireLifecycleEvent(lifecycleEvent, data);
}
}
setStateInternal方法调用了fireLifecycleEvent方法
protected void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(this, type, data);
for (LifecycleListener listener : lifecycleListeners) {
listener.lifecycleEvent(event);
}
}
此方法则如上文中所说的,调用了容器内部所有Listener的lifecycleEvent方法,
由此可以达到当状态改变时,容器能够自主的通过Listener进行操作,实际上这就是观察者模式的一大运用.
更多推荐
所有评论(0)