Tomcat 8中组件生命周期的管理以及事件通知模型

时间:2020-12-24 14:45:44

Tomcat是一个组件化很彻底的应用程序,包括Server、Service、Connector、Container、Engine、Host、Context、Wrapper,各个组件各司其值。Server组件代表Tomcat容器;Service代表容器中一个完整的服务,Server可包含多个Service服务;Service服务由Connector和Container组成,Connector负责接收和转发网络请求,Container则负责处理网络请求;Engine、Host、Context、Wrapper则是具体的Container子类,也一层套一层负责处理请求的各个阶级。其结构如图1所示。
Tomcat 8中组件生命周期的管理以及事件通知模型
图1 Tomcat的整体结构

1、组件生命周期管理
当我们启动Tomcat时,各个组件会依次启动;当我们关闭Tomcat时,各个组件会依次关闭。Tomcat定义了Lifecycle接口来实现组件的统一启动和关闭。
Tomcat 8中组件生命周期的管理以及事件通知模型
图2 Lifecycle的outline

观察Lifecycle接口,发现其定义了组件生命周期需要实现的接口规范。对于Tomcat中的各个组件,需要其实现Lifecycle接口。这样,当前一个组件持有后一个组件时,只需要调用后一个组件实现的start()方法就能完成后一个组件的启动。以StandardServer为类。
Tomcat 8中组件生命周期的管理以及事件通知模型
图3 StandardServer的类层级关系

可以看到Server接口继承自Lifecycle接口,同时StandardServer的实现继承自实现Lifecycle接口的LifecycleBase。观察StandardServer的启动过程,其在启动时会依次调用持有的Service对象的start()方法来启动Service组件。Service组件同样继承自LifecycleBase。

    protected void startInternal() throws LifecycleException {

fireLifecycleEvent(CONFIGURE_START_EVENT, null);
setState(LifecycleState.STARTING);

globalNamingResources.start();

// Start our defined Services
synchronized (servicesLock) {
for (int i = 0; i < services.length; i++) {
services[i].start();
}
}
}

通过以上方式,便完成了Tomcat中各个组件的启动过程。初始化、停止、销毁过程也以同样的方式实现。此处就不再展开。

2、事件通知模型
回头观察图2中Lifecycle,其还定义了事件通知的规范。事件通知其实就是观察者模式。在Tomcat中,完整地定义了事件通知的模型。
在LifecycleBase中,初始化新建了一个LifecycleSupport对象。LifecycleSupport对象负责处理事件通知。由于LifecycleSupport对象是在LifecycleBase中新建的,因此Tomcat中的每一个组件都有自己的LifecycleSupport 来管理事件的观察者。


/**
* Used to handle firing lifecycle events.
* TODO: Consider merging LifecycleSupport into this class.
*/

private final LifecycleSupport lifecycle = new LifecycleSupport(this);

LifecycleSupport 完整的类如下:

public final class LifecycleSupport {

// ----------------------------------------------------------- Constructors

/**
* Construct a new LifecycleSupport object associated with the specified
* Lifecycle component.
*
* @param lifecycle The Lifecycle component that will be the source
* of events that we fire
*/

public LifecycleSupport(Lifecycle lifecycle) {
super();
this.lifecycle = lifecycle;
}


// ----------------------------------------------------- Instance Variables

/**
* The source component for lifecycle events that we will fire.
*/

private final Lifecycle lifecycle;


/**
* The list of registered LifecycleListeners for event notifications.
*/

private final List<LifecycleListener> listeners = new CopyOnWriteArrayList<>();


// --------------------------------------------------------- Public Methods

/**
* Add a lifecycle event listener to this component.
*
* @param listener The listener to add
*/

public void addLifecycleListener(LifecycleListener listener) {
listeners.add(listener);
}


/**
* Get the lifecycle listeners associated with this lifecycle. If this
* Lifecycle has no listeners registered, a zero-length array is returned.
*/

public LifecycleListener[] findLifecycleListeners() {
return listeners.toArray(new LifecycleListener[0]);
}


/**
* Notify all lifecycle event listeners that a particular event has
* occurred for this Container. The default implementation performs
* this notification synchronously using the calling thread.
*
* @param type Event type
* @param data Event data
*/

public void fireLifecycleEvent(String type, Object data) {
LifecycleEvent event = new LifecycleEvent(lifecycle, type, data);
for (LifecycleListener listener : listeners) {
listener.lifecycleEvent(event);
}
}


/**
* Remove a lifecycle event listener from this component.
*
* @param listener The listener to remove
*/

public void removeLifecycleListener(LifecycleListener listener) {
listeners.remove(listener);
}
}

Tomcat同样定义了Listener观察者的规范。观察者中就一个函数需要实现,就是对LifecycleEvent 事件的响应。

public interface LifecycleListener {


/**
* Acknowledge the occurrence of the specified event.
*
* @param event LifecycleEvent that has occurred
*/

public void lifecycleEvent(LifecycleEvent event);


}

LifecycleEvent 是Tomcat中定义的事件规范。事件中监听事件的触发者(即哪个组件触发的)、事件的类型以及事件的数据。LifecycleEvent中包括事件触发需要的所有数据,并传递给Listener进行触发。

public final class LifecycleEvent extends EventObject {

private static final long serialVersionUID = 1L;


// ----------------------------------------------------------- Constructors

/**
* Construct a new LifecycleEvent with the specified parameters.
*
* @param lifecycle Component on which this event occurred
* @param type Event type (required)
* @param data Event data (if any)
*/

public LifecycleEvent(Lifecycle lifecycle, String type, Object data) {

super(lifecycle);
this.type = type;
this.data = data;
}


// ----------------------------------------------------- Instance Variables


/**
* The event data associated with this event.
*/

private final Object data;


/**
* The event type this instance represents.
*/

private final String type;


// ------------------------------------------------------------- Properties


/**
* Return the event data of this event.
*/

public Object getData() {

return (this.data);

}


/**
* Return the Lifecycle on which this event occurred.
*/

public Lifecycle getLifecycle() {

return (Lifecycle) getSource();

}


/**
* Return the event type of this event.
*/

public String getType() {

return (this.type);

}


}

至此,Tomcat就完整地定义了事件触发的模型。对于事件触发,同样以StandardServer为例。观察前文中StandardServer启动过程的代码,发现 fireLifecycleEvent(CONFIGURE_START_EVENT, null) 语句来触发事件。fireLifecycleEvent函数实现如下。

    protected void fireLifecycleEvent(String type, Object data) {
lifecycle.fireLifecycleEvent(type, data);
}

fireLifecycleEvent函数是在LifecycleBase中实现的。lifecycle变量即前文提到的LifecycleSupport对象,通过把事件类型和数据传递给lifecycle,交由lifecycle来封装事件参数并通知相应的监听者。

总结:
在Tomcat组件生命周期的管理中,定义了Lifecycle接口来规范组件生命周期的状态以及行为,各个组件通过实现Lifecycle接口来实现生命周期的统一管理。在事件模型中,定义了LifecycleSupport类来辅助组件行为中的事件通知;定义了LifecycleListener来规范事件监听者;同时定义了LifecycleEvent来包装事件数据。

参考:
【1】http://www.ibm.com/developerworks/cn/java/j-lo-tomcat1/
【2】http://blog.csdn.net/cutesource/article/details/5006062